1 /* 2 * linux/arch/m68k/kernel/signal.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 9 */ 10 11 /* 12 * Linux/m68k support by Hamish Macdonald 13 * 14 * 68060 fixes by Jesper Skov 15 * 16 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab 17 * 18 * mathemu support by Roman Zippel 19 * (Note: fpstate in the signal context is completely ignored for the emulator 20 * and the internal floating point format is put on stack) 21 */ 22 23 /* 24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on 25 * Atari :-) Current limitation: Only one sigstack can be active at one time. 26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack, 27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested 28 * signal handlers! 29 */ 30 31 #include <linux/sched.h> 32 #include <linux/mm.h> 33 #include <linux/kernel.h> 34 #include <linux/signal.h> 35 #include <linux/syscalls.h> 36 #include <linux/errno.h> 37 #include <linux/wait.h> 38 #include <linux/ptrace.h> 39 #include <linux/unistd.h> 40 #include <linux/stddef.h> 41 #include <linux/highuid.h> 42 #include <linux/personality.h> 43 #include <linux/tty.h> 44 #include <linux/binfmts.h> 45 46 #include <asm/setup.h> 47 #include <asm/uaccess.h> 48 #include <asm/pgtable.h> 49 #include <asm/traps.h> 50 #include <asm/ucontext.h> 51 52 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 53 54 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); 55 56 const int frame_extra_sizes[16] = { 57 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ 58 [2] = sizeof(((struct frame *)0)->un.fmt2), 59 [3] = sizeof(((struct frame *)0)->un.fmt3), 60 [4] = sizeof(((struct frame *)0)->un.fmt4), 61 [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */ 62 [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */ 63 [7] = sizeof(((struct frame *)0)->un.fmt7), 64 [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */ 65 [9] = sizeof(((struct frame *)0)->un.fmt9), 66 [10] = sizeof(((struct frame *)0)->un.fmta), 67 [11] = sizeof(((struct frame *)0)->un.fmtb), 68 [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */ 69 [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */ 70 [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */ 71 [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */ 72 }; 73 74 /* 75 * Atomically swap in the new signal mask, and wait for a signal. 76 */ 77 asmlinkage int do_sigsuspend(struct pt_regs *regs) 78 { 79 old_sigset_t mask = regs->d3; 80 sigset_t saveset; 81 82 mask &= _BLOCKABLE; 83 saveset = current->blocked; 84 siginitset(¤t->blocked, mask); 85 recalc_sigpending(); 86 87 regs->d0 = -EINTR; 88 while (1) { 89 current->state = TASK_INTERRUPTIBLE; 90 schedule(); 91 if (do_signal(&saveset, regs)) 92 return -EINTR; 93 } 94 } 95 96 asmlinkage int 97 do_rt_sigsuspend(struct pt_regs *regs) 98 { 99 sigset_t __user *unewset = (sigset_t __user *)regs->d1; 100 size_t sigsetsize = (size_t)regs->d2; 101 sigset_t saveset, newset; 102 103 /* XXX: Don't preclude handling different sized sigset_t's. */ 104 if (sigsetsize != sizeof(sigset_t)) 105 return -EINVAL; 106 107 if (copy_from_user(&newset, unewset, sizeof(newset))) 108 return -EFAULT; 109 sigdelsetmask(&newset, ~_BLOCKABLE); 110 111 saveset = current->blocked; 112 current->blocked = newset; 113 recalc_sigpending(); 114 115 regs->d0 = -EINTR; 116 while (1) { 117 current->state = TASK_INTERRUPTIBLE; 118 schedule(); 119 if (do_signal(&saveset, regs)) 120 return -EINTR; 121 } 122 } 123 124 asmlinkage int 125 sys_sigaction(int sig, const struct old_sigaction __user *act, 126 struct old_sigaction __user *oact) 127 { 128 struct k_sigaction new_ka, old_ka; 129 int ret; 130 131 if (act) { 132 old_sigset_t mask; 133 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 134 __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 135 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) 136 return -EFAULT; 137 __get_user(new_ka.sa.sa_flags, &act->sa_flags); 138 __get_user(mask, &act->sa_mask); 139 siginitset(&new_ka.sa.sa_mask, mask); 140 } 141 142 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 143 144 if (!ret && oact) { 145 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 146 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 147 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) 148 return -EFAULT; 149 __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 150 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); 151 } 152 153 return ret; 154 } 155 156 asmlinkage int 157 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 158 { 159 return do_sigaltstack(uss, uoss, rdusp()); 160 } 161 162 163 /* 164 * Do a signal return; undo the signal stack. 165 * 166 * Keep the return code on the stack quadword aligned! 167 * That makes the cache flush below easier. 168 */ 169 170 struct sigframe 171 { 172 char __user *pretcode; 173 int sig; 174 int code; 175 struct sigcontext __user *psc; 176 char retcode[8]; 177 unsigned long extramask[_NSIG_WORDS-1]; 178 struct sigcontext sc; 179 }; 180 181 struct rt_sigframe 182 { 183 char __user *pretcode; 184 int sig; 185 struct siginfo __user *pinfo; 186 void __user *puc; 187 char retcode[8]; 188 struct siginfo info; 189 struct ucontext uc; 190 }; 191 192 193 static unsigned char fpu_version; /* version number of fpu, set by setup_frame */ 194 195 static inline int restore_fpu_state(struct sigcontext *sc) 196 { 197 int err = 1; 198 199 if (FPU_IS_EMU) { 200 /* restore registers */ 201 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12); 202 memcpy(current->thread.fp, sc->sc_fpregs, 24); 203 return 0; 204 } 205 206 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { 207 /* Verify the frame format. */ 208 if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) 209 goto out; 210 if (CPU_IS_020_OR_030) { 211 if (m68k_fputype & FPU_68881 && 212 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4)) 213 goto out; 214 if (m68k_fputype & FPU_68882 && 215 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4)) 216 goto out; 217 } else if (CPU_IS_040) { 218 if (!(sc->sc_fpstate[1] == 0x00 || 219 sc->sc_fpstate[1] == 0x28 || 220 sc->sc_fpstate[1] == 0x60)) 221 goto out; 222 } else if (CPU_IS_060) { 223 if (!(sc->sc_fpstate[3] == 0x00 || 224 sc->sc_fpstate[3] == 0x60 || 225 sc->sc_fpstate[3] == 0xe0)) 226 goto out; 227 } else 228 goto out; 229 230 __asm__ volatile (".chip 68k/68881\n\t" 231 "fmovemx %0,%%fp0-%%fp1\n\t" 232 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" 233 ".chip 68k" 234 : /* no outputs */ 235 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); 236 } 237 __asm__ volatile (".chip 68k/68881\n\t" 238 "frestore %0\n\t" 239 ".chip 68k" : : "m" (*sc->sc_fpstate)); 240 err = 0; 241 242 out: 243 return err; 244 } 245 246 #define FPCONTEXT_SIZE 216 247 #define uc_fpstate uc_filler[0] 248 #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] 249 #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] 250 251 static inline int rt_restore_fpu_state(struct ucontext __user *uc) 252 { 253 unsigned char fpstate[FPCONTEXT_SIZE]; 254 int context_size = CPU_IS_060 ? 8 : 0; 255 fpregset_t fpregs; 256 int err = 1; 257 258 if (FPU_IS_EMU) { 259 /* restore fpu control register */ 260 if (__copy_from_user(current->thread.fpcntl, 261 uc->uc_mcontext.fpregs.f_fpcntl, 12)) 262 goto out; 263 /* restore all other fpu register */ 264 if (__copy_from_user(current->thread.fp, 265 uc->uc_mcontext.fpregs.f_fpregs, 96)) 266 goto out; 267 return 0; 268 } 269 270 if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) 271 goto out; 272 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { 273 if (!CPU_IS_060) 274 context_size = fpstate[1]; 275 /* Verify the frame format. */ 276 if (!CPU_IS_060 && (fpstate[0] != fpu_version)) 277 goto out; 278 if (CPU_IS_020_OR_030) { 279 if (m68k_fputype & FPU_68881 && 280 !(context_size == 0x18 || context_size == 0xb4)) 281 goto out; 282 if (m68k_fputype & FPU_68882 && 283 !(context_size == 0x38 || context_size == 0xd4)) 284 goto out; 285 } else if (CPU_IS_040) { 286 if (!(context_size == 0x00 || 287 context_size == 0x28 || 288 context_size == 0x60)) 289 goto out; 290 } else if (CPU_IS_060) { 291 if (!(fpstate[3] == 0x00 || 292 fpstate[3] == 0x60 || 293 fpstate[3] == 0xe0)) 294 goto out; 295 } else 296 goto out; 297 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, 298 sizeof(fpregs))) 299 goto out; 300 __asm__ volatile (".chip 68k/68881\n\t" 301 "fmovemx %0,%%fp0-%%fp7\n\t" 302 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" 303 ".chip 68k" 304 : /* no outputs */ 305 : "m" (*fpregs.f_fpregs), 306 "m" (*fpregs.f_fpcntl)); 307 } 308 if (context_size && 309 __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, 310 context_size)) 311 goto out; 312 __asm__ volatile (".chip 68k/68881\n\t" 313 "frestore %0\n\t" 314 ".chip 68k" : : "m" (*fpstate)); 315 err = 0; 316 317 out: 318 return err; 319 } 320 321 static inline int 322 restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, 323 int *pd0) 324 { 325 int fsize, formatvec; 326 struct sigcontext context; 327 int err; 328 329 /* Always make any pending restarted system calls return -EINTR */ 330 current_thread_info()->restart_block.fn = do_no_restart_syscall; 331 332 /* get previous context */ 333 if (copy_from_user(&context, usc, sizeof(context))) 334 goto badframe; 335 336 /* restore passed registers */ 337 regs->d1 = context.sc_d1; 338 regs->a0 = context.sc_a0; 339 regs->a1 = context.sc_a1; 340 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); 341 regs->pc = context.sc_pc; 342 regs->orig_d0 = -1; /* disable syscall checks */ 343 wrusp(context.sc_usp); 344 formatvec = context.sc_formatvec; 345 regs->format = formatvec >> 12; 346 regs->vector = formatvec & 0xfff; 347 348 err = restore_fpu_state(&context); 349 350 fsize = frame_extra_sizes[regs->format]; 351 if (fsize < 0) { 352 /* 353 * user process trying to return with weird frame format 354 */ 355 #ifdef DEBUG 356 printk("user process returning with weird frame format\n"); 357 #endif 358 goto badframe; 359 } 360 361 /* OK. Make room on the supervisor stack for the extra junk, 362 * if necessary. 363 */ 364 365 if (fsize) { 366 struct switch_stack *sw = (struct switch_stack *)regs - 1; 367 regs->d0 = context.sc_d0; 368 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) 369 __asm__ __volatile__ 370 (" movel %0,%/a0\n\t" 371 " subl %1,%/a0\n\t" /* make room on stack */ 372 " movel %/a0,%/sp\n\t" /* set stack pointer */ 373 /* move switch_stack and pt_regs */ 374 "1: movel %0@+,%/a0@+\n\t" 375 " dbra %2,1b\n\t" 376 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ 377 " lsrl #2,%1\n\t" 378 " subql #1,%1\n\t" 379 "2: movesl %4@+,%2\n\t" 380 "3: movel %2,%/a0@+\n\t" 381 " dbra %1,2b\n\t" 382 " bral ret_from_signal\n" 383 "4:\n" 384 ".section __ex_table,\"a\"\n" 385 " .align 4\n" 386 " .long 2b,4b\n" 387 " .long 3b,4b\n" 388 ".previous" 389 : /* no outputs, it doesn't ever return */ 390 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), 391 "n" (frame_offset), "a" (fp) 392 : "a0"); 393 #undef frame_offset 394 /* 395 * If we ever get here an exception occurred while 396 * building the above stack-frame. 397 */ 398 goto badframe; 399 } 400 401 *pd0 = context.sc_d0; 402 return err; 403 404 badframe: 405 return 1; 406 } 407 408 static inline int 409 rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, 410 struct ucontext __user *uc, int *pd0) 411 { 412 int fsize, temp; 413 greg_t __user *gregs = uc->uc_mcontext.gregs; 414 unsigned long usp; 415 int err; 416 417 /* Always make any pending restarted system calls return -EINTR */ 418 current_thread_info()->restart_block.fn = do_no_restart_syscall; 419 420 err = __get_user(temp, &uc->uc_mcontext.version); 421 if (temp != MCONTEXT_VERSION) 422 goto badframe; 423 /* restore passed registers */ 424 err |= __get_user(regs->d0, &gregs[0]); 425 err |= __get_user(regs->d1, &gregs[1]); 426 err |= __get_user(regs->d2, &gregs[2]); 427 err |= __get_user(regs->d3, &gregs[3]); 428 err |= __get_user(regs->d4, &gregs[4]); 429 err |= __get_user(regs->d5, &gregs[5]); 430 err |= __get_user(sw->d6, &gregs[6]); 431 err |= __get_user(sw->d7, &gregs[7]); 432 err |= __get_user(regs->a0, &gregs[8]); 433 err |= __get_user(regs->a1, &gregs[9]); 434 err |= __get_user(regs->a2, &gregs[10]); 435 err |= __get_user(sw->a3, &gregs[11]); 436 err |= __get_user(sw->a4, &gregs[12]); 437 err |= __get_user(sw->a5, &gregs[13]); 438 err |= __get_user(sw->a6, &gregs[14]); 439 err |= __get_user(usp, &gregs[15]); 440 wrusp(usp); 441 err |= __get_user(regs->pc, &gregs[16]); 442 err |= __get_user(temp, &gregs[17]); 443 regs->sr = (regs->sr & 0xff00) | (temp & 0xff); 444 regs->orig_d0 = -1; /* disable syscall checks */ 445 err |= __get_user(temp, &uc->uc_formatvec); 446 regs->format = temp >> 12; 447 regs->vector = temp & 0xfff; 448 449 err |= rt_restore_fpu_state(uc); 450 451 if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) 452 goto badframe; 453 454 fsize = frame_extra_sizes[regs->format]; 455 if (fsize < 0) { 456 /* 457 * user process trying to return with weird frame format 458 */ 459 #ifdef DEBUG 460 printk("user process returning with weird frame format\n"); 461 #endif 462 goto badframe; 463 } 464 465 /* OK. Make room on the supervisor stack for the extra junk, 466 * if necessary. 467 */ 468 469 if (fsize) { 470 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) 471 __asm__ __volatile__ 472 (" movel %0,%/a0\n\t" 473 " subl %1,%/a0\n\t" /* make room on stack */ 474 " movel %/a0,%/sp\n\t" /* set stack pointer */ 475 /* move switch_stack and pt_regs */ 476 "1: movel %0@+,%/a0@+\n\t" 477 " dbra %2,1b\n\t" 478 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ 479 " lsrl #2,%1\n\t" 480 " subql #1,%1\n\t" 481 "2: movesl %4@+,%2\n\t" 482 "3: movel %2,%/a0@+\n\t" 483 " dbra %1,2b\n\t" 484 " bral ret_from_signal\n" 485 "4:\n" 486 ".section __ex_table,\"a\"\n" 487 " .align 4\n" 488 " .long 2b,4b\n" 489 " .long 3b,4b\n" 490 ".previous" 491 : /* no outputs, it doesn't ever return */ 492 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), 493 "n" (frame_offset), "a" (&uc->uc_extra) 494 : "a0"); 495 #undef frame_offset 496 /* 497 * If we ever get here an exception occurred while 498 * building the above stack-frame. 499 */ 500 goto badframe; 501 } 502 503 *pd0 = regs->d0; 504 return err; 505 506 badframe: 507 return 1; 508 } 509 510 asmlinkage int do_sigreturn(unsigned long __unused) 511 { 512 struct switch_stack *sw = (struct switch_stack *) &__unused; 513 struct pt_regs *regs = (struct pt_regs *) (sw + 1); 514 unsigned long usp = rdusp(); 515 struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); 516 sigset_t set; 517 int d0; 518 519 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 520 goto badframe; 521 if (__get_user(set.sig[0], &frame->sc.sc_mask) || 522 (_NSIG_WORDS > 1 && 523 __copy_from_user(&set.sig[1], &frame->extramask, 524 sizeof(frame->extramask)))) 525 goto badframe; 526 527 sigdelsetmask(&set, ~_BLOCKABLE); 528 current->blocked = set; 529 recalc_sigpending(); 530 531 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) 532 goto badframe; 533 return d0; 534 535 badframe: 536 force_sig(SIGSEGV, current); 537 return 0; 538 } 539 540 asmlinkage int do_rt_sigreturn(unsigned long __unused) 541 { 542 struct switch_stack *sw = (struct switch_stack *) &__unused; 543 struct pt_regs *regs = (struct pt_regs *) (sw + 1); 544 unsigned long usp = rdusp(); 545 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); 546 sigset_t set; 547 int d0; 548 549 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 550 goto badframe; 551 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 552 goto badframe; 553 554 sigdelsetmask(&set, ~_BLOCKABLE); 555 current->blocked = set; 556 recalc_sigpending(); 557 558 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) 559 goto badframe; 560 return d0; 561 562 badframe: 563 force_sig(SIGSEGV, current); 564 return 0; 565 } 566 567 /* 568 * Set up a signal frame. 569 */ 570 571 static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) 572 { 573 if (FPU_IS_EMU) { 574 /* save registers */ 575 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); 576 memcpy(sc->sc_fpregs, current->thread.fp, 24); 577 return; 578 } 579 580 __asm__ volatile (".chip 68k/68881\n\t" 581 "fsave %0\n\t" 582 ".chip 68k" 583 : : "m" (*sc->sc_fpstate) : "memory"); 584 585 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { 586 fpu_version = sc->sc_fpstate[0]; 587 if (CPU_IS_020_OR_030 && 588 regs->vector >= (VEC_FPBRUC * 4) && 589 regs->vector <= (VEC_FPNAN * 4)) { 590 /* Clear pending exception in 68882 idle frame */ 591 if (*(unsigned short *) sc->sc_fpstate == 0x1f38) 592 sc->sc_fpstate[0x38] |= 1 << 3; 593 } 594 __asm__ volatile (".chip 68k/68881\n\t" 595 "fmovemx %%fp0-%%fp1,%0\n\t" 596 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" 597 ".chip 68k" 598 : "=m" (*sc->sc_fpregs), 599 "=m" (*sc->sc_fpcntl) 600 : /* no inputs */ 601 : "memory"); 602 } 603 } 604 605 static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) 606 { 607 unsigned char fpstate[FPCONTEXT_SIZE]; 608 int context_size = CPU_IS_060 ? 8 : 0; 609 int err = 0; 610 611 if (FPU_IS_EMU) { 612 /* save fpu control register */ 613 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, 614 current->thread.fpcntl, 12); 615 /* save all other fpu register */ 616 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, 617 current->thread.fp, 96); 618 return err; 619 } 620 621 __asm__ volatile (".chip 68k/68881\n\t" 622 "fsave %0\n\t" 623 ".chip 68k" 624 : : "m" (*fpstate) : "memory"); 625 626 err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); 627 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { 628 fpregset_t fpregs; 629 if (!CPU_IS_060) 630 context_size = fpstate[1]; 631 fpu_version = fpstate[0]; 632 if (CPU_IS_020_OR_030 && 633 regs->vector >= (VEC_FPBRUC * 4) && 634 regs->vector <= (VEC_FPNAN * 4)) { 635 /* Clear pending exception in 68882 idle frame */ 636 if (*(unsigned short *) fpstate == 0x1f38) 637 fpstate[0x38] |= 1 << 3; 638 } 639 __asm__ volatile (".chip 68k/68881\n\t" 640 "fmovemx %%fp0-%%fp7,%0\n\t" 641 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" 642 ".chip 68k" 643 : "=m" (*fpregs.f_fpregs), 644 "=m" (*fpregs.f_fpcntl) 645 : /* no inputs */ 646 : "memory"); 647 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, 648 sizeof(fpregs)); 649 } 650 if (context_size) 651 err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, 652 context_size); 653 return err; 654 } 655 656 static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, 657 unsigned long mask) 658 { 659 sc->sc_mask = mask; 660 sc->sc_usp = rdusp(); 661 sc->sc_d0 = regs->d0; 662 sc->sc_d1 = regs->d1; 663 sc->sc_a0 = regs->a0; 664 sc->sc_a1 = regs->a1; 665 sc->sc_sr = regs->sr; 666 sc->sc_pc = regs->pc; 667 sc->sc_formatvec = regs->format << 12 | regs->vector; 668 save_fpu_state(sc, regs); 669 } 670 671 static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) 672 { 673 struct switch_stack *sw = (struct switch_stack *)regs - 1; 674 greg_t __user *gregs = uc->uc_mcontext.gregs; 675 int err = 0; 676 677 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); 678 err |= __put_user(regs->d0, &gregs[0]); 679 err |= __put_user(regs->d1, &gregs[1]); 680 err |= __put_user(regs->d2, &gregs[2]); 681 err |= __put_user(regs->d3, &gregs[3]); 682 err |= __put_user(regs->d4, &gregs[4]); 683 err |= __put_user(regs->d5, &gregs[5]); 684 err |= __put_user(sw->d6, &gregs[6]); 685 err |= __put_user(sw->d7, &gregs[7]); 686 err |= __put_user(regs->a0, &gregs[8]); 687 err |= __put_user(regs->a1, &gregs[9]); 688 err |= __put_user(regs->a2, &gregs[10]); 689 err |= __put_user(sw->a3, &gregs[11]); 690 err |= __put_user(sw->a4, &gregs[12]); 691 err |= __put_user(sw->a5, &gregs[13]); 692 err |= __put_user(sw->a6, &gregs[14]); 693 err |= __put_user(rdusp(), &gregs[15]); 694 err |= __put_user(regs->pc, &gregs[16]); 695 err |= __put_user(regs->sr, &gregs[17]); 696 err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); 697 err |= rt_save_fpu_state(uc, regs); 698 return err; 699 } 700 701 static inline void push_cache (unsigned long vaddr) 702 { 703 /* 704 * Using the old cache_push_v() was really a big waste. 705 * 706 * What we are trying to do is to flush 8 bytes to ram. 707 * Flushing 2 cache lines of 16 bytes is much cheaper than 708 * flushing 1 or 2 pages, as previously done in 709 * cache_push_v(). 710 * Jes 711 */ 712 if (CPU_IS_040) { 713 unsigned long temp; 714 715 __asm__ __volatile__ (".chip 68040\n\t" 716 "nop\n\t" 717 "ptestr (%1)\n\t" 718 "movec %%mmusr,%0\n\t" 719 ".chip 68k" 720 : "=r" (temp) 721 : "a" (vaddr)); 722 723 temp &= PAGE_MASK; 724 temp |= vaddr & ~PAGE_MASK; 725 726 __asm__ __volatile__ (".chip 68040\n\t" 727 "nop\n\t" 728 "cpushl %%bc,(%0)\n\t" 729 ".chip 68k" 730 : : "a" (temp)); 731 } 732 else if (CPU_IS_060) { 733 unsigned long temp; 734 __asm__ __volatile__ (".chip 68060\n\t" 735 "plpar (%0)\n\t" 736 ".chip 68k" 737 : "=a" (temp) 738 : "0" (vaddr)); 739 __asm__ __volatile__ (".chip 68060\n\t" 740 "cpushl %%bc,(%0)\n\t" 741 ".chip 68k" 742 : : "a" (temp)); 743 } 744 else { 745 /* 746 * 68030/68020 have no writeback cache; 747 * still need to clear icache. 748 * Note that vaddr is guaranteed to be long word aligned. 749 */ 750 unsigned long temp; 751 asm volatile ("movec %%cacr,%0" : "=r" (temp)); 752 temp += 4; 753 asm volatile ("movec %0,%%caar\n\t" 754 "movec %1,%%cacr" 755 : : "r" (vaddr), "r" (temp)); 756 asm volatile ("movec %0,%%caar\n\t" 757 "movec %1,%%cacr" 758 : : "r" (vaddr + 4), "r" (temp)); 759 } 760 } 761 762 static inline void __user * 763 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 764 { 765 unsigned long usp; 766 767 /* Default to using normal stack. */ 768 usp = rdusp(); 769 770 /* This is the X/Open sanctioned signal stack switching. */ 771 if (ka->sa.sa_flags & SA_ONSTACK) { 772 if (!sas_ss_flags(usp)) 773 usp = current->sas_ss_sp + current->sas_ss_size; 774 } 775 return (void __user *)((usp - frame_size) & -8UL); 776 } 777 778 static void setup_frame (int sig, struct k_sigaction *ka, 779 sigset_t *set, struct pt_regs *regs) 780 { 781 struct sigframe __user *frame; 782 int fsize = frame_extra_sizes[regs->format]; 783 struct sigcontext context; 784 int err = 0; 785 786 if (fsize < 0) { 787 #ifdef DEBUG 788 printk ("setup_frame: Unknown frame format %#x\n", 789 regs->format); 790 #endif 791 goto give_sigsegv; 792 } 793 794 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); 795 796 if (fsize) { 797 err |= copy_to_user (frame + 1, regs + 1, fsize); 798 regs->stkadj = fsize; 799 } 800 801 err |= __put_user((current_thread_info()->exec_domain 802 && current_thread_info()->exec_domain->signal_invmap 803 && sig < 32 804 ? current_thread_info()->exec_domain->signal_invmap[sig] 805 : sig), 806 &frame->sig); 807 808 err |= __put_user(regs->vector, &frame->code); 809 err |= __put_user(&frame->sc, &frame->psc); 810 811 if (_NSIG_WORDS > 1) 812 err |= copy_to_user(frame->extramask, &set->sig[1], 813 sizeof(frame->extramask)); 814 815 setup_sigcontext(&context, regs, set->sig[0]); 816 err |= copy_to_user (&frame->sc, &context, sizeof(context)); 817 818 /* Set up to return from userspace. */ 819 err |= __put_user(frame->retcode, &frame->pretcode); 820 /* moveq #,d0; trap #0 */ 821 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), 822 (long __user *)(frame->retcode)); 823 824 if (err) 825 goto give_sigsegv; 826 827 push_cache ((unsigned long) &frame->retcode); 828 829 /* Set up registers for signal handler */ 830 wrusp ((unsigned long) frame); 831 regs->pc = (unsigned long) ka->sa.sa_handler; 832 833 adjust_stack: 834 /* Prepare to skip over the extra stuff in the exception frame. */ 835 if (regs->stkadj) { 836 struct pt_regs *tregs = 837 (struct pt_regs *)((ulong)regs + regs->stkadj); 838 #ifdef DEBUG 839 printk("Performing stackadjust=%04x\n", regs->stkadj); 840 #endif 841 /* This must be copied with decreasing addresses to 842 handle overlaps. */ 843 tregs->vector = 0; 844 tregs->format = 0; 845 tregs->pc = regs->pc; 846 tregs->sr = regs->sr; 847 } 848 return; 849 850 give_sigsegv: 851 force_sigsegv(sig, current); 852 goto adjust_stack; 853 } 854 855 static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, 856 sigset_t *set, struct pt_regs *regs) 857 { 858 struct rt_sigframe __user *frame; 859 int fsize = frame_extra_sizes[regs->format]; 860 int err = 0; 861 862 if (fsize < 0) { 863 #ifdef DEBUG 864 printk ("setup_frame: Unknown frame format %#x\n", 865 regs->format); 866 #endif 867 goto give_sigsegv; 868 } 869 870 frame = get_sigframe(ka, regs, sizeof(*frame)); 871 872 if (fsize) { 873 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); 874 regs->stkadj = fsize; 875 } 876 877 err |= __put_user((current_thread_info()->exec_domain 878 && current_thread_info()->exec_domain->signal_invmap 879 && sig < 32 880 ? current_thread_info()->exec_domain->signal_invmap[sig] 881 : sig), 882 &frame->sig); 883 err |= __put_user(&frame->info, &frame->pinfo); 884 err |= __put_user(&frame->uc, &frame->puc); 885 err |= copy_siginfo_to_user(&frame->info, info); 886 887 /* Create the ucontext. */ 888 err |= __put_user(0, &frame->uc.uc_flags); 889 err |= __put_user(NULL, &frame->uc.uc_link); 890 err |= __put_user((void __user *)current->sas_ss_sp, 891 &frame->uc.uc_stack.ss_sp); 892 err |= __put_user(sas_ss_flags(rdusp()), 893 &frame->uc.uc_stack.ss_flags); 894 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 895 err |= rt_setup_ucontext(&frame->uc, regs); 896 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); 897 898 /* Set up to return from userspace. */ 899 err |= __put_user(frame->retcode, &frame->pretcode); 900 /* moveq #,d0; notb d0; trap #0 */ 901 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), 902 (long __user *)(frame->retcode + 0)); 903 err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); 904 905 if (err) 906 goto give_sigsegv; 907 908 push_cache ((unsigned long) &frame->retcode); 909 910 /* Set up registers for signal handler */ 911 wrusp ((unsigned long) frame); 912 regs->pc = (unsigned long) ka->sa.sa_handler; 913 914 adjust_stack: 915 /* Prepare to skip over the extra stuff in the exception frame. */ 916 if (regs->stkadj) { 917 struct pt_regs *tregs = 918 (struct pt_regs *)((ulong)regs + regs->stkadj); 919 #ifdef DEBUG 920 printk("Performing stackadjust=%04x\n", regs->stkadj); 921 #endif 922 /* This must be copied with decreasing addresses to 923 handle overlaps. */ 924 tregs->vector = 0; 925 tregs->format = 0; 926 tregs->pc = regs->pc; 927 tregs->sr = regs->sr; 928 } 929 return; 930 931 give_sigsegv: 932 force_sigsegv(sig, current); 933 goto adjust_stack; 934 } 935 936 static inline void 937 handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) 938 { 939 switch (regs->d0) { 940 case -ERESTARTNOHAND: 941 if (!has_handler) 942 goto do_restart; 943 regs->d0 = -EINTR; 944 break; 945 946 case -ERESTART_RESTARTBLOCK: 947 if (!has_handler) { 948 regs->d0 = __NR_restart_syscall; 949 regs->pc -= 2; 950 break; 951 } 952 regs->d0 = -EINTR; 953 break; 954 955 case -ERESTARTSYS: 956 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { 957 regs->d0 = -EINTR; 958 break; 959 } 960 /* fallthrough */ 961 case -ERESTARTNOINTR: 962 do_restart: 963 regs->d0 = regs->orig_d0; 964 regs->pc -= 2; 965 break; 966 } 967 } 968 969 void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) 970 { 971 if (regs->orig_d0 < 0) 972 return; 973 switch (regs->d0) { 974 case -ERESTARTNOHAND: 975 case -ERESTARTSYS: 976 case -ERESTARTNOINTR: 977 regs->d0 = regs->orig_d0; 978 regs->orig_d0 = -1; 979 regs->pc -= 2; 980 break; 981 } 982 } 983 984 /* 985 * OK, we're invoking a handler 986 */ 987 static void 988 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 989 sigset_t *oldset, struct pt_regs *regs) 990 { 991 /* are we from a system call? */ 992 if (regs->orig_d0 >= 0) 993 /* If so, check system call restarting.. */ 994 handle_restart(regs, ka, 1); 995 996 /* set up the stack frame */ 997 if (ka->sa.sa_flags & SA_SIGINFO) 998 setup_rt_frame(sig, ka, info, oldset, regs); 999 else 1000 setup_frame(sig, ka, oldset, regs); 1001 1002 if (ka->sa.sa_flags & SA_ONESHOT) 1003 ka->sa.sa_handler = SIG_DFL; 1004 1005 sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); 1006 if (!(ka->sa.sa_flags & SA_NODEFER)) 1007 sigaddset(¤t->blocked,sig); 1008 recalc_sigpending(); 1009 } 1010 1011 /* 1012 * Note that 'init' is a special process: it doesn't get signals it doesn't 1013 * want to handle. Thus you cannot kill init even with a SIGKILL even by 1014 * mistake. 1015 */ 1016 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) 1017 { 1018 siginfo_t info; 1019 struct k_sigaction ka; 1020 int signr; 1021 1022 current->thread.esp0 = (unsigned long) regs; 1023 1024 if (!oldset) 1025 oldset = ¤t->blocked; 1026 1027 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 1028 if (signr > 0) { 1029 /* Whee! Actually deliver the signal. */ 1030 handle_signal(signr, &ka, &info, oldset, regs); 1031 return 1; 1032 } 1033 1034 /* Did we come from a system call? */ 1035 if (regs->orig_d0 >= 0) 1036 /* Restart the system call - no handlers present */ 1037 handle_restart(regs, NULL, 0); 1038 1039 return 0; 1040 } 1041