]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/powerpc/kernel/signal.c
[POWERPC] Consolidate sys_sigaltstack
[karo-tx-linux.git] / arch / powerpc / kernel / signal.c
1 /*
2  * Common signal handling code for both 32 and 64 bits
3  *
4  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
5  *    Extracted from signal_32.c and signal_64.c
6  *
7  * This file is subject to the terms and conditions of the GNU General
8  * Public License.  See the file README.legal in the main directory of
9  * this archive for more details.
10  */
11
12 #include <linux/ptrace.h>
13 #include <linux/signal.h>
14 #include <asm/unistd.h>
15
16 void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
17                            int has_handler)
18 {
19         unsigned long ret = regs->gpr[3];
20         int restart = 1;
21
22         /* syscall ? */
23         if (TRAP(regs) != 0x0C00)
24                 return;
25
26         /* error signalled ? */
27         if (!(regs->ccr & 0x10000000))
28                 return;
29
30         switch (ret) {
31         case ERESTART_RESTARTBLOCK:
32         case ERESTARTNOHAND:
33                 /* ERESTARTNOHAND means that the syscall should only be
34                  * restarted if there was no handler for the signal, and since
35                  * we only get here if there is a handler, we dont restart.
36                  */
37                 restart = !has_handler;
38                 break;
39         case ERESTARTSYS:
40                 /* ERESTARTSYS means to restart the syscall if there is no
41                  * handler or the handler was registered with SA_RESTART
42                  */
43                 restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
44                 break;
45         case ERESTARTNOINTR:
46                 /* ERESTARTNOINTR means that the syscall should be
47                  * called again after the signal handler returns.
48                  */
49                 break;
50         default:
51                 return;
52         }
53         if (restart) {
54                 if (ret == ERESTART_RESTARTBLOCK)
55                         regs->gpr[0] = __NR_restart_syscall;
56                 else
57                         regs->gpr[3] = regs->orig_gpr3;
58                 regs->nip -= 4;
59                 regs->result = 0;
60         } else {
61                 regs->result = -EINTR;
62                 regs->gpr[3] = EINTR;
63                 regs->ccr |= 0x10000000;
64         }
65 }
66
67 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
68                 unsigned long r5, unsigned long r6, unsigned long r7,
69                 unsigned long r8, struct pt_regs *regs)
70 {
71         return do_sigaltstack(uss, uoss, regs->gpr[1]);
72 }