aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 21:11:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 21:11:45 -0400
commitf9369910a6225b8d4892c3f20ae740a711cd5ace (patch)
tree8650ff79d7607bceb35509c028400ecf1c317de0 /arch/microblaze
parent05f144a0d5c2207a0349348127f996e104ad7404 (diff)
parent415d04d08fec74b226c92c1fb54ad117c9c6bac4 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull first series of signal handling cleanups from Al Viro: "This is just the first part of the queue (about a half of it); assorted fixes all over the place in signal handling. This one ends with all sigsuspend() implementations switched to generic one (->saved_sigmask-based). With this, a bunch of assorted old buglets are fixed and most of the missing bits of NOTIFY_RESUME hookup are in place. Two more fixes sit in arm and um trees respectively, and there's a couple of broken ones that need obvious fixes - parisc and avr32 check TIF_NOTIFY_RESUME only on one of two codepaths; fixes for that will happen in the next series" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (55 commits) unicore32: if there's no handler we need to restore sigmask, syscall or no syscall xtensa: add handling of TIF_NOTIFY_RESUME microblaze: drop 'oldset' argument of do_notify_resume() microblaze: handle TIF_NOTIFY_RESUME score: add handling of NOTIFY_RESUME to do_notify_resume() m68k: add TIF_NOTIFY_RESUME and handle it. sparc: kill ancient comment in sparc_sigaction() h8300: missing checks of __get_user()/__put_user() return values frv: missing checks of __get_user()/__put_user() return values cris: missing checks of __get_user()/__put_user() return values powerpc: missing checks of __get_user()/__put_user() return values sh: missing checks of __get_user()/__put_user() return values sparc: missing checks of __get_user()/__put_user() return values avr32: struct old_sigaction is never used m32r: struct old_sigaction is never used xtensa: xtensa_sigaction doesn't exist alpha: tidy signal delivery up score: don't open-code force_sigsegv() cris: don't open-code force_sigsegv() blackfin: don't open-code force_sigsegv() ...
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/kernel/entry-nommu.S20
-rw-r--r--arch/microblaze/kernel/entry.S30
-rw-r--r--arch/microblaze/kernel/signal.c85
3 files changed, 65 insertions, 70 deletions
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 34b526f59b43..75c3ea1f48a1 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -132,11 +132,10 @@ ret_from_intr:
132 beqi r11, 1f 132 beqi r11, 1f
133 bralid r15, schedule 133 bralid r15, schedule
134 nop 134 nop
1351: andi r11, r19, _TIF_SIGPENDING 1351: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
136 beqid r11, no_intr_resched 136 beqid r11, no_intr_resched
137 addk r5, r1, r0 137 addk r5, r1, r0
138 addk r7, r0, r0 138 bralid r15, do_notify_resume
139 bralid r15, do_signal
140 addk r6, r0, r0 139 addk r6, r0, r0
141 140
142no_intr_resched: 141no_intr_resched:
@@ -292,8 +291,8 @@ ENTRY(_user_exception)
292 291
293/* 292/*
294 * Debug traps are like a system call, but entered via brki r14, 0x60 293 * Debug traps are like a system call, but entered via brki r14, 0x60
295 * All we need to do is send the SIGTRAP signal to current, ptrace and do_signal 294 * All we need to do is send the SIGTRAP signal to current, ptrace and
296 * will handle the rest 295 * do_notify_resume will handle the rest
297 */ 296 */
298ENTRY(_debug_exception) 297ENTRY(_debug_exception)
299 swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */ 298 swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
@@ -482,12 +481,11 @@ work_pending:
482 beqi r11, 1f 481 beqi r11, 1f
483 bralid r15, schedule 482 bralid r15, schedule
484 nop 483 nop
4851: andi r11, r19, _TIF_SIGPENDING 4841: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
486 beqi r11, no_work_pending 485 beqi r11, no_work_pending
487 addk r5, r1, r0 486 addk r5, r1, r0
488 addik r7, r0, 1 487 bralid r15, do_notify_resume
489 bralid r15, do_signal 488 addik r6, r0, 1
490 addk r6, r0, r0
491 bri no_work_pending 489 bri no_work_pending
492 490
493ENTRY(ret_to_user) 491ENTRY(ret_to_user)
@@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper:
569 brid sys_rt_sigreturn 567 brid sys_rt_sigreturn
570 addk r5, r1, r0 568 addk r5, r1, r0
571 569
572sys_rt_sigsuspend_wrapper:
573 brid sys_rt_sigsuspend
574 addk r7, r1, r0
575
576 /* Interrupt vector table */ 570 /* Interrupt vector table */
577 .section .init.ivt, "ax" 571 .section .init.ivt, "ax"
578 .org 0x0 572 .org 0x0
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 66e34a3bfe1b..daff9e5e4a1f 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap):
4305: /* get thread info from current task*/ 4305: /* get thread info from current task*/
431 lwi r11, CURRENT_TASK, TS_THREAD_INFO; 431 lwi r11, CURRENT_TASK, TS_THREAD_INFO;
432 lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 432 lwi r11, r11, TI_FLAGS; /* get flags in thread info */
433 andi r11, r11, _TIF_SIGPENDING; 433 andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
434 beqi r11, 1f; /* Signals to handle, handle them */ 434 beqi r11, 1f; /* Signals to handle, handle them */
435 435
436 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 436 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
437 addi r7, r0, 1; /* Arg 3: int in_syscall */ 437 bralid r15, do_notify_resume; /* Handle any signals */
438 bralid r15, do_signal; /* Handle any signals */ 438 addi r6, r0, 1; /* Arg 2: int in_syscall */
439 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
440 439
441/* Finally, return to user state. */ 440/* Finally, return to user state. */
4421: set_bip; /* Ints masked for state restore */ 4411: set_bip; /* Ints masked for state restore */
@@ -622,7 +621,7 @@ C_ENTRY(ret_from_exc):
622 /* Maybe handle a signal */ 621 /* Maybe handle a signal */
6235: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 6225: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
624 lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 623 lwi r11, r11, TI_FLAGS; /* get flags in thread info */
625 andi r11, r11, _TIF_SIGPENDING; 624 andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
626 beqi r11, 1f; /* Signals to handle, handle them */ 625 beqi r11, 1f; /* Signals to handle, handle them */
627 626
628 /* 627 /*
@@ -635,11 +634,10 @@ C_ENTRY(ret_from_exc):
635 * traps), but signal handlers may want to examine or change the 634 * traps), but signal handlers may want to examine or change the
636 * complete register state. Here we save anything not saved by 635 * complete register state. Here we save anything not saved by
637 * the normal entry sequence, so that it may be safely restored 636 * the normal entry sequence, so that it may be safely restored
638 * (in a possibly modified form) after do_signal returns. */ 637 * (in a possibly modified form) after do_notify_resume returns. */
639 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 638 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
640 addi r7, r0, 0; /* Arg 3: int in_syscall */ 639 bralid r15, do_notify_resume; /* Handle any signals */
641 bralid r15, do_signal; /* Handle any signals */ 640 addi r6, r0, 0; /* Arg 2: int in_syscall */
642 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
643 641
644/* Finally, return to user state. */ 642/* Finally, return to user state. */
6451: set_bip; /* Ints masked for state restore */ 6431: set_bip; /* Ints masked for state restore */
@@ -732,13 +730,12 @@ ret_from_irq:
732 /* Maybe handle a signal */ 730 /* Maybe handle a signal */
7335: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */ 7315: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
734 lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 732 lwi r11, r11, TI_FLAGS; /* get flags in thread info */
735 andi r11, r11, _TIF_SIGPENDING; 733 andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
736 beqid r11, no_intr_resched 734 beqid r11, no_intr_resched
737/* Handle a signal return; Pending signals should be in r18. */ 735/* Handle a signal return; Pending signals should be in r18. */
738 addi r7, r0, 0; /* Arg 3: int in_syscall */
739 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 736 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
740 bralid r15, do_signal; /* Handle any signals */ 737 bralid r15, do_notify_resume; /* Handle any signals */
741 add r6, r0, r0; /* Arg 2: sigset_t *oldset */ 738 addi r6, r0, 0; /* Arg 2: int in_syscall */
742 739
743/* Finally, return to user state. */ 740/* Finally, return to user state. */
744no_intr_resched: 741no_intr_resched:
@@ -869,13 +866,12 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
869 /* Maybe handle a signal */ 866 /* Maybe handle a signal */
8705: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 8675: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
871 lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 868 lwi r11, r11, TI_FLAGS; /* get flags in thread info */
872 andi r11, r11, _TIF_SIGPENDING; 869 andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
873 beqi r11, 1f; /* Signals to handle, handle them */ 870 beqi r11, 1f; /* Signals to handle, handle them */
874 871
875 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 872 addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
876 addi r7, r0, 0; /* Arg 3: int in_syscall */ 873 bralid r15, do_notify_resume; /* Handle any signals */
877 bralid r15, do_signal; /* Handle any signals */ 874 addi r6, r0, 0; /* Arg 2: int in_syscall */
878 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
879 875
880/* Finally, return to user state. */ 876/* Finally, return to user state. */
8811: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 8771: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
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
45asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
46
47asmlinkage long 46asmlinkage long
48sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 47sys_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(&current->sighand->siglock); 110 set_current_blocked(&set);
109 current->blocked = set;
110 recalc_sigpending();
111 spin_unlock_irq(&current->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
172static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 171static 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
272give_sigsegv: 271give_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
316handle_signal(unsigned long sig, struct k_sigaction *ka, 314handle_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(&current->sighand->siglock); 329
330 sigorsets(&current->blocked, 330 return 0;
331 &current->blocked, &ka->sa.sa_mask);
332 sigaddset(&current->blocked, sig);
333 recalc_sigpending();
334 spin_unlock_irq(&current->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 */
348int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) 342static 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 = &current->saved_sigmask; 355 oldset = &current->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, &current->saved_sigmask, NULL); 386 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
400 } 387 }
388}
401 389
402 /* Did we come from a system call? */ 390void 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}