diff options
Diffstat (limited to 'arch/blackfin/kernel/signal.c')
-rw-r--r-- | arch/blackfin/kernel/signal.c | 67 |
1 files changed, 19 insertions, 48 deletions
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index fc9ecce8b6ce..6682b73a8523 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #include <asm/fixed_code.h> | 19 | #include <asm/fixed_code.h> |
20 | #include <asm/syscall.h> | 20 | #include <asm/syscall.h> |
21 | 21 | ||
22 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
23 | |||
24 | /* Location of the trace bit in SYSCFG. */ | 22 | /* Location of the trace bit in SYSCFG. */ |
25 | #define TRACE_BITS 0x0001 | 23 | #define TRACE_BITS 0x0001 |
26 | 24 | ||
@@ -98,7 +96,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) | |||
98 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | 96 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
99 | goto badframe; | 97 | goto badframe; |
100 | 98 | ||
101 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
102 | set_current_blocked(&set); | 99 | set_current_blocked(&set); |
103 | 100 | ||
104 | if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 101 | if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) |
@@ -190,17 +187,22 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
190 | err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 187 | err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
191 | 188 | ||
192 | if (err) | 189 | if (err) |
193 | goto give_sigsegv; | 190 | return -EFAULT; |
194 | 191 | ||
195 | /* Set up registers for signal handler */ | 192 | /* Set up registers for signal handler */ |
196 | wrusp((unsigned long)frame); | ||
197 | if (current->personality & FDPIC_FUNCPTRS) { | 193 | if (current->personality & FDPIC_FUNCPTRS) { |
198 | struct fdpic_func_descriptor __user *funcptr = | 194 | struct fdpic_func_descriptor __user *funcptr = |
199 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; | 195 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; |
200 | __get_user(regs->pc, &funcptr->text); | 196 | u32 pc, p3; |
201 | __get_user(regs->p3, &funcptr->GOT); | 197 | err |= __get_user(pc, &funcptr->text); |
198 | err |= __get_user(p3, &funcptr->GOT); | ||
199 | if (err) | ||
200 | return -EFAULT; | ||
201 | regs->pc = pc; | ||
202 | regs->p3 = p3; | ||
202 | } else | 203 | } else |
203 | regs->pc = (unsigned long)ka->sa.sa_handler; | 204 | regs->pc = (unsigned long)ka->sa.sa_handler; |
205 | wrusp((unsigned long)frame); | ||
204 | regs->rets = SIGRETURN_STUB; | 206 | regs->rets = SIGRETURN_STUB; |
205 | 207 | ||
206 | regs->r0 = frame->sig; | 208 | regs->r0 = frame->sig; |
@@ -208,10 +210,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
208 | regs->r2 = (unsigned long)(&frame->uc); | 210 | regs->r2 = (unsigned long)(&frame->uc); |
209 | 211 | ||
210 | return 0; | 212 | return 0; |
211 | |||
212 | give_sigsegv: | ||
213 | force_sigsegv(sig, current); | ||
214 | return -EFAULT; | ||
215 | } | 213 | } |
216 | 214 | ||
217 | static inline void | 215 | static inline void |
@@ -247,24 +245,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) | |||
247 | /* | 245 | /* |
248 | * OK, we're invoking a handler | 246 | * OK, we're invoking a handler |
249 | */ | 247 | */ |
250 | static int | 248 | static void |
251 | handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, | 249 | handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, |
252 | sigset_t *oldset, struct pt_regs *regs) | 250 | struct pt_regs *regs) |
253 | { | 251 | { |
254 | int ret; | ||
255 | |||
256 | /* are we from a system call? to see pt_regs->orig_p0 */ | 252 | /* are we from a system call? to see pt_regs->orig_p0 */ |
257 | if (regs->orig_p0 >= 0) | 253 | if (regs->orig_p0 >= 0) |
258 | /* If so, check system call restarting.. */ | 254 | /* If so, check system call restarting.. */ |
259 | handle_restart(regs, ka, 1); | 255 | handle_restart(regs, ka, 1); |
260 | 256 | ||
261 | /* set up the stack frame */ | 257 | /* set up the stack frame */ |
262 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 258 | if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) |
263 | 259 | force_sigsegv(sig, current); | |
264 | if (ret == 0) | 260 | else |
265 | block_sigmask(ka, sig); | 261 | signal_delivered(sig, info, ka, regs, |
266 | 262 | test_thread_flag(TIF_SINGLESTEP)); | |
267 | return ret; | ||
268 | } | 263 | } |
269 | 264 | ||
270 | /* | 265 | /* |
@@ -281,37 +276,16 @@ asmlinkage void do_signal(struct pt_regs *regs) | |||
281 | siginfo_t info; | 276 | siginfo_t info; |
282 | int signr; | 277 | int signr; |
283 | struct k_sigaction ka; | 278 | struct k_sigaction ka; |
284 | sigset_t *oldset; | ||
285 | 279 | ||
286 | current->thread.esp0 = (unsigned long)regs; | 280 | current->thread.esp0 = (unsigned long)regs; |
287 | 281 | ||
288 | if (try_to_freeze()) | ||
289 | goto no_signal; | ||
290 | |||
291 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
292 | oldset = ¤t->saved_sigmask; | ||
293 | else | ||
294 | oldset = ¤t->blocked; | ||
295 | |||
296 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 282 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
297 | if (signr > 0) { | 283 | if (signr > 0) { |
298 | /* Whee! Actually deliver the signal. */ | 284 | /* Whee! Actually deliver the signal. */ |
299 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 285 | handle_signal(signr, &info, &ka, regs); |
300 | /* a signal was successfully delivered; the saved | ||
301 | * sigmask will have been stored in the signal frame, | ||
302 | * and will be restored by sigreturn, so we can simply | ||
303 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
304 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
305 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
306 | |||
307 | tracehook_signal_handler(signr, &info, &ka, regs, | ||
308 | test_thread_flag(TIF_SINGLESTEP)); | ||
309 | } | ||
310 | |||
311 | return; | 286 | return; |
312 | } | 287 | } |
313 | 288 | ||
314 | no_signal: | ||
315 | /* Did we come from a system call? */ | 289 | /* Did we come from a system call? */ |
316 | if (regs->orig_p0 >= 0) | 290 | if (regs->orig_p0 >= 0) |
317 | /* Restart the system call - no handlers present */ | 291 | /* Restart the system call - no handlers present */ |
@@ -319,10 +293,7 @@ asmlinkage void do_signal(struct pt_regs *regs) | |||
319 | 293 | ||
320 | /* if there's no signal to deliver, we just put the saved sigmask | 294 | /* if there's no signal to deliver, we just put the saved sigmask |
321 | * back */ | 295 | * back */ |
322 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 296 | restore_saved_sigmask(); |
323 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
324 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
325 | } | ||
326 | } | 297 | } |
327 | 298 | ||
328 | /* | 299 | /* |
@@ -330,7 +301,7 @@ asmlinkage void do_signal(struct pt_regs *regs) | |||
330 | */ | 301 | */ |
331 | asmlinkage void do_notify_resume(struct pt_regs *regs) | 302 | asmlinkage void do_notify_resume(struct pt_regs *regs) |
332 | { | 303 | { |
333 | if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK)) | 304 | if (test_thread_flag(TIF_SIGPENDING)) |
334 | do_signal(regs); | 305 | do_signal(regs); |
335 | 306 | ||
336 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { | 307 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { |