qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

signal.c (19518B)


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