qemu

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

signal.c (7358B)


      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     struct target_pt_regs regs;  /* needs to be first */
     27     uint32_t oldmask;
     28 };
     29 
     30 struct target_stack_t {
     31     abi_ulong ss_sp;
     32     int ss_flags;
     33     unsigned int ss_size;
     34 };
     35 
     36 struct target_ucontext {
     37     abi_ulong tuc_flags;
     38     abi_ulong tuc_link;
     39     target_stack_t tuc_stack;
     40     struct target_sigcontext tuc_mcontext;
     41     target_sigset_t tuc_sigmask;
     42 };
     43 
     44 /* Signal frames. */
     45 struct target_rt_sigframe {
     46     target_siginfo_t info;
     47     struct target_ucontext uc;
     48     uint32_t tramp[2];
     49 };
     50 
     51 static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
     52 {
     53     __put_user(env->regs[0], &sc->regs.r0);
     54     __put_user(env->regs[1], &sc->regs.r1);
     55     __put_user(env->regs[2], &sc->regs.r2);
     56     __put_user(env->regs[3], &sc->regs.r3);
     57     __put_user(env->regs[4], &sc->regs.r4);
     58     __put_user(env->regs[5], &sc->regs.r5);
     59     __put_user(env->regs[6], &sc->regs.r6);
     60     __put_user(env->regs[7], &sc->regs.r7);
     61     __put_user(env->regs[8], &sc->regs.r8);
     62     __put_user(env->regs[9], &sc->regs.r9);
     63     __put_user(env->regs[10], &sc->regs.r10);
     64     __put_user(env->regs[11], &sc->regs.r11);
     65     __put_user(env->regs[12], &sc->regs.r12);
     66     __put_user(env->regs[13], &sc->regs.r13);
     67     __put_user(env->regs[14], &sc->regs.r14);
     68     __put_user(env->regs[15], &sc->regs.r15);
     69     __put_user(env->regs[16], &sc->regs.r16);
     70     __put_user(env->regs[17], &sc->regs.r17);
     71     __put_user(env->regs[18], &sc->regs.r18);
     72     __put_user(env->regs[19], &sc->regs.r19);
     73     __put_user(env->regs[20], &sc->regs.r20);
     74     __put_user(env->regs[21], &sc->regs.r21);
     75     __put_user(env->regs[22], &sc->regs.r22);
     76     __put_user(env->regs[23], &sc->regs.r23);
     77     __put_user(env->regs[24], &sc->regs.r24);
     78     __put_user(env->regs[25], &sc->regs.r25);
     79     __put_user(env->regs[26], &sc->regs.r26);
     80     __put_user(env->regs[27], &sc->regs.r27);
     81     __put_user(env->regs[28], &sc->regs.r28);
     82     __put_user(env->regs[29], &sc->regs.r29);
     83     __put_user(env->regs[30], &sc->regs.r30);
     84     __put_user(env->regs[31], &sc->regs.r31);
     85     __put_user(env->pc, &sc->regs.pc);
     86 }
     87 
     88 static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
     89 {
     90     __get_user(env->regs[0], &sc->regs.r0);
     91     __get_user(env->regs[1], &sc->regs.r1);
     92     __get_user(env->regs[2], &sc->regs.r2);
     93     __get_user(env->regs[3], &sc->regs.r3);
     94     __get_user(env->regs[4], &sc->regs.r4);
     95     __get_user(env->regs[5], &sc->regs.r5);
     96     __get_user(env->regs[6], &sc->regs.r6);
     97     __get_user(env->regs[7], &sc->regs.r7);
     98     __get_user(env->regs[8], &sc->regs.r8);
     99     __get_user(env->regs[9], &sc->regs.r9);
    100     __get_user(env->regs[10], &sc->regs.r10);
    101     __get_user(env->regs[11], &sc->regs.r11);
    102     __get_user(env->regs[12], &sc->regs.r12);
    103     __get_user(env->regs[13], &sc->regs.r13);
    104     __get_user(env->regs[14], &sc->regs.r14);
    105     __get_user(env->regs[15], &sc->regs.r15);
    106     __get_user(env->regs[16], &sc->regs.r16);
    107     __get_user(env->regs[17], &sc->regs.r17);
    108     __get_user(env->regs[18], &sc->regs.r18);
    109     __get_user(env->regs[19], &sc->regs.r19);
    110     __get_user(env->regs[20], &sc->regs.r20);
    111     __get_user(env->regs[21], &sc->regs.r21);
    112     __get_user(env->regs[22], &sc->regs.r22);
    113     __get_user(env->regs[23], &sc->regs.r23);
    114     __get_user(env->regs[24], &sc->regs.r24);
    115     __get_user(env->regs[25], &sc->regs.r25);
    116     __get_user(env->regs[26], &sc->regs.r26);
    117     __get_user(env->regs[27], &sc->regs.r27);
    118     __get_user(env->regs[28], &sc->regs.r28);
    119     __get_user(env->regs[29], &sc->regs.r29);
    120     __get_user(env->regs[30], &sc->regs.r30);
    121     __get_user(env->regs[31], &sc->regs.r31);
    122     __get_user(env->pc, &sc->regs.pc);
    123 }
    124 
    125 static abi_ulong get_sigframe(struct target_sigaction *ka,
    126                               CPUMBState *env, int frame_size)
    127 {
    128     abi_ulong sp = env->regs[1];
    129 
    130     sp = target_sigsp(sp, ka);
    131 
    132     return ((sp - frame_size) & -8UL);
    133 }
    134 
    135 void setup_rt_frame(int sig, struct target_sigaction *ka,
    136                     target_siginfo_t *info,
    137                     target_sigset_t *set, CPUMBState *env)
    138 {
    139     struct target_rt_sigframe *frame;
    140     abi_ulong frame_addr;
    141 
    142     frame_addr = get_sigframe(ka, env, sizeof *frame);
    143     trace_user_setup_rt_frame(env, frame_addr);
    144 
    145     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
    146         force_sigsegv(sig);
    147         return;
    148     }
    149 
    150     tswap_siginfo(&frame->info, info);
    151 
    152     __put_user(0, &frame->uc.tuc_flags);
    153     __put_user(0, &frame->uc.tuc_link);
    154 
    155     target_save_altstack(&frame->uc.tuc_stack, env);
    156     setup_sigcontext(&frame->uc.tuc_mcontext, env);
    157 
    158     for (int i = 0; i < TARGET_NSIG_WORDS; i++) {
    159         __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
    160     }
    161 
    162     /* Kernel does not use SA_RESTORER. */
    163 
    164     /*
    165      * Return from sighandler will jump to the tramp.
    166      * Negative 8 offset because return is rtsd r15, 8
    167      */
    168     env->regs[15] = default_rt_sigreturn - 8;
    169 
    170     /* Set up registers for signal handler */
    171     env->regs[1] = frame_addr;
    172 
    173     /* Signal handler args: */
    174     env->regs[5] = sig;
    175     env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, info);
    176     env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, uc);
    177 
    178     /* Offset to handle microblaze rtid r14, 0 */
    179     env->pc = (unsigned long)ka->_sa_handler;
    180 
    181     unlock_user_struct(frame, frame_addr, 1);
    182 }
    183 
    184 
    185 long do_sigreturn(CPUMBState *env)
    186 {
    187     return -TARGET_ENOSYS;
    188 }
    189 
    190 long do_rt_sigreturn(CPUMBState *env)
    191 {
    192     struct target_rt_sigframe *frame = NULL;
    193     abi_ulong frame_addr = env->regs[1];
    194     sigset_t set;
    195 
    196     trace_user_do_rt_sigreturn(env, frame_addr);
    197 
    198     if  (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
    199         goto badframe;
    200     }
    201 
    202     target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
    203     set_sigmask(&set);
    204 
    205     restore_sigcontext(&frame->uc.tuc_mcontext, env);
    206 
    207     target_restore_altstack(&frame->uc.tuc_stack, env);
    208 
    209     unlock_user_struct(frame, frame_addr, 0);
    210     return -QEMU_ESIGRETURN;
    211 
    212  badframe:
    213     unlock_user_struct(frame, frame_addr, 0);
    214     force_sig(TARGET_SIGSEGV);
    215     return -QEMU_ESIGRETURN;
    216 }
    217 
    218 void setup_sigtramp(abi_ulong sigtramp_page)
    219 {
    220     uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
    221     assert(tramp != NULL);
    222 
    223     /*
    224      * addi r12, r0, __NR_rt_sigreturn
    225      * brki r14, 0x8
    226      */
    227     __put_user(0x31800000U | TARGET_NR_rt_sigreturn, tramp);
    228     __put_user(0xb9cc0008U, tramp + 1);
    229 
    230     default_rt_sigreturn = sigtramp_page;
    231     unlock_user(tramp, sigtramp_page, 8);
    232 }