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