diff options
Diffstat (limited to 'arch/microblaze/kernel/signal.c')
-rw-r--r-- | arch/microblaze/kernel/signal.c | 85 |
1 files changed, 45 insertions, 40 deletions
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 599671168980..7f4c7bef1642 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/personality.h> | 31 | #include <linux/personality.h> |
32 | #include <linux/percpu.h> | 32 | #include <linux/percpu.h> |
33 | #include <linux/linkage.h> | 33 | #include <linux/linkage.h> |
34 | #include <linux/tracehook.h> | ||
34 | #include <asm/entry.h> | 35 | #include <asm/entry.h> |
35 | #include <asm/ucontext.h> | 36 | #include <asm/ucontext.h> |
36 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
@@ -42,8 +43,6 @@ | |||
42 | 43 | ||
43 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
44 | 45 | ||
45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); | ||
46 | |||
47 | asmlinkage long | 46 | asmlinkage long |
48 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 47 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
49 | struct pt_regs *regs) | 48 | struct pt_regs *regs) |
@@ -98,6 +97,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
98 | sigset_t set; | 97 | sigset_t set; |
99 | int rval; | 98 | int rval; |
100 | 99 | ||
100 | /* Always make any pending restarted system calls return -EINTR */ | ||
101 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
102 | |||
101 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 103 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
102 | goto badframe; | 104 | goto badframe; |
103 | 105 | ||
@@ -105,10 +107,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
105 | goto badframe; | 107 | goto badframe; |
106 | 108 | ||
107 | sigdelsetmask(&set, ~_BLOCKABLE); | 109 | sigdelsetmask(&set, ~_BLOCKABLE); |
108 | spin_lock_irq(¤t->sighand->siglock); | 110 | set_current_blocked(&set); |
109 | current->blocked = set; | ||
110 | recalc_sigpending(); | ||
111 | spin_unlock_irq(¤t->sighand->siglock); | ||
112 | 111 | ||
113 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) | 112 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) |
114 | goto badframe; | 113 | goto badframe; |
@@ -169,7 +168,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
169 | return (void __user *)((sp - frame_size) & -8UL); | 168 | return (void __user *)((sp - frame_size) & -8UL); |
170 | } | 169 | } |
171 | 170 | ||
172 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 171 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
173 | sigset_t *set, struct pt_regs *regs) | 172 | sigset_t *set, struct pt_regs *regs) |
174 | { | 173 | { |
175 | struct rt_sigframe __user *frame; | 174 | struct rt_sigframe __user *frame; |
@@ -267,12 +266,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
267 | current->comm, current->pid, frame, regs->pc); | 266 | current->comm, current->pid, frame, regs->pc); |
268 | #endif | 267 | #endif |
269 | 268 | ||
270 | return; | 269 | return 0; |
271 | 270 | ||
272 | give_sigsegv: | 271 | give_sigsegv: |
273 | if (sig == SIGSEGV) | 272 | force_sigsegv(sig, current); |
274 | ka->sa.sa_handler = SIG_DFL; | 273 | return -EFAULT; |
275 | force_sig(SIGSEGV, current); | ||
276 | } | 274 | } |
277 | 275 | ||
278 | /* Handle restarting system calls */ | 276 | /* Handle restarting system calls */ |
@@ -316,24 +314,20 @@ static int | |||
316 | handle_signal(unsigned long sig, struct k_sigaction *ka, | 314 | handle_signal(unsigned long sig, struct k_sigaction *ka, |
317 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | 315 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
318 | { | 316 | { |
317 | int ret; | ||
318 | |||
319 | /* Set up the stack frame */ | 319 | /* Set up the stack frame */ |
320 | if (ka->sa.sa_flags & SA_SIGINFO) | 320 | if (ka->sa.sa_flags & SA_SIGINFO) |
321 | setup_rt_frame(sig, ka, info, oldset, regs); | 321 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
322 | else | 322 | else |
323 | setup_rt_frame(sig, ka, NULL, oldset, regs); | 323 | ret = setup_rt_frame(sig, ka, NULL, oldset, regs); |
324 | 324 | ||
325 | if (ka->sa.sa_flags & SA_ONESHOT) | 325 | if (ret) |
326 | ka->sa.sa_handler = SIG_DFL; | 326 | return ret; |
327 | 327 | ||
328 | if (!(ka->sa.sa_flags & SA_NODEFER)) { | 328 | block_sigmask(ka, sig); |
329 | spin_lock_irq(¤t->sighand->siglock); | 329 | |
330 | sigorsets(¤t->blocked, | 330 | return 0; |
331 | ¤t->blocked, &ka->sa.sa_mask); | ||
332 | sigaddset(¤t->blocked, sig); | ||
333 | recalc_sigpending(); | ||
334 | spin_unlock_irq(¤t->sighand->siglock); | ||
335 | } | ||
336 | return 1; | ||
337 | } | 331 | } |
338 | 332 | ||
339 | /* | 333 | /* |
@@ -345,24 +339,17 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
345 | * the kernel can handle, and then we build all the user-level signal handling | 339 | * the kernel can handle, and then we build all the user-level signal handling |
346 | * stack-frames in one go after that. | 340 | * stack-frames in one go after that. |
347 | */ | 341 | */ |
348 | int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | 342 | static void do_signal(struct pt_regs *regs, int in_syscall) |
349 | { | 343 | { |
350 | siginfo_t info; | 344 | siginfo_t info; |
351 | int signr; | 345 | int signr; |
352 | struct k_sigaction ka; | 346 | struct k_sigaction ka; |
347 | sigset_t *oldset; | ||
353 | #ifdef DEBUG_SIG | 348 | #ifdef DEBUG_SIG |
354 | printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall); | 349 | printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall); |
355 | printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, | 350 | printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, |
356 | regs->r12, current_thread_info()->flags); | 351 | regs->r12, current_thread_info()->flags); |
357 | #endif | 352 | #endif |
358 | /* | ||
359 | * We want the common case to go fast, which | ||
360 | * is why we may in certain cases get here from | ||
361 | * kernel mode. Just return without doing anything | ||
362 | * if so. | ||
363 | */ | ||
364 | if (kernel_mode(regs)) | ||
365 | return 1; | ||
366 | 353 | ||
367 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | 354 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
368 | oldset = ¤t->saved_sigmask; | 355 | oldset = ¤t->saved_sigmask; |
@@ -374,7 +361,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
374 | /* Whee! Actually deliver the signal. */ | 361 | /* Whee! Actually deliver the signal. */ |
375 | if (in_syscall) | 362 | if (in_syscall) |
376 | handle_restart(regs, &ka, 1); | 363 | handle_restart(regs, &ka, 1); |
377 | if (handle_signal(signr, &ka, &info, oldset, regs)) { | 364 | if (!handle_signal(signr, &ka, &info, oldset, regs)) { |
378 | /* | 365 | /* |
379 | * A signal was successfully delivered; the saved | 366 | * A signal was successfully delivered; the saved |
380 | * sigmask will have been stored in the signal frame, | 367 | * sigmask will have been stored in the signal frame, |
@@ -384,7 +371,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
384 | current_thread_info()->status &= | 371 | current_thread_info()->status &= |
385 | ~TS_RESTORE_SIGMASK; | 372 | ~TS_RESTORE_SIGMASK; |
386 | } | 373 | } |
387 | return 1; | 374 | return; |
388 | } | 375 | } |
389 | 376 | ||
390 | if (in_syscall) | 377 | if (in_syscall) |
@@ -398,7 +385,25 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
398 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 385 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
399 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 386 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
400 | } | 387 | } |
388 | } | ||
401 | 389 | ||
402 | /* Did we come from a system call? */ | 390 | void do_notify_resume(struct pt_regs *regs, int in_syscall) |
403 | return 0; | 391 | { |
392 | /* | ||
393 | * We want the common case to go fast, which | ||
394 | * is why we may in certain cases get here from | ||
395 | * kernel mode. Just return without doing anything | ||
396 | * if so. | ||
397 | */ | ||
398 | if (kernel_mode(regs)) | ||
399 | return; | ||
400 | |||
401 | if (test_thread_flag(TIF_SIGPENDING)) | ||
402 | do_signal(regs, in_syscall); | ||
403 | |||
404 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | ||
405 | tracehook_notify_resume(regs); | ||
406 | if (current->replacement_session_keyring) | ||
407 | key_replace_session_keyring(); | ||
408 | } | ||
404 | } | 409 | } |