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 "target_signal.h" 22 #include "signal-common.h" 23 #include "linux-user/trace.h" 24 25 struct target_sigcontext { 26 abi_ulong sc_mask; 27 abi_ulong sc_usp; 28 abi_ulong sc_d0; 29 abi_ulong sc_d1; 30 abi_ulong sc_a0; 31 abi_ulong sc_a1; 32 unsigned short sc_sr; 33 abi_ulong sc_pc; 34 }; 35 36 struct target_sigframe 37 { 38 abi_ulong pretcode; 39 int sig; 40 int code; 41 abi_ulong psc; 42 char retcode[8]; 43 abi_ulong extramask[TARGET_NSIG_WORDS-1]; 44 struct target_sigcontext sc; 45 }; 46 47 typedef int target_greg_t; 48 #define TARGET_NGREG 18 49 typedef target_greg_t target_gregset_t[TARGET_NGREG]; 50 51 typedef struct target_fpregset { 52 int f_fpcntl[3]; 53 int f_fpregs[8*3]; 54 } target_fpregset_t; 55 56 struct target_mcontext { 57 int version; 58 target_gregset_t gregs; 59 target_fpregset_t fpregs; 60 }; 61 62 #define TARGET_MCONTEXT_VERSION 2 63 64 struct target_ucontext { 65 abi_ulong tuc_flags; 66 abi_ulong tuc_link; 67 target_stack_t tuc_stack; 68 struct target_mcontext tuc_mcontext; 69 abi_long tuc_filler[80]; 70 target_sigset_t tuc_sigmask; 71 }; 72 73 struct target_rt_sigframe 74 { 75 abi_ulong pretcode; 76 int sig; 77 abi_ulong pinfo; 78 abi_ulong puc; 79 char retcode[8]; 80 struct target_siginfo info; 81 struct target_ucontext uc; 82 }; 83 84 static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env, 85 abi_ulong mask) 86 { 87 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env); 88 __put_user(mask, &sc->sc_mask); 89 __put_user(env->aregs[7], &sc->sc_usp); 90 __put_user(env->dregs[0], &sc->sc_d0); 91 __put_user(env->dregs[1], &sc->sc_d1); 92 __put_user(env->aregs[0], &sc->sc_a0); 93 __put_user(env->aregs[1], &sc->sc_a1); 94 __put_user(sr, &sc->sc_sr); 95 __put_user(env->pc, &sc->sc_pc); 96 } 97 98 static void 99 restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc) 100 { 101 int temp; 102 103 __get_user(env->aregs[7], &sc->sc_usp); 104 __get_user(env->dregs[0], &sc->sc_d0); 105 __get_user(env->dregs[1], &sc->sc_d1); 106 __get_user(env->aregs[0], &sc->sc_a0); 107 __get_user(env->aregs[1], &sc->sc_a1); 108 __get_user(env->pc, &sc->sc_pc); 109 __get_user(temp, &sc->sc_sr); 110 cpu_m68k_set_ccr(env, temp); 111 } 112 113 /* 114 * Determine which stack to use.. 115 */ 116 static inline abi_ulong 117 get_sigframe(struct target_sigaction *ka, CPUM68KState *regs, 118 size_t frame_size) 119 { 120 unsigned long sp; 121 122 sp = regs->aregs[7]; 123 124 /* This is the X/Open sanctioned signal stack switching. */ 125 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { 126 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; 127 } 128 129 return ((sp - frame_size) & -8UL); 130 } 131 132 void setup_frame(int sig, struct target_sigaction *ka, 133 target_sigset_t *set, CPUM68KState *env) 134 { 135 struct target_sigframe *frame; 136 abi_ulong frame_addr; 137 abi_ulong retcode_addr; 138 abi_ulong sc_addr; 139 int i; 140 141 frame_addr = get_sigframe(ka, env, sizeof *frame); 142 trace_user_setup_frame(env, frame_addr); 143 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { 144 goto give_sigsegv; 145 } 146 147 __put_user(sig, &frame->sig); 148 149 sc_addr = frame_addr + offsetof(struct target_sigframe, sc); 150 __put_user(sc_addr, &frame->psc); 151 152 setup_sigcontext(&frame->sc, env, set->sig[0]); 153 154 for(i = 1; i < TARGET_NSIG_WORDS; i++) { 155 __put_user(set->sig[i], &frame->extramask[i - 1]); 156 } 157 158 /* Set up to return from userspace. */ 159 160 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); 161 __put_user(retcode_addr, &frame->pretcode); 162 163 /* moveq #,d0; trap #0 */ 164 165 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), 166 (uint32_t *)(frame->retcode)); 167 168 /* Set up to return from userspace */ 169 170 env->aregs[7] = frame_addr; 171 env->pc = ka->_sa_handler; 172 173 unlock_user_struct(frame, frame_addr, 1); 174 return; 175 176 give_sigsegv: 177 force_sigsegv(sig); 178 } 179 180 static inline void target_rt_save_fpu_state(struct target_ucontext *uc, 181 CPUM68KState *env) 182 { 183 int i; 184 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs; 185 186 __put_user(env->fpcr, &fpregs->f_fpcntl[0]); 187 __put_user(env->fpsr, &fpregs->f_fpcntl[1]); 188 /* fpiar is not emulated */ 189 190 for (i = 0; i < 8; i++) { 191 uint32_t high = env->fregs[i].d.high << 16; 192 __put_user(high, &fpregs->f_fpregs[i * 3]); 193 __put_user(env->fregs[i].d.low, 194 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]); 195 } 196 } 197 198 static inline int target_rt_setup_ucontext(struct target_ucontext *uc, 199 CPUM68KState *env) 200 { 201 target_greg_t *gregs = uc->tuc_mcontext.gregs; 202 uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env); 203 204 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version); 205 __put_user(env->dregs[0], &gregs[0]); 206 __put_user(env->dregs[1], &gregs[1]); 207 __put_user(env->dregs[2], &gregs[2]); 208 __put_user(env->dregs[3], &gregs[3]); 209 __put_user(env->dregs[4], &gregs[4]); 210 __put_user(env->dregs[5], &gregs[5]); 211 __put_user(env->dregs[6], &gregs[6]); 212 __put_user(env->dregs[7], &gregs[7]); 213 __put_user(env->aregs[0], &gregs[8]); 214 __put_user(env->aregs[1], &gregs[9]); 215 __put_user(env->aregs[2], &gregs[10]); 216 __put_user(env->aregs[3], &gregs[11]); 217 __put_user(env->aregs[4], &gregs[12]); 218 __put_user(env->aregs[5], &gregs[13]); 219 __put_user(env->aregs[6], &gregs[14]); 220 __put_user(env->aregs[7], &gregs[15]); 221 __put_user(env->pc, &gregs[16]); 222 __put_user(sr, &gregs[17]); 223 224 target_rt_save_fpu_state(uc, env); 225 226 return 0; 227 } 228 229 static inline void target_rt_restore_fpu_state(CPUM68KState *env, 230 struct target_ucontext *uc) 231 { 232 int i; 233 target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs; 234 uint32_t fpcr; 235 236 __get_user(fpcr, &fpregs->f_fpcntl[0]); 237 cpu_m68k_set_fpcr(env, fpcr); 238 __get_user(env->fpsr, &fpregs->f_fpcntl[1]); 239 /* fpiar is not emulated */ 240 241 for (i = 0; i < 8; i++) { 242 uint32_t high; 243 __get_user(high, &fpregs->f_fpregs[i * 3]); 244 env->fregs[i].d.high = high >> 16; 245 __get_user(env->fregs[i].d.low, 246 (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]); 247 } 248 } 249 250 static inline int target_rt_restore_ucontext(CPUM68KState *env, 251 struct target_ucontext *uc) 252 { 253 int temp; 254 target_greg_t *gregs = uc->tuc_mcontext.gregs; 255 256 __get_user(temp, &uc->tuc_mcontext.version); 257 if (temp != TARGET_MCONTEXT_VERSION) 258 goto badframe; 259 260 /* restore passed registers */ 261 __get_user(env->dregs[0], &gregs[0]); 262 __get_user(env->dregs[1], &gregs[1]); 263 __get_user(env->dregs[2], &gregs[2]); 264 __get_user(env->dregs[3], &gregs[3]); 265 __get_user(env->dregs[4], &gregs[4]); 266 __get_user(env->dregs[5], &gregs[5]); 267 __get_user(env->dregs[6], &gregs[6]); 268 __get_user(env->dregs[7], &gregs[7]); 269 __get_user(env->aregs[0], &gregs[8]); 270 __get_user(env->aregs[1], &gregs[9]); 271 __get_user(env->aregs[2], &gregs[10]); 272 __get_user(env->aregs[3], &gregs[11]); 273 __get_user(env->aregs[4], &gregs[12]); 274 __get_user(env->aregs[5], &gregs[13]); 275 __get_user(env->aregs[6], &gregs[14]); 276 __get_user(env->aregs[7], &gregs[15]); 277 __get_user(env->pc, &gregs[16]); 278 __get_user(temp, &gregs[17]); 279 cpu_m68k_set_ccr(env, temp); 280 281 target_rt_restore_fpu_state(env, uc); 282 283 return 0; 284 285 badframe: 286 return 1; 287 } 288 289 void setup_rt_frame(int sig, struct target_sigaction *ka, 290 target_siginfo_t *info, 291 target_sigset_t *set, CPUM68KState *env) 292 { 293 struct target_rt_sigframe *frame; 294 abi_ulong frame_addr; 295 abi_ulong retcode_addr; 296 abi_ulong info_addr; 297 abi_ulong uc_addr; 298 int err = 0; 299 int i; 300 301 frame_addr = get_sigframe(ka, env, sizeof *frame); 302 trace_user_setup_rt_frame(env, frame_addr); 303 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { 304 goto give_sigsegv; 305 } 306 307 __put_user(sig, &frame->sig); 308 309 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); 310 __put_user(info_addr, &frame->pinfo); 311 312 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); 313 __put_user(uc_addr, &frame->puc); 314 315 tswap_siginfo(&frame->info, info); 316 317 /* Create the ucontext */ 318 319 __put_user(0, &frame->uc.tuc_flags); 320 __put_user(0, &frame->uc.tuc_link); 321 __put_user(target_sigaltstack_used.ss_sp, 322 &frame->uc.tuc_stack.ss_sp); 323 __put_user(sas_ss_flags(env->aregs[7]), 324 &frame->uc.tuc_stack.ss_flags); 325 __put_user(target_sigaltstack_used.ss_size, 326 &frame->uc.tuc_stack.ss_size); 327 err |= target_rt_setup_ucontext(&frame->uc, env); 328 329 if (err) 330 goto give_sigsegv; 331 332 for(i = 0; i < TARGET_NSIG_WORDS; i++) { 333 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); 334 } 335 336 /* Set up to return from userspace. */ 337 338 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); 339 __put_user(retcode_addr, &frame->pretcode); 340 341 /* moveq #,d0; notb d0; trap #0 */ 342 343 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16), 344 (uint32_t *)(frame->retcode + 0)); 345 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4)); 346 347 if (err) 348 goto give_sigsegv; 349 350 /* Set up to return from userspace */ 351 352 env->aregs[7] = frame_addr; 353 env->pc = ka->_sa_handler; 354 355 unlock_user_struct(frame, frame_addr, 1); 356 return; 357 358 give_sigsegv: 359 unlock_user_struct(frame, frame_addr, 1); 360 force_sigsegv(sig); 361 } 362 363 long do_sigreturn(CPUM68KState *env) 364 { 365 struct target_sigframe *frame; 366 abi_ulong frame_addr = env->aregs[7] - 4; 367 target_sigset_t target_set; 368 sigset_t set; 369 int i; 370 371 trace_user_do_sigreturn(env, frame_addr); 372 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 373 goto badframe; 374 375 /* set blocked signals */ 376 377 __get_user(target_set.sig[0], &frame->sc.sc_mask); 378 379 for(i = 1; i < TARGET_NSIG_WORDS; i++) { 380 __get_user(target_set.sig[i], &frame->extramask[i - 1]); 381 } 382 383 target_to_host_sigset_internal(&set, &target_set); 384 set_sigmask(&set); 385 386 /* restore registers */ 387 388 restore_sigcontext(env, &frame->sc); 389 390 unlock_user_struct(frame, frame_addr, 0); 391 return -TARGET_QEMU_ESIGRETURN; 392 393 badframe: 394 force_sig(TARGET_SIGSEGV); 395 return -TARGET_QEMU_ESIGRETURN; 396 } 397 398 long do_rt_sigreturn(CPUM68KState *env) 399 { 400 struct target_rt_sigframe *frame; 401 abi_ulong frame_addr = env->aregs[7] - 4; 402 sigset_t set; 403 404 trace_user_do_rt_sigreturn(env, frame_addr); 405 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) 406 goto badframe; 407 408 target_to_host_sigset(&set, &frame->uc.tuc_sigmask); 409 set_sigmask(&set); 410 411 /* restore registers */ 412 413 if (target_rt_restore_ucontext(env, &frame->uc)) 414 goto badframe; 415 416 if (do_sigaltstack(frame_addr + 417 offsetof(struct target_rt_sigframe, uc.tuc_stack), 418 0, get_sp_from_cpustate(env)) == -EFAULT) 419 goto badframe; 420 421 unlock_user_struct(frame, frame_addr, 0); 422 return -TARGET_QEMU_ESIGRETURN; 423 424 badframe: 425 unlock_user_struct(frame, frame_addr, 0); 426 force_sig(TARGET_SIGSEGV); 427 return -TARGET_QEMU_ESIGRETURN; 428 } 429