aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-06-04 01:15:52 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-14 08:29:58 -0400
commitf478f5430c8a599f46c41e8172a507a5772a6b69 (patch)
treece42723ed517a82a5e73b45cfe52a3bd338c1a4d /arch/powerpc/kernel/signal.c
parentdb277e9a67b9d81b9d6cd74edf0c3e1a0ef2aa4b (diff)
[POWERPC] Consolidate do_signal
do_signal has exactly the same behaviour on 32bit and 64bit and 32bit compat on 64bit for handling 32bit signals. Consolidate all these into one common function in signal.c. The only odd left over is the try_to_free in the 32bit version that no other architecture has in mainline (only in i386 for some odd SuSE release). We should probably get rid of it in a separate patch. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/signal.c')
-rw-r--r--arch/powerpc/kernel/signal.c107
1 files changed, 105 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index f92856b98b70..640b5f3611ee 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -9,6 +9,7 @@
9 * this archive for more details. 9 * this archive for more details.
10 */ 10 */
11 11
12#include <linux/freezer.h>
12#include <linux/ptrace.h> 13#include <linux/ptrace.h>
13#include <linux/signal.h> 14#include <linux/signal.h>
14#include <asm/unistd.h> 15#include <asm/unistd.h>
@@ -16,6 +17,19 @@
16#include "signal.h" 17#include "signal.h"
17 18
18 19
20#ifdef CONFIG_PPC64
21static inline int is_32bit_task(void)
22{
23 return test_thread_flag(TIF_32BIT);
24}
25#else
26static inline int is_32bit_task(void)
27{
28 return 1;
29}
30#endif
31
32
19/* 33/*
20 * Restore the user process's signal mask 34 * Restore the user process's signal mask
21 */ 35 */
@@ -28,8 +42,8 @@ void restore_sigmask(sigset_t *set)
28 spin_unlock_irq(&current->sighand->siglock); 42 spin_unlock_irq(&current->sighand->siglock);
29} 43}
30 44
31void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, 45static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
32 int has_handler) 46 int has_handler)
33{ 47{
34 unsigned long ret = regs->gpr[3]; 48 unsigned long ret = regs->gpr[3];
35 int restart = 1; 49 int restart = 1;
@@ -79,6 +93,95 @@ void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
79 } 93 }
80} 94}
81 95
96int do_signal(sigset_t *oldset, struct pt_regs *regs)
97{
98 siginfo_t info;
99 int signr;
100 struct k_sigaction ka;
101 int ret;
102 int is32 = is_32bit_task();
103
104#ifdef CONFIG_PPC32
105 if (try_to_freeze()) {
106 signr = 0;
107 if (!signal_pending(current))
108 goto no_signal;
109 }
110#endif
111
112 if (test_thread_flag(TIF_RESTORE_SIGMASK))
113 oldset = &current->saved_sigmask;
114 else if (!oldset)
115 oldset = &current->blocked;
116
117 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
118
119#ifdef CONFIG_PPC32
120no_signal:
121#endif
122 /* Is there any syscall restart business here ? */
123 check_syscall_restart(regs, &ka, signr > 0);
124
125 if (signr <= 0) {
126 /* No signal to deliver -- put the saved sigmask back */
127 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
128 clear_thread_flag(TIF_RESTORE_SIGMASK);
129 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
130 }
131 return 0; /* no signals delivered */
132 }
133
134#ifdef CONFIG_PPC64
135 /*
136 * Reenable the DABR before delivering the signal to
137 * user space. The DABR will have been cleared if it
138 * triggered inside the kernel.
139 */
140 if (current->thread.dabr)
141 set_dabr(current->thread.dabr);
142#endif
143
144 if (is32) {
145 unsigned int newsp;
146
147 if ((ka.sa.sa_flags & SA_ONSTACK) &&
148 current->sas_ss_size && !on_sig_stack(regs->gpr[1]))
149 newsp = current->sas_ss_sp + current->sas_ss_size;
150 else
151 newsp = regs->gpr[1];
152
153 if (ka.sa.sa_flags & SA_SIGINFO)
154 ret = handle_rt_signal32(signr, &ka, &info, oldset,
155 regs, newsp);
156 else
157 ret = handle_signal32(signr, &ka, &info, oldset,
158 regs, newsp);
159#ifdef CONFIG_PPC64
160 } else {
161 ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
162#endif
163 }
164
165 if (ret) {
166 spin_lock_irq(&current->sighand->siglock);
167 sigorsets(&current->blocked, &current->blocked,
168 &ka.sa.sa_mask);
169 if (!(ka.sa.sa_flags & SA_NODEFER))
170 sigaddset(&current->blocked, signr);
171 recalc_sigpending();
172 spin_unlock_irq(&current->sighand->siglock);
173
174 /*
175 * A signal was successfully delivered; the saved sigmask is in
176 * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
177 */
178 if (test_thread_flag(TIF_RESTORE_SIGMASK))
179 clear_thread_flag(TIF_RESTORE_SIGMASK);
180 }
181
182 return ret;
183}
184
82long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 185long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
83 unsigned long r5, unsigned long r6, unsigned long r7, 186 unsigned long r5, unsigned long r6, unsigned long r7,
84 unsigned long r8, struct pt_regs *regs) 187 unsigned long r8, struct pt_regs *regs)