aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-rw-r--r--arch/powerpc/kernel/signal.c107
-rw-r--r--arch/powerpc/kernel/signal.h14
-rw-r--r--arch/powerpc/kernel/signal_32.c88
-rw-r--r--arch/powerpc/kernel/signal_64.c86
4 files changed, 120 insertions, 175 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)
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index 4b091d8b764c..190d4325f974 100644
--- a/arch/powerpc/kernel/signal.h
+++ b/arch/powerpc/kernel/signal.h
@@ -13,7 +13,17 @@
13#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 13#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
14 14
15extern void restore_sigmask(sigset_t *set); 15extern void restore_sigmask(sigset_t *set);
16extern void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, 16
17 int has_handler); 17extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
18 siginfo_t *info, sigset_t *oldset,
19 struct pt_regs *regs, unsigned long newsp);
20
21extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
22 siginfo_t *info, sigset_t *oldset,
23 struct pt_regs *regs, unsigned long newsp);
24
25extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
26 siginfo_t *info, sigset_t *set,
27 struct pt_regs *regs);
18 28
19#endif /* _POWERPC_ARCH_SIGNAL_H */ 29#endif /* _POWERPC_ARCH_SIGNAL_H */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 1d899a56fa13..32481e71d71e 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -56,7 +56,6 @@
56#undef DEBUG_SIG 56#undef DEBUG_SIG
57 57
58#ifdef CONFIG_PPC64 58#ifdef CONFIG_PPC64
59#define do_signal do_signal32
60#define sys_sigsuspend compat_sys_sigsuspend 59#define sys_sigsuspend compat_sys_sigsuspend
61#define sys_rt_sigsuspend compat_sys_rt_sigsuspend 60#define sys_rt_sigsuspend compat_sys_rt_sigsuspend
62#define sys_rt_sigreturn compat_sys_rt_sigreturn 61#define sys_rt_sigreturn compat_sys_rt_sigreturn
@@ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs,
231 230
232#endif /* CONFIG_PPC64 */ 231#endif /* CONFIG_PPC64 */
233 232
234int do_signal(sigset_t *oldset, struct pt_regs *regs);
235
236/* 233/*
237 * Atomically swap in the new signal mask, and wait for a signal. 234 * Atomically swap in the new signal mask, and wait for a signal.
238 */ 235 */
@@ -699,7 +696,7 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
699 * Set up a signal frame for a "real-time" signal handler 696 * Set up a signal frame for a "real-time" signal handler
700 * (one which gets siginfo). 697 * (one which gets siginfo).
701 */ 698 */
702static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, 699int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
703 siginfo_t *info, sigset_t *oldset, 700 siginfo_t *info, sigset_t *oldset,
704 struct pt_regs *regs, unsigned long newsp) 701 struct pt_regs *regs, unsigned long newsp)
705{ 702{
@@ -990,7 +987,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
990/* 987/*
991 * OK, we're invoking a handler 988 * OK, we're invoking a handler
992 */ 989 */
993static int handle_signal(unsigned long sig, struct k_sigaction *ka, 990int handle_signal32(unsigned long sig, struct k_sigaction *ka,
994 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, 991 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
995 unsigned long newsp) 992 unsigned long newsp)
996{ 993{
@@ -1101,84 +1098,3 @@ badframe:
1101 force_sig(SIGSEGV, current); 1098 force_sig(SIGSEGV, current);
1102 return 0; 1099 return 0;
1103} 1100}
1104
1105/*
1106 * Note that 'init' is a special process: it doesn't get signals it doesn't
1107 * want to handle. Thus you cannot kill init even with a SIGKILL even by
1108 * mistake.
1109 */
1110int do_signal(sigset_t *oldset, struct pt_regs *regs)
1111{
1112 siginfo_t info;
1113 struct k_sigaction ka;
1114 unsigned int newsp;
1115 int signr, ret;
1116
1117#ifdef CONFIG_PPC32
1118 if (try_to_freeze()) {
1119 signr = 0;
1120 if (!signal_pending(current))
1121 goto no_signal;
1122 }
1123#endif
1124
1125 if (test_thread_flag(TIF_RESTORE_SIGMASK))
1126 oldset = &current->saved_sigmask;
1127 else if (!oldset)
1128 oldset = &current->blocked;
1129
1130 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
1131#ifdef CONFIG_PPC32
1132no_signal:
1133#endif
1134 /* Is there any syscall restart business here ? */
1135 check_syscall_restart(regs, &ka, signr > 0);
1136
1137 if (signr == 0) {
1138 /* No signal to deliver -- put the saved sigmask back */
1139 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
1140 clear_thread_flag(TIF_RESTORE_SIGMASK);
1141 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
1142 }
1143 return 0; /* no signals delivered */
1144 }
1145
1146 if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
1147 && !on_sig_stack(regs->gpr[1]))
1148 newsp = current->sas_ss_sp + current->sas_ss_size;
1149 else
1150 newsp = regs->gpr[1];
1151 newsp &= ~0xfUL;
1152
1153#ifdef CONFIG_PPC64
1154 /*
1155 * Reenable the DABR before delivering the signal to
1156 * user space. The DABR will have been cleared if it
1157 * triggered inside the kernel.
1158 */
1159 if (current->thread.dabr)
1160 set_dabr(current->thread.dabr);
1161#endif
1162
1163 /* Whee! Actually deliver the signal. */
1164 if (ka.sa.sa_flags & SA_SIGINFO)
1165 ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
1166 else
1167 ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
1168
1169 if (ret) {
1170 spin_lock_irq(&current->sighand->siglock);
1171 sigorsets(&current->blocked, &current->blocked,
1172 &ka.sa.sa_mask);
1173 if (!(ka.sa.sa_flags & SA_NODEFER))
1174 sigaddset(&current->blocked, signr);
1175 recalc_sigpending();
1176 spin_unlock_irq(&current->sighand->siglock);
1177 /* A signal was successfully delivered; the saved sigmask is in
1178 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
1179 if (test_thread_flag(TIF_RESTORE_SIGMASK))
1180 clear_thread_flag(TIF_RESTORE_SIGMASK);
1181 }
1182
1183 return ret;
1184}
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 7e9c4b7e7e82..c17903cd384a 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -334,7 +334,7 @@ badframe:
334 return 0; 334 return 0;
335} 335}
336 336
337static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, 337int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
338 sigset_t *set, struct pt_regs *regs) 338 sigset_t *set, struct pt_regs *regs)
339{ 339{
340 /* Handler is *really* a pointer to the function descriptor for 340 /* Handler is *really* a pointer to the function descriptor for
@@ -417,87 +417,3 @@ badframe:
417 force_sigsegv(signr, current); 417 force_sigsegv(signr, current);
418 return 0; 418 return 0;
419} 419}
420
421
422/*
423 * OK, we're invoking a handler
424 */
425static int handle_signal(unsigned long sig, struct k_sigaction *ka,
426 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
427{
428 int ret;
429
430 /* Set up Signal Frame */
431 ret = setup_rt_frame(sig, ka, info, oldset, regs);
432
433 if (ret) {
434 spin_lock_irq(&current->sighand->siglock);
435 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
436 if (!(ka->sa.sa_flags & SA_NODEFER))
437 sigaddset(&current->blocked,sig);
438 recalc_sigpending();
439 spin_unlock_irq(&current->sighand->siglock);
440 }
441
442 return ret;
443}
444
445/*
446 * Note that 'init' is a special process: it doesn't get signals it doesn't
447 * want to handle. Thus you cannot kill init even with a SIGKILL even by
448 * mistake.
449 */
450int do_signal(sigset_t *oldset, struct pt_regs *regs)
451{
452 siginfo_t info;
453 int signr;
454 struct k_sigaction ka;
455
456 /*
457 * If the current thread is 32 bit - invoke the
458 * 32 bit signal handling code
459 */
460 if (test_thread_flag(TIF_32BIT))
461 return do_signal32(oldset, regs);
462
463 if (test_thread_flag(TIF_RESTORE_SIGMASK))
464 oldset = &current->saved_sigmask;
465 else if (!oldset)
466 oldset = &current->blocked;
467
468 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
469
470 /* Is there any syscall restart business here ? */
471 check_syscall_restart(regs, &ka, signr > 0);
472
473 if (signr > 0) {
474 int ret;
475
476 /*
477 * Reenable the DABR before delivering the signal to
478 * user space. The DABR will have been cleared if it
479 * triggered inside the kernel.
480 */
481 if (current->thread.dabr)
482 set_dabr(current->thread.dabr);
483
484 /* Whee! Actually deliver the signal. */
485 ret = handle_signal(signr, &ka, &info, oldset, regs);
486
487 /* If a signal was successfully delivered, the saved sigmask is in
488 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
489 if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
490 clear_thread_flag(TIF_RESTORE_SIGMASK);
491
492 return ret;
493 }
494
495 /* No signal to deliver -- put the saved sigmask back */
496 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
497 clear_thread_flag(TIF_RESTORE_SIGMASK);
498 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
499 }
500
501 return 0;
502}
503EXPORT_SYMBOL(do_signal);