xref: /openbmc/qemu/linux-user/arm/signal.c (revision 4f8f199fa569492bb07efee02489f521629d275d)
1  /*
2   *  Emulation of Linux signals
3   *
4   *  Copyright (c) 2003 Fabrice Bellard
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
8   *  the Free Software Foundation; either version 2 of the License, or
9   *  (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *  GNU General Public License for more details.
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18   */
19  #include "qemu/osdep.h"
20  #include "qemu.h"
21  #include "user-internals.h"
22  #include "signal-common.h"
23  #include "linux-user/trace.h"
24  #include "target/arm/cpu-features.h"
25  #include "vdso-asmoffset.h"
26  
27  struct target_sigcontext {
28      abi_ulong trap_no;
29      abi_ulong error_code;
30      abi_ulong oldmask;
31      abi_ulong arm_r0;
32      abi_ulong arm_r1;
33      abi_ulong arm_r2;
34      abi_ulong arm_r3;
35      abi_ulong arm_r4;
36      abi_ulong arm_r5;
37      abi_ulong arm_r6;
38      abi_ulong arm_r7;
39      abi_ulong arm_r8;
40      abi_ulong arm_r9;
41      abi_ulong arm_r10;
42      abi_ulong arm_fp;
43      abi_ulong arm_ip;
44      abi_ulong arm_sp;
45      abi_ulong arm_lr;
46      abi_ulong arm_pc;
47      abi_ulong arm_cpsr;
48      abi_ulong fault_address;
49  };
50  
51  struct target_ucontext {
52      abi_ulong tuc_flags;
53      abi_ulong tuc_link;
54      target_stack_t tuc_stack;
55      struct target_sigcontext tuc_mcontext;
56      target_sigset_t  tuc_sigmask;       /* mask last for extensibility */
57      char __unused[128 - sizeof(target_sigset_t)];
58      abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
59  };
60  
61  struct target_user_vfp {
62      uint64_t fpregs[32];
63      abi_ulong fpscr;
64  };
65  
66  struct target_user_vfp_exc {
67      abi_ulong fpexc;
68      abi_ulong fpinst;
69      abi_ulong fpinst2;
70  };
71  
72  struct target_vfp_sigframe {
73      abi_ulong magic;
74      abi_ulong size;
75      struct target_user_vfp ufp;
76      struct target_user_vfp_exc ufp_exc;
77  } __attribute__((__aligned__(8)));
78  
79  struct target_iwmmxt_sigframe {
80      abi_ulong magic;
81      abi_ulong size;
82      uint64_t regs[16];
83      /* Note that not all the coprocessor control registers are stored here */
84      uint32_t wcssf;
85      uint32_t wcasf;
86      uint32_t wcgr0;
87      uint32_t wcgr1;
88      uint32_t wcgr2;
89      uint32_t wcgr3;
90  } __attribute__((__aligned__(8)));
91  
92  #define TARGET_VFP_MAGIC 0x56465001
93  #define TARGET_IWMMXT_MAGIC 0x12ef842a
94  
95  struct sigframe
96  {
97      struct target_ucontext uc;
98      abi_ulong retcode[4];
99  };
100  
101  struct rt_sigframe
102  {
103      struct target_siginfo info;
104      struct sigframe sig;
105  };
106  
107  QEMU_BUILD_BUG_ON(offsetof(struct sigframe, retcode[3])
108                    != SIGFRAME_RC3_OFFSET);
109  QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, sig.retcode[3])
110                    != RT_SIGFRAME_RC3_OFFSET);
111  
112  static abi_ptr sigreturn_fdpic_tramp;
113  
114  /*
115   * Up to 3 words of 'retcode' in the sigframe are code,
116   * with retcode[3] being used by fdpic for the function descriptor.
117   * This code is not actually executed, but is retained for ABI compat.
118   *
119   * We will create a table of 8 retcode variants in the sigtramp page.
120   * Let each table entry use 3 words.
121   */
122  #define RETCODE_WORDS  3
123  #define RETCODE_BYTES  (RETCODE_WORDS * 4)
124  
125  static inline int valid_user_regs(CPUARMState *regs)
126  {
127      return 1;
128  }
129  
130  static void
131  setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
132                   CPUARMState *env, abi_ulong mask)
133  {
134      __put_user(env->regs[0], &sc->arm_r0);
135      __put_user(env->regs[1], &sc->arm_r1);
136      __put_user(env->regs[2], &sc->arm_r2);
137      __put_user(env->regs[3], &sc->arm_r3);
138      __put_user(env->regs[4], &sc->arm_r4);
139      __put_user(env->regs[5], &sc->arm_r5);
140      __put_user(env->regs[6], &sc->arm_r6);
141      __put_user(env->regs[7], &sc->arm_r7);
142      __put_user(env->regs[8], &sc->arm_r8);
143      __put_user(env->regs[9], &sc->arm_r9);
144      __put_user(env->regs[10], &sc->arm_r10);
145      __put_user(env->regs[11], &sc->arm_fp);
146      __put_user(env->regs[12], &sc->arm_ip);
147      __put_user(env->regs[13], &sc->arm_sp);
148      __put_user(env->regs[14], &sc->arm_lr);
149      __put_user(env->regs[15], &sc->arm_pc);
150      __put_user(cpsr_read(env), &sc->arm_cpsr);
151  
152      __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
153      __put_user(/* current->thread.error_code */ 0, &sc->error_code);
154      __put_user(/* current->thread.address */ 0, &sc->fault_address);
155      __put_user(mask, &sc->oldmask);
156  }
157  
158  static inline abi_ulong
159  get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
160  {
161      unsigned long sp;
162  
163      sp = target_sigsp(get_sp_from_cpustate(regs), ka);
164      /*
165       * ATPCS B01 mandates 8-byte alignment
166       */
167      return (sp - framesize) & ~7;
168  }
169  
170  static void write_arm_sigreturn(uint32_t *rc, int syscall);
171  static void write_arm_fdpic_sigreturn(uint32_t *rc, int ofs);
172  
173  static int
174  setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
175               struct sigframe *frame, abi_ulong sp_addr)
176  {
177      abi_ulong handler = 0;
178      abi_ulong handler_fdpic_GOT = 0;
179      abi_ulong retcode;
180      bool is_fdpic = info_is_fdpic(get_task_state(thread_cpu)->info);
181      bool is_rt = ka->sa_flags & TARGET_SA_SIGINFO;
182      bool thumb;
183  
184      if (is_fdpic) {
185          /* In FDPIC mode, ka->_sa_handler points to a function
186           * descriptor (FD). The first word contains the address of the
187           * handler. The second word contains the value of the PIC
188           * register (r9).  */
189          abi_ulong funcdesc_ptr = ka->_sa_handler;
190          if (get_user_ual(handler, funcdesc_ptr)
191              || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
192              return 1;
193          }
194      } else {
195          handler = ka->_sa_handler;
196      }
197      thumb = handler & 1;
198  
199      uint32_t cpsr = cpsr_read(env);
200  
201      cpsr &= ~CPSR_IT;
202      if (thumb) {
203          cpsr |= CPSR_T;
204      } else {
205          cpsr &= ~CPSR_T;
206      }
207      if (env->cp15.sctlr_el[1] & SCTLR_E0E) {
208          cpsr |= CPSR_E;
209      } else {
210          cpsr &= ~CPSR_E;
211      }
212  
213      /* Our vdso default_sigreturn label is a table of entry points. */
214      retcode = default_sigreturn + (is_fdpic * 2 + is_rt) * 8;
215  
216      /*
217       * Put the sigreturn code on the stack no matter which return
218       * mechanism we use in order to remain ABI compliant.
219       * Because this is about ABI, always use the A32 instructions,
220       * despite the fact that our actual vdso trampoline is T16.
221       */
222      if (is_fdpic) {
223          write_arm_fdpic_sigreturn(frame->retcode,
224                                    is_rt ? RT_SIGFRAME_RC3_OFFSET
225                                          : SIGFRAME_RC3_OFFSET);
226      } else {
227          write_arm_sigreturn(frame->retcode,
228                              is_rt ? TARGET_NR_rt_sigreturn
229                                    : TARGET_NR_sigreturn);
230      }
231  
232      if (ka->sa_flags & TARGET_SA_RESTORER) {
233          if (is_fdpic) {
234              /* Place the function descriptor in slot 3. */
235              __put_user((abi_ulong)ka->sa_restorer, &frame->retcode[3]);
236          } else {
237              retcode = ka->sa_restorer;
238          }
239      }
240  
241      env->regs[0] = usig;
242      if (is_fdpic) {
243          env->regs[9] = handler_fdpic_GOT;
244      }
245      env->regs[13] = sp_addr;
246      env->regs[14] = retcode;
247      env->regs[15] = handler & (thumb ? ~1 : ~3);
248      cpsr_write(env, cpsr, CPSR_IT | CPSR_T | CPSR_E, CPSRWriteByInstr);
249  
250      return 0;
251  }
252  
253  static abi_ulong *setup_sigframe_vfp(abi_ulong *regspace, CPUARMState *env)
254  {
255      int i;
256      struct target_vfp_sigframe *vfpframe;
257      vfpframe = (struct target_vfp_sigframe *)regspace;
258      __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
259      __put_user(sizeof(*vfpframe), &vfpframe->size);
260      for (i = 0; i < 32; i++) {
261          __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
262      }
263      __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
264      __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
265      __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
266      __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
267      return (abi_ulong*)(vfpframe+1);
268  }
269  
270  static abi_ulong *setup_sigframe_iwmmxt(abi_ulong *regspace, CPUARMState *env)
271  {
272      int i;
273      struct target_iwmmxt_sigframe *iwmmxtframe;
274      iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
275      __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
276      __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
277      for (i = 0; i < 16; i++) {
278          __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
279      }
280      __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
281      __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
282      __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
283      __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
284      __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
285      __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
286      return (abi_ulong*)(iwmmxtframe+1);
287  }
288  
289  static void setup_sigframe(struct target_ucontext *uc,
290                             target_sigset_t *set, CPUARMState *env)
291  {
292      struct target_sigaltstack stack;
293      int i;
294      abi_ulong *regspace;
295  
296      /* Clear all the bits of the ucontext we don't use.  */
297      memset(uc, 0, offsetof(struct target_ucontext, tuc_mcontext));
298  
299      memset(&stack, 0, sizeof(stack));
300      target_save_altstack(&stack, env);
301      memcpy(&uc->tuc_stack, &stack, sizeof(stack));
302  
303      setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
304      /* Save coprocessor signal frame.  */
305      regspace = uc->tuc_regspace;
306      if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
307          regspace = setup_sigframe_vfp(regspace, env);
308      }
309      if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
310          regspace = setup_sigframe_iwmmxt(regspace, env);
311      }
312  
313      /* Write terminating magic word */
314      __put_user(0, regspace);
315  
316      for(i = 0; i < TARGET_NSIG_WORDS; i++) {
317          __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
318      }
319  }
320  
321  void setup_frame(int usig, struct target_sigaction *ka,
322                   target_sigset_t *set, CPUARMState *regs)
323  {
324      struct sigframe *frame;
325      abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
326  
327      trace_user_setup_frame(regs, frame_addr);
328      if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
329          goto sigsegv;
330      }
331  
332      setup_sigframe(&frame->uc, set, regs);
333  
334      if (setup_return(regs, ka, usig, frame, frame_addr)) {
335          goto sigsegv;
336      }
337  
338      unlock_user_struct(frame, frame_addr, 1);
339      return;
340  sigsegv:
341      unlock_user_struct(frame, frame_addr, 1);
342      force_sigsegv(usig);
343  }
344  
345  void setup_rt_frame(int usig, struct target_sigaction *ka,
346                      target_siginfo_t *info,
347                      target_sigset_t *set, CPUARMState *env)
348  {
349      struct rt_sigframe *frame;
350      abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
351      abi_ulong info_addr, uc_addr;
352  
353      trace_user_setup_rt_frame(env, frame_addr);
354      if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
355          goto sigsegv;
356      }
357  
358      info_addr = frame_addr + offsetof(struct rt_sigframe, info);
359      uc_addr = frame_addr + offsetof(struct rt_sigframe, sig.uc);
360      frame->info = *info;
361  
362      setup_sigframe(&frame->sig.uc, set, env);
363  
364      if (setup_return(env, ka, usig, &frame->sig, frame_addr)) {
365          goto sigsegv;
366      }
367  
368      env->regs[1] = info_addr;
369      env->regs[2] = uc_addr;
370  
371      unlock_user_struct(frame, frame_addr, 1);
372      return;
373  sigsegv:
374      unlock_user_struct(frame, frame_addr, 1);
375      force_sigsegv(usig);
376  }
377  
378  static int
379  restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
380  {
381      int err = 0;
382      uint32_t cpsr;
383  
384      __get_user(env->regs[0], &sc->arm_r0);
385      __get_user(env->regs[1], &sc->arm_r1);
386      __get_user(env->regs[2], &sc->arm_r2);
387      __get_user(env->regs[3], &sc->arm_r3);
388      __get_user(env->regs[4], &sc->arm_r4);
389      __get_user(env->regs[5], &sc->arm_r5);
390      __get_user(env->regs[6], &sc->arm_r6);
391      __get_user(env->regs[7], &sc->arm_r7);
392      __get_user(env->regs[8], &sc->arm_r8);
393      __get_user(env->regs[9], &sc->arm_r9);
394      __get_user(env->regs[10], &sc->arm_r10);
395      __get_user(env->regs[11], &sc->arm_fp);
396      __get_user(env->regs[12], &sc->arm_ip);
397      __get_user(env->regs[13], &sc->arm_sp);
398      __get_user(env->regs[14], &sc->arm_lr);
399      __get_user(env->regs[15], &sc->arm_pc);
400      __get_user(cpsr, &sc->arm_cpsr);
401      cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
402  
403      err |= !valid_user_regs(env);
404  
405      return err;
406  }
407  
408  static abi_ulong *restore_sigframe_vfp(CPUARMState *env, abi_ulong *regspace)
409  {
410      int i;
411      abi_ulong magic, sz;
412      uint32_t fpscr, fpexc;
413      struct target_vfp_sigframe *vfpframe;
414      vfpframe = (struct target_vfp_sigframe *)regspace;
415  
416      __get_user(magic, &vfpframe->magic);
417      __get_user(sz, &vfpframe->size);
418      if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
419          return 0;
420      }
421      for (i = 0; i < 32; i++) {
422          __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
423      }
424      __get_user(fpscr, &vfpframe->ufp.fpscr);
425      vfp_set_fpscr(env, fpscr);
426      __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
427      /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
428       * and the exception flag is cleared
429       */
430      fpexc |= (1 << 30);
431      fpexc &= ~((1 << 31) | (1 << 28));
432      env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
433      __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
434      __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
435      return (abi_ulong*)(vfpframe + 1);
436  }
437  
438  static abi_ulong *restore_sigframe_iwmmxt(CPUARMState *env,
439                                            abi_ulong *regspace)
440  {
441      int i;
442      abi_ulong magic, sz;
443      struct target_iwmmxt_sigframe *iwmmxtframe;
444      iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
445  
446      __get_user(magic, &iwmmxtframe->magic);
447      __get_user(sz, &iwmmxtframe->size);
448      if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
449          return 0;
450      }
451      for (i = 0; i < 16; i++) {
452          __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
453      }
454      __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
455      __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
456      __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
457      __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
458      __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
459      __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
460      return (abi_ulong*)(iwmmxtframe + 1);
461  }
462  
463  static int do_sigframe_return(CPUARMState *env,
464                                target_ulong context_addr,
465                                struct target_ucontext *uc)
466  {
467      sigset_t host_set;
468      abi_ulong *regspace;
469  
470      target_to_host_sigset(&host_set, &uc->tuc_sigmask);
471      set_sigmask(&host_set);
472  
473      if (restore_sigcontext(env, &uc->tuc_mcontext)) {
474          return 1;
475      }
476  
477      /* Restore coprocessor signal frame */
478      regspace = uc->tuc_regspace;
479      if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
480          regspace = restore_sigframe_vfp(env, regspace);
481          if (!regspace) {
482              return 1;
483          }
484      }
485      if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
486          regspace = restore_sigframe_iwmmxt(env, regspace);
487          if (!regspace) {
488              return 1;
489          }
490      }
491  
492      target_restore_altstack(&uc->tuc_stack, env);
493  
494  #if 0
495      /* Send SIGTRAP if we're single-stepping */
496      if (ptrace_cancel_bpt(current))
497          send_sig(SIGTRAP, current, 1);
498  #endif
499  
500      return 0;
501  }
502  
503  long do_sigreturn(CPUARMState *env)
504  {
505      abi_ulong frame_addr;
506      struct sigframe *frame = NULL;
507  
508      /*
509       * Since we stacked the signal on a 64-bit boundary,
510       * then 'sp' should be word aligned here.  If it's
511       * not, then the user is trying to mess with us.
512       */
513      frame_addr = env->regs[13];
514      trace_user_do_sigreturn(env, frame_addr);
515      if (frame_addr & 7) {
516          goto badframe;
517      }
518  
519      if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
520          goto badframe;
521      }
522  
523      if (do_sigframe_return(env,
524                             frame_addr + offsetof(struct sigframe, uc),
525                             &frame->uc)) {
526          goto badframe;
527      }
528  
529      unlock_user_struct(frame, frame_addr, 0);
530      return -QEMU_ESIGRETURN;
531  
532  badframe:
533      unlock_user_struct(frame, frame_addr, 0);
534      force_sig(TARGET_SIGSEGV);
535      return -QEMU_ESIGRETURN;
536  }
537  
538  long do_rt_sigreturn(CPUARMState *env)
539  {
540      abi_ulong frame_addr;
541      struct rt_sigframe *frame = NULL;
542  
543      /*
544       * Since we stacked the signal on a 64-bit boundary,
545       * then 'sp' should be word aligned here.  If it's
546       * not, then the user is trying to mess with us.
547       */
548      frame_addr = env->regs[13];
549      trace_user_do_rt_sigreturn(env, frame_addr);
550      if (frame_addr & 7) {
551          goto badframe;
552      }
553  
554      if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
555          goto badframe;
556      }
557  
558      if (do_sigframe_return(env,
559                             frame_addr + offsetof(struct rt_sigframe, sig.uc),
560                             &frame->sig.uc)) {
561          goto badframe;
562      }
563  
564      unlock_user_struct(frame, frame_addr, 0);
565      return -QEMU_ESIGRETURN;
566  
567  badframe:
568      unlock_user_struct(frame, frame_addr, 0);
569      force_sig(TARGET_SIGSEGV);
570      return -QEMU_ESIGRETURN;
571  }
572  
573  /*
574   * EABI syscalls pass the number via r7.
575   * Note that the kernel still adds the OABI syscall number to the trap,
576   * presumably for backward ABI compatibility with unwinders.
577   */
578  #define ARM_MOV_R7_IMM(X)       (0xe3a07000 | (X))
579  #define ARM_SWI_SYS(X)          (0xef000000 | (X) | ARM_SYSCALL_BASE)
580  
581  #define THUMB_MOVS_R7_IMM(X)    (0x2700 | (X))
582  #define THUMB_SWI_SYS           0xdf00
583  
584  static void write_arm_sigreturn(uint32_t *rc, int syscall)
585  {
586      __put_user(ARM_MOV_R7_IMM(syscall), rc);
587      __put_user(ARM_SWI_SYS(syscall), rc + 1);
588      /* Wrote 8 of 12 bytes */
589  }
590  
591  static void write_thm_sigreturn(uint32_t *rc, int syscall)
592  {
593      __put_user(THUMB_SWI_SYS << 16 | THUMB_MOVS_R7_IMM(syscall), rc);
594      /* Wrote 4 of 12 bytes */
595  }
596  
597  /*
598   * Stub needed to make sure the FD register (r9) contains the right value.
599   * Use the same instruction sequence as the kernel.
600   */
601  static void write_arm_fdpic_sigreturn(uint32_t *rc, int ofs)
602  {
603      assert(ofs <= 0xfff);
604      __put_user(0xe59d3000 | ofs, rc + 0);   /* ldr r3, [sp, #ofs] */
605      __put_user(0xe8930908, rc + 1);         /* ldm r3, { r3, r9 } */
606      __put_user(0xe12fff13, rc + 2);         /* bx  r3 */
607      /* Wrote 12 of 12 bytes */
608  }
609  
610  static void write_thm_fdpic_sigreturn(void *vrc, int ofs)
611  {
612      uint16_t *rc = vrc;
613  
614      assert((ofs & ~0x3fc) == 0);
615      __put_user(0x9b00 | (ofs >> 2), rc + 0);      /* ldr r3, [sp, #ofs] */
616      __put_user(0xcb0c, rc + 1);                   /* ldm r3, { r2, r3 } */
617      __put_user(0x4699, rc + 2);                   /* mov r9, r3 */
618      __put_user(0x4710, rc + 3);                   /* bx  r2 */
619      /* Wrote 8 of 12 bytes */
620  }
621  
622  void setup_sigtramp(abi_ulong sigtramp_page)
623  {
624      uint32_t total_size = 8 * RETCODE_BYTES;
625      uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, total_size, 0);
626  
627      assert(tramp != NULL);
628  
629      default_sigreturn = sigtramp_page;
630      write_arm_sigreturn(&tramp[0 * RETCODE_WORDS], TARGET_NR_sigreturn);
631      write_thm_sigreturn(&tramp[1 * RETCODE_WORDS], TARGET_NR_sigreturn);
632      write_arm_sigreturn(&tramp[2 * RETCODE_WORDS], TARGET_NR_rt_sigreturn);
633      write_thm_sigreturn(&tramp[3 * RETCODE_WORDS], TARGET_NR_rt_sigreturn);
634  
635      sigreturn_fdpic_tramp = sigtramp_page + 4 * RETCODE_BYTES;
636      write_arm_fdpic_sigreturn(tramp + 4 * RETCODE_WORDS,
637                                offsetof(struct sigframe, retcode[3]));
638      write_thm_fdpic_sigreturn(tramp + 5 * RETCODE_WORDS,
639                                  offsetof(struct sigframe, retcode[3]));
640      write_arm_fdpic_sigreturn(tramp + 6 * RETCODE_WORDS,
641                                offsetof(struct rt_sigframe, sig.retcode[3]));
642      write_thm_fdpic_sigreturn(tramp + 7 * RETCODE_WORDS,
643                                offsetof(struct rt_sigframe, sig.retcode[3]));
644  
645      unlock_user(tramp, sigtramp_page, total_size);
646  }
647