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