diff options
Diffstat (limited to 'arch/blackfin/kernel/signal.c')
| -rw-r--r-- | arch/blackfin/kernel/signal.c | 69 |
1 files changed, 19 insertions, 50 deletions
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index e5bbc1a5edc2..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,14 +301,12 @@ 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)) { |
| 337 | clear_thread_flag(TIF_NOTIFY_RESUME); | 308 | clear_thread_flag(TIF_NOTIFY_RESUME); |
| 338 | tracehook_notify_resume(regs); | 309 | tracehook_notify_resume(regs); |
| 339 | if (current->replacement_session_keyring) | ||
| 340 | key_replace_session_keyring(); | ||
| 341 | } | 310 | } |
| 342 | } | 311 | } |
| 343 | 312 | ||
