aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/signal.c')
-rw-r--r--arch/parisc/kernel/signal.c273
1 files changed, 132 insertions, 141 deletions
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index ee6653edeb7a..9784e405f849 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -59,58 +59,13 @@
59 * this. */ 59 * this. */
60#define A(__x) ((unsigned long)(__x)) 60#define A(__x) ((unsigned long)(__x))
61 61
62int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
63
64/* 62/*
65 * Atomically swap in the new signal mask, and wait for a signal. 63 * Atomically swap in the new signal mask, and wait for a signal.
66 */ 64 */
67#ifdef __LP64__ 65#ifdef CONFIG_64BIT
68#include "sys32.h" 66#include "sys32.h"
69#endif 67#endif
70 68
71asmlinkage int
72sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
73{
74 sigset_t saveset, newset;
75#ifdef __LP64__
76 compat_sigset_t newset32;
77
78 if (is_compat_task()) {
79 /* XXX: Don't preclude handling different sized sigset_t's. */
80 if (sigsetsize != sizeof(compat_sigset_t))
81 return -EINVAL;
82 if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
83 return -EFAULT;
84 sigset_32to64(&newset,&newset32);
85
86 } else
87#endif
88 {
89 /* XXX: Don't preclude handling different sized sigset_t's. */
90 if (sigsetsize != sizeof(sigset_t))
91 return -EINVAL;
92
93 if (copy_from_user(&newset, unewset, sizeof(newset)))
94 return -EFAULT;
95 }
96
97 sigdelsetmask(&newset, ~_BLOCKABLE);
98
99 spin_lock_irq(&current->sighand->siglock);
100 saveset = current->blocked;
101 current->blocked = newset;
102 recalc_sigpending();
103 spin_unlock_irq(&current->sighand->siglock);
104
105 regs->gr[28] = -EINTR;
106 while (1) {
107 current->state = TASK_INTERRUPTIBLE;
108 schedule();
109 if (do_signal(&saveset, regs, 1))
110 return -EINTR;
111 }
112}
113
114/* 69/*
115 * Do a signal return - restore sigcontext. 70 * Do a signal return - restore sigcontext.
116 */ 71 */
@@ -148,7 +103,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
148 sigset_t set; 103 sigset_t set;
149 unsigned long usp = (regs->gr[30] & ~(0x01UL)); 104 unsigned long usp = (regs->gr[30] & ~(0x01UL));
150 unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE; 105 unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
151#ifdef __LP64__ 106#ifdef CONFIG_64BIT
152 compat_sigset_t compat_set; 107 compat_sigset_t compat_set;
153 struct compat_rt_sigframe __user * compat_frame; 108 struct compat_rt_sigframe __user * compat_frame;
154 109
@@ -162,7 +117,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
162 (usp - sigframe_size); 117 (usp - sigframe_size);
163 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); 118 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
164 119
165#ifdef __LP64__ 120#ifdef CONFIG_64BIT
166 compat_frame = (struct compat_rt_sigframe __user *)frame; 121 compat_frame = (struct compat_rt_sigframe __user *)frame;
167 122
168 if (is_compat_task()) { 123 if (is_compat_task()) {
@@ -184,7 +139,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
184 spin_unlock_irq(&current->sighand->siglock); 139 spin_unlock_irq(&current->sighand->siglock);
185 140
186 /* Good thing we saved the old gr[30], eh? */ 141 /* Good thing we saved the old gr[30], eh? */
187#ifdef __LP64__ 142#ifdef CONFIG_64BIT
188 if (is_compat_task()) { 143 if (is_compat_task()) {
189 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n", 144 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
190 &compat_frame->uc.uc_mcontext); 145 &compat_frame->uc.uc_mcontext);
@@ -296,7 +251,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
296 unsigned long rp, usp; 251 unsigned long rp, usp;
297 unsigned long haddr, sigframe_size; 252 unsigned long haddr, sigframe_size;
298 int err = 0; 253 int err = 0;
299#ifdef __LP64__ 254#ifdef CONFIG_64BIT
300 compat_int_t compat_val; 255 compat_int_t compat_val;
301 struct compat_rt_sigframe __user * compat_frame; 256 struct compat_rt_sigframe __user * compat_frame;
302 compat_sigset_t compat_set; 257 compat_sigset_t compat_set;
@@ -310,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
310 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info); 265 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
311 266
312 267
313#ifdef __LP64__ 268#ifdef CONFIG_64BIT
314 269
315 compat_frame = (struct compat_rt_sigframe __user *)frame; 270 compat_frame = (struct compat_rt_sigframe __user *)frame;
316 271
@@ -390,7 +345,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
390 345
391 haddr = A(ka->sa.sa_handler); 346 haddr = A(ka->sa.sa_handler);
392 /* The sa_handler may be a pointer to a function descriptor */ 347 /* The sa_handler may be a pointer to a function descriptor */
393#ifdef __LP64__ 348#ifdef CONFIG_64BIT
394 if (is_compat_task()) { 349 if (is_compat_task()) {
395#endif 350#endif
396 if (haddr & PA_PLABEL_FDESC) { 351 if (haddr & PA_PLABEL_FDESC) {
@@ -405,7 +360,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
405 haddr = fdesc.addr; 360 haddr = fdesc.addr;
406 regs->gr[19] = fdesc.gp; 361 regs->gr[19] = fdesc.gp;
407 } 362 }
408#ifdef __LP64__ 363#ifdef CONFIG_64BIT
409 } else { 364 } else {
410 Elf64_Fdesc fdesc; 365 Elf64_Fdesc fdesc;
411 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3); 366 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
@@ -425,19 +380,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
425 /* The syscall return path will create IAOQ values from r31. 380 /* The syscall return path will create IAOQ values from r31.
426 */ 381 */
427 sigframe_size = PARISC_RT_SIGFRAME_SIZE; 382 sigframe_size = PARISC_RT_SIGFRAME_SIZE;
428#ifdef __LP64__ 383#ifdef CONFIG_64BIT
429 if (is_compat_task()) 384 if (is_compat_task())
430 sigframe_size = PARISC_RT_SIGFRAME_SIZE32; 385 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
431#endif 386#endif
432 if (in_syscall) { 387 if (in_syscall) {
433 regs->gr[31] = haddr; 388 regs->gr[31] = haddr;
434#ifdef __LP64__ 389#ifdef CONFIG_64BIT
435 if (!test_thread_flag(TIF_32BIT)) 390 if (!test_thread_flag(TIF_32BIT))
436 sigframe_size |= 1; 391 sigframe_size |= 1;
437#endif 392#endif
438 } else { 393 } else {
439 unsigned long psw = USER_PSW; 394 unsigned long psw = USER_PSW;
440#ifdef __LP64__ 395#ifdef CONFIG_64BIT
441 if (!test_thread_flag(TIF_32BIT)) 396 if (!test_thread_flag(TIF_32BIT))
442 psw |= PSW_W; 397 psw |= PSW_W;
443#endif 398#endif
@@ -462,7 +417,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
462 regs->gr[2] = rp; /* userland return pointer */ 417 regs->gr[2] = rp; /* userland return pointer */
463 regs->gr[26] = sig; /* signal number */ 418 regs->gr[26] = sig; /* signal number */
464 419
465#ifdef __LP64__ 420#ifdef CONFIG_64BIT
466 if (is_compat_task()) { 421 if (is_compat_task()) {
467 regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */ 422 regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
468 regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */ 423 regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */
@@ -516,6 +471,97 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
516 return 1; 471 return 1;
517} 472}
518 473
474static inline void
475syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
476{
477 /* Check the return code */
478 switch (regs->gr[28]) {
479 case -ERESTART_RESTARTBLOCK:
480 current_thread_info()->restart_block.fn =
481 do_no_restart_syscall;
482 case -ERESTARTNOHAND:
483 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
484 regs->gr[28] = -EINTR;
485 break;
486
487 case -ERESTARTSYS:
488 if (!(ka->sa.sa_flags & SA_RESTART)) {
489 DBG(1,"ERESTARTSYS: putting -EINTR\n");
490 regs->gr[28] = -EINTR;
491 break;
492 }
493 /* fallthrough */
494 case -ERESTARTNOINTR:
495 /* A syscall is just a branch, so all
496 * we have to do is fiddle the return pointer.
497 */
498 regs->gr[31] -= 8; /* delayed branching */
499 /* Preserve original r28. */
500 regs->gr[28] = regs->orig_r28;
501 break;
502 }
503}
504
505static inline void
506insert_restart_trampoline(struct pt_regs *regs)
507{
508 switch(regs->gr[28]) {
509 case -ERESTART_RESTARTBLOCK: {
510 /* Restart the system call - no handlers present */
511 unsigned int *usp = (unsigned int *)regs->gr[30];
512
513 /* Setup a trampoline to restart the syscall
514 * with __NR_restart_syscall
515 *
516 * 0: <return address (orig r31)>
517 * 4: <2nd half for 64-bit>
518 * 8: ldw 0(%sp), %r31
519 * 12: be 0x100(%sr2, %r0)
520 * 16: ldi __NR_restart_syscall, %r20
521 */
522#ifdef CONFIG_64BIT
523 put_user(regs->gr[31] >> 32, &usp[0]);
524 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
525 put_user(0x0fc010df, &usp[2]);
526#else
527 put_user(regs->gr[31], &usp[0]);
528 put_user(0x0fc0109f, &usp[2]);
529#endif
530 put_user(0xe0008200, &usp[3]);
531 put_user(0x34140000, &usp[4]);
532
533 /* Stack is 64-byte aligned, and we only need
534 * to flush 1 cache line.
535 * Flushing one cacheline is cheap.
536 * "sync" on bigger (> 4 way) boxes is not.
537 */
538 flush_icache_range(regs->gr[30], regs->gr[30] + 4);
539
540 regs->gr[31] = regs->gr[30] + 8;
541 /* Preserve original r28. */
542 regs->gr[28] = regs->orig_r28;
543
544 return;
545 }
546 case -ERESTARTNOHAND:
547 case -ERESTARTSYS:
548 case -ERESTARTNOINTR: {
549 /* Hooray for delayed branching. We don't
550 * have to restore %r20 (the system call
551 * number) because it gets loaded in the delay
552 * slot of the branch external instruction.
553 */
554 regs->gr[31] -= 8;
555 /* Preserve original r28. */
556 regs->gr[28] = regs->orig_r28;
557
558 return;
559 }
560 default:
561 break;
562 }
563}
564
519/* 565/*
520 * Note that 'init' is a special process: it doesn't get signals it doesn't 566 * Note that 'init' is a special process: it doesn't get signals it doesn't
521 * want to handle. Thus you cannot kill init even with a SIGKILL even by 567 * want to handle. Thus you cannot kill init even with a SIGKILL even by
@@ -527,13 +573,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
527 * registers). As noted below, the syscall number gets restored for 573 * registers). As noted below, the syscall number gets restored for
528 * us due to the magic of delayed branching. 574 * us due to the magic of delayed branching.
529 */ 575 */
530 576asmlinkage void
531asmlinkage int 577do_signal(struct pt_regs *regs, long in_syscall)
532do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
533{ 578{
534 siginfo_t info; 579 siginfo_t info;
535 struct k_sigaction ka; 580 struct k_sigaction ka;
536 int signr; 581 int signr;
582 sigset_t *oldset;
537 583
538 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", 584 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
539 oldset, regs, regs->sr[7], in_syscall); 585 oldset, regs, regs->sr[7], in_syscall);
@@ -543,7 +589,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
543 we would be called in that case, but for some reason we 589 we would be called in that case, but for some reason we
544 are. */ 590 are. */
545 591
546 if (!oldset) 592 if (test_thread_flag(TIF_RESTORE_SIGMASK))
593 oldset = &current->saved_sigmask;
594 else
547 oldset = &current->blocked; 595 oldset = &current->blocked;
548 596
549 DBG(1,"do_signal: oldset %08lx / %08lx\n", 597 DBG(1,"do_signal: oldset %08lx / %08lx\n",
@@ -560,98 +608,41 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
560 break; 608 break;
561 609
562 /* Restart a system call if necessary. */ 610 /* Restart a system call if necessary. */
563 if (in_syscall) { 611 if (in_syscall)
564 /* Check the return code */ 612 syscall_restart(regs, &ka);
565 switch (regs->gr[28]) { 613
566 case -ERESTART_RESTARTBLOCK:
567 current_thread_info()->restart_block.fn = do_no_restart_syscall;
568 case -ERESTARTNOHAND:
569 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
570 regs->gr[28] = -EINTR;
571 break;
572
573 case -ERESTARTSYS:
574 if (!(ka.sa.sa_flags & SA_RESTART)) {
575 DBG(1,"ERESTARTSYS: putting -EINTR\n");
576 regs->gr[28] = -EINTR;
577 break;
578 }
579 /* fallthrough */
580 case -ERESTARTNOINTR:
581 /* A syscall is just a branch, so all
582 we have to do is fiddle the return pointer. */
583 regs->gr[31] -= 8; /* delayed branching */
584 /* Preserve original r28. */
585 regs->gr[28] = regs->orig_r28;
586 break;
587 }
588 }
589 /* Whee! Actually deliver the signal. If the 614 /* Whee! Actually deliver the signal. If the
590 delivery failed, we need to continue to iterate in 615 delivery failed, we need to continue to iterate in
591 this loop so we can deliver the SIGSEGV... */ 616 this loop so we can deliver the SIGSEGV... */
592 if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { 617 if (handle_signal(signr, &info, &ka, oldset,
618 regs, in_syscall)) {
593 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", 619 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
594 regs->gr[28]); 620 regs->gr[28]);
595 return 1; 621 if (test_thread_flag(TIF_RESTORE_SIGMASK))
622 clear_thread_flag(TIF_RESTORE_SIGMASK);
623 return;
596 } 624 }
597 } 625 }
598 /* end of while(1) looping forever if we can't force a signal */ 626 /* end of while(1) looping forever if we can't force a signal */
599 627
600 /* Did we come from a system call? */ 628 /* Did we come from a system call? */
601 if (in_syscall) { 629 if (in_syscall)
602 /* Restart the system call - no handlers present */ 630 insert_restart_trampoline(regs);
603 if (regs->gr[28] == -ERESTART_RESTARTBLOCK) {
604 unsigned int *usp = (unsigned int *)regs->gr[30];
605
606 /* Setup a trampoline to restart the syscall
607 * with __NR_restart_syscall
608 *
609 * 0: <return address (orig r31)>
610 * 4: <2nd half for 64-bit>
611 * 8: ldw 0(%sp), %r31
612 * 12: be 0x100(%sr2, %r0)
613 * 16: ldi __NR_restart_syscall, %r20
614 */
615#ifndef __LP64__
616 put_user(regs->gr[31], &usp[0]);
617 put_user(0x0fc0109f, &usp[2]);
618#else
619 put_user(regs->gr[31] >> 32, &usp[0]);
620 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
621 put_user(0x0fc010df, &usp[2]);
622#endif
623 put_user(0xe0008200, &usp[3]);
624 put_user(0x34140000, &usp[4]);
625
626 /* Stack is 64-byte aligned, and we only need
627 * to flush 1 cache line.
628 * Flushing one cacheline is cheap.
629 * "sync" on bigger (> 4 way) boxes is not.
630 */
631 asm("fdc %%r0(%%sr3, %0)\n"
632 "sync\n"
633 "fic %%r0(%%sr3, %0)\n"
634 "sync\n"
635 : : "r"(regs->gr[30]));
636
637 regs->gr[31] = regs->gr[30] + 8;
638 /* Preserve original r28. */
639 regs->gr[28] = regs->orig_r28;
640 } else if (regs->gr[28] == -ERESTARTNOHAND ||
641 regs->gr[28] == -ERESTARTSYS ||
642 regs->gr[28] == -ERESTARTNOINTR) {
643 /* Hooray for delayed branching. We don't
644 have to restore %r20 (the system call
645 number) because it gets loaded in the delay
646 slot of the branch external instruction. */
647 regs->gr[31] -= 8;
648 /* Preserve original r28. */
649 regs->gr[28] = regs->orig_r28;
650 }
651 }
652 631
653 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 632 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
654 regs->gr[28]); 633 regs->gr[28]);
655 634
656 return 0; 635 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
636 clear_thread_flag(TIF_RESTORE_SIGMASK);
637 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
638 }
639
640 return;
641}
642
643void do_notify_resume(struct pt_regs *regs, long in_syscall)
644{
645 if (test_thread_flag(TIF_SIGPENDING) ||
646 test_thread_flag(TIF_RESTORE_SIGMASK))
647 do_signal(regs, in_syscall);
657} 648}