diff options
-rw-r--r-- | arch/powerpc/kernel/signal.c | 107 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal.h | 14 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 88 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 86 |
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 | ||
21 | static inline int is_32bit_task(void) | ||
22 | { | ||
23 | return test_thread_flag(TIF_32BIT); | ||
24 | } | ||
25 | #else | ||
26 | static 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(¤t->sighand->siglock); | 42 | spin_unlock_irq(¤t->sighand->siglock); |
29 | } | 43 | } |
30 | 44 | ||
31 | void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | 45 | static 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 | ||
96 | int 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 = ¤t->saved_sigmask; | ||
114 | else if (!oldset) | ||
115 | oldset = ¤t->blocked; | ||
116 | |||
117 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
118 | |||
119 | #ifdef CONFIG_PPC32 | ||
120 | no_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, ¤t->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(¤t->sighand->siglock); | ||
167 | sigorsets(¤t->blocked, ¤t->blocked, | ||
168 | &ka.sa.sa_mask); | ||
169 | if (!(ka.sa.sa_flags & SA_NODEFER)) | ||
170 | sigaddset(¤t->blocked, signr); | ||
171 | recalc_sigpending(); | ||
172 | spin_unlock_irq(¤t->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 | |||
82 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 185 | long 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 | ||
15 | extern void restore_sigmask(sigset_t *set); | 15 | extern void restore_sigmask(sigset_t *set); |
16 | extern void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | 16 | |
17 | int has_handler); | 17 | extern 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 | |||
21 | extern 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 | |||
25 | extern 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 | ||
234 | int 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 | */ |
702 | static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | 699 | int 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 | */ |
993 | static int handle_signal(unsigned long sig, struct k_sigaction *ka, | 990 | int 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 | */ | ||
1110 | int 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 = ¤t->saved_sigmask; | ||
1127 | else if (!oldset) | ||
1128 | oldset = ¤t->blocked; | ||
1129 | |||
1130 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
1131 | #ifdef CONFIG_PPC32 | ||
1132 | no_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, ¤t->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(¤t->sighand->siglock); | ||
1171 | sigorsets(¤t->blocked, ¤t->blocked, | ||
1172 | &ka.sa.sa_mask); | ||
1173 | if (!(ka.sa.sa_flags & SA_NODEFER)) | ||
1174 | sigaddset(¤t->blocked, signr); | ||
1175 | recalc_sigpending(); | ||
1176 | spin_unlock_irq(¤t->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 | ||
337 | static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | 337 | int 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 | */ | ||
425 | static 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(¤t->sighand->siglock); | ||
435 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
436 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
437 | sigaddset(¤t->blocked,sig); | ||
438 | recalc_sigpending(); | ||
439 | spin_unlock_irq(¤t->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 | */ | ||
450 | int 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 = ¤t->saved_sigmask; | ||
465 | else if (!oldset) | ||
466 | oldset = ¤t->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, ¤t->saved_sigmask, NULL); | ||
499 | } | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | EXPORT_SYMBOL(do_signal); | ||