diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 14:53:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 14:53:44 -0400 |
commit | 86c47b70f62a7072d441ba212aab33c2f82627c2 (patch) | |
tree | d03988bd2226966352bb7f3c2e82ff545353d2c4 /arch/frv | |
parent | 1193755ac6328ad240ba987e6ec41d5e8baf0680 (diff) | |
parent | 44fbbb3dc687c9709a6f2236197316e5c79ab1eb (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull third pile of signal handling patches from Al Viro:
"This time it's mostly helpers and conversions to them; there's a lot
of stuff remaining in the tree, but that'll either go in -rc2
(isolated bug fixes, ideally via arch maintainers' trees) or will sit
there until the next cycle."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal:
x86: get rid of calling do_notify_resume() when returning to kernel mode
blackfin: check __get_user() return value
whack-a-mole with TIF_FREEZE
FRV: Optimise the system call exit path in entry.S [ver #2]
FRV: Shrink TIF_WORK_MASK [ver #2]
FRV: Prevent syscall exit tracing and notify_resume at end of kernel exceptions
new helper: signal_delivered()
powerpc: get rid of restore_sigmask()
most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set
set_restore_sigmask() is never called without SIGPENDING (and never should be)
TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set
don't call try_to_freeze() from do_signal()
pull clearing RESTORE_SIGMASK into block_sigmask()
sh64: failure to build sigframe != signal without handler
openrisc: tracehook_signal_handler() is supposed to be called on success
new helper: sigmask_to_save()
new helper: restore_saved_sigmask()
new helpers: {clear,test,test_and_clear}_restore_sigmask()
HAVE_RESTORE_SIGMASK is defined on all architectures now
Diffstat (limited to 'arch/frv')
-rw-r--r-- | arch/frv/include/asm/thread_info.h | 16 | ||||
-rw-r--r-- | arch/frv/kernel/entry.S | 29 | ||||
-rw-r--r-- | arch/frv/kernel/signal.c | 57 |
3 files changed, 35 insertions, 67 deletions
diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h index 54ab13a0de41..0ff03a33c81e 100644 --- a/arch/frv/include/asm/thread_info.h +++ b/arch/frv/include/asm/thread_info.h | |||
@@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15"); | |||
94 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ | 94 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ |
95 | #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ | 95 | #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ |
96 | #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ | 96 | #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ |
97 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 97 | #define TIF_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
98 | #define TIF_MEMDIE 17 /* is terminating due to OOM killer */ | 98 | #define TIF_MEMDIE 7 /* is terminating due to OOM killer */ |
99 | 99 | ||
100 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 100 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
101 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 101 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
@@ -105,8 +105,16 @@ register struct thread_info *__current_thread_info asm("gr15"); | |||
105 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) | 105 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) |
106 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | 106 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) |
107 | 107 | ||
108 | #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ | 108 | /* work to do on interrupt/exception return */ |
109 | #define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ | 109 | #define _TIF_WORK_MASK \ |
110 | (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP) | ||
111 | |||
112 | /* work to do on any return to u-space */ | ||
113 | #define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE) | ||
114 | |||
115 | #if _TIF_ALLWORK_MASK >= 0x2000 | ||
116 | #error "_TIF_ALLWORK_MASK won't fit in an ANDI now (see entry.S)" | ||
117 | #endif | ||
110 | 118 | ||
111 | /* | 119 | /* |
112 | * Thread-synchronous status. | 120 | * Thread-synchronous status. |
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 5ba23f715ea5..7d5e000fd32e 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S | |||
@@ -905,18 +905,19 @@ __syscall_call: | |||
905 | __syscall_exit: | 905 | __syscall_exit: |
906 | LEDS 0x6300 | 906 | LEDS 0x6300 |
907 | 907 | ||
908 | sti gr8,@(gr28,#REG_GR(8)) ; save return value | 908 | # keep current PSR in GR23 |
909 | movsg psr,gr23 | ||
909 | 910 | ||
910 | # rebuild saved psr - execve will change it for init/main.c | ||
911 | ldi @(gr28,#REG_PSR),gr22 | 911 | ldi @(gr28,#REG_PSR),gr22 |
912 | |||
913 | sti.p gr8,@(gr28,#REG_GR(8)) ; save return value | ||
914 | |||
915 | # rebuild saved psr - execve will change it for init/main.c | ||
912 | srli gr22,#1,gr5 | 916 | srli gr22,#1,gr5 |
913 | andi.p gr22,#~PSR_PS,gr22 | 917 | andi.p gr22,#~PSR_PS,gr22 |
914 | andi gr5,#PSR_PS,gr5 | 918 | andi gr5,#PSR_PS,gr5 |
915 | or gr5,gr22,gr22 | 919 | or gr5,gr22,gr22 |
916 | ori gr22,#PSR_S,gr22 | 920 | ori.p gr22,#PSR_S,gr22 |
917 | |||
918 | # keep current PSR in GR23 | ||
919 | movsg psr,gr23 | ||
920 | 921 | ||
921 | # make sure we don't miss an interrupt setting need_resched or sigpending between | 922 | # make sure we don't miss an interrupt setting need_resched or sigpending between |
922 | # sampling and the RETT | 923 | # sampling and the RETT |
@@ -924,9 +925,7 @@ __syscall_exit: | |||
924 | movgs gr23,psr | 925 | movgs gr23,psr |
925 | 926 | ||
926 | ldi @(gr15,#TI_FLAGS),gr4 | 927 | ldi @(gr15,#TI_FLAGS),gr4 |
927 | sethi.p %hi(_TIF_ALLWORK_MASK),gr5 | 928 | andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0 |
928 | setlo %lo(_TIF_ALLWORK_MASK),gr5 | ||
929 | andcc gr4,gr5,gr0,icc0 | ||
930 | bne icc0,#0,__syscall_exit_work | 929 | bne icc0,#0,__syscall_exit_work |
931 | 930 | ||
932 | # restore all registers and return | 931 | # restore all registers and return |
@@ -1111,9 +1110,7 @@ __entry_resume_userspace: | |||
1111 | __entry_return_from_user_interrupt: | 1110 | __entry_return_from_user_interrupt: |
1112 | LEDS 0x6402 | 1111 | LEDS 0x6402 |
1113 | ldi @(gr15,#TI_FLAGS),gr4 | 1112 | ldi @(gr15,#TI_FLAGS),gr4 |
1114 | sethi.p %hi(_TIF_WORK_MASK),gr5 | 1113 | andicc gr4,#_TIF_WORK_MASK,gr0,icc0 |
1115 | setlo %lo(_TIF_WORK_MASK),gr5 | ||
1116 | andcc gr4,gr5,gr0,icc0 | ||
1117 | beq icc0,#1,__entry_return_direct | 1114 | beq icc0,#1,__entry_return_direct |
1118 | 1115 | ||
1119 | __entry_work_pending: | 1116 | __entry_work_pending: |
@@ -1133,9 +1130,7 @@ __entry_work_resched: | |||
1133 | 1130 | ||
1134 | LEDS 0x6401 | 1131 | LEDS 0x6401 |
1135 | ldi @(gr15,#TI_FLAGS),gr4 | 1132 | ldi @(gr15,#TI_FLAGS),gr4 |
1136 | sethi.p %hi(_TIF_WORK_MASK),gr5 | 1133 | andicc gr4,#_TIF_WORK_MASK,gr0,icc0 |
1137 | setlo %lo(_TIF_WORK_MASK),gr5 | ||
1138 | andcc gr4,gr5,gr0,icc0 | ||
1139 | beq icc0,#1,__entry_return_direct | 1134 | beq icc0,#1,__entry_return_direct |
1140 | andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 | 1135 | andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 |
1141 | bne icc0,#1,__entry_work_resched | 1136 | bne icc0,#1,__entry_work_resched |
@@ -1163,7 +1158,9 @@ __syscall_trace_entry: | |||
1163 | # perform syscall exit tracing | 1158 | # perform syscall exit tracing |
1164 | __syscall_exit_work: | 1159 | __syscall_exit_work: |
1165 | LEDS 0x6340 | 1160 | LEDS 0x6340 |
1166 | andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 | 1161 | andicc gr22,#PSR_PS,gr0,icc1 ; don't handle on return to kernel mode |
1162 | andicc.p gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 | ||
1163 | bne icc1,#0,__entry_return_direct | ||
1167 | beq icc0,#1,__entry_work_pending | 1164 | beq icc0,#1,__entry_work_pending |
1168 | 1165 | ||
1169 | movsg psr,gr23 | 1166 | movsg psr,gr23 |
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 595bf1e5a5dc..f3b9064c548c 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -28,8 +28,6 @@ | |||
28 | 28 | ||
29 | #define DEBUG_SIG 0 | 29 | #define DEBUG_SIG 0 |
30 | 30 | ||
31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
32 | |||
33 | struct fdpic_func_descriptor { | 31 | struct fdpic_func_descriptor { |
34 | unsigned long text; | 32 | unsigned long text; |
35 | unsigned long GOT; | 33 | unsigned long GOT; |
@@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void) | |||
149 | __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) | 147 | __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) |
150 | goto badframe; | 148 | goto badframe; |
151 | 149 | ||
152 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
153 | set_current_blocked(&set); | 150 | set_current_blocked(&set); |
154 | 151 | ||
155 | if (restore_sigcontext(&frame->sc, &gr8)) | 152 | if (restore_sigcontext(&frame->sc, &gr8)) |
@@ -172,7 +169,6 @@ asmlinkage int sys_rt_sigreturn(void) | |||
172 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | 169 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
173 | goto badframe; | 170 | goto badframe; |
174 | 171 | ||
175 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
176 | set_current_blocked(&set); | 172 | set_current_blocked(&set); |
177 | 173 | ||
178 | if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) | 174 | if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) |
@@ -426,9 +422,10 @@ give_sigsegv: | |||
426 | /* | 422 | /* |
427 | * OK, we're invoking a handler | 423 | * OK, we're invoking a handler |
428 | */ | 424 | */ |
429 | static int handle_signal(unsigned long sig, siginfo_t *info, | 425 | static void handle_signal(unsigned long sig, siginfo_t *info, |
430 | struct k_sigaction *ka, sigset_t *oldset) | 426 | struct k_sigaction *ka) |
431 | { | 427 | { |
428 | sigset_t *oldset = sigmask_to_save(); | ||
432 | int ret; | 429 | int ret; |
433 | 430 | ||
434 | /* Are we from a system call? */ | 431 | /* Are we from a system call? */ |
@@ -460,11 +457,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
460 | else | 457 | else |
461 | ret = setup_frame(sig, ka, oldset); | 458 | ret = setup_frame(sig, ka, oldset); |
462 | 459 | ||
463 | if (ret == 0) | 460 | if (ret) |
464 | block_sigmask(ka, sig); | 461 | return; |
465 | |||
466 | return ret; | ||
467 | 462 | ||
463 | signal_delivered(sig, info, ka, __frame, | ||
464 | test_thread_flag(TIF_SINGLESTEP)); | ||
468 | } /* end handle_signal() */ | 465 | } /* end handle_signal() */ |
469 | 466 | ||
470 | /*****************************************************************************/ | 467 | /*****************************************************************************/ |
@@ -477,44 +474,14 @@ static void do_signal(void) | |||
477 | { | 474 | { |
478 | struct k_sigaction ka; | 475 | struct k_sigaction ka; |
479 | siginfo_t info; | 476 | siginfo_t info; |
480 | sigset_t *oldset; | ||
481 | int signr; | 477 | int signr; |
482 | 478 | ||
483 | /* | ||
484 | * We want the common case to go fast, which | ||
485 | * is why we may in certain cases get here from | ||
486 | * kernel mode. Just return without doing anything | ||
487 | * if so. | ||
488 | */ | ||
489 | if (!user_mode(__frame)) | ||
490 | return; | ||
491 | |||
492 | if (try_to_freeze()) | ||
493 | goto no_signal; | ||
494 | |||
495 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
496 | oldset = ¤t->saved_sigmask; | ||
497 | else | ||
498 | oldset = ¤t->blocked; | ||
499 | |||
500 | signr = get_signal_to_deliver(&info, &ka, __frame, NULL); | 479 | signr = get_signal_to_deliver(&info, &ka, __frame, NULL); |
501 | if (signr > 0) { | 480 | if (signr > 0) { |
502 | if (handle_signal(signr, &info, &ka, oldset) == 0) { | 481 | handle_signal(signr, &info, &ka); |
503 | /* a signal was successfully delivered; the saved | ||
504 | * sigmask will have been stored in the signal frame, | ||
505 | * and will be restored by sigreturn, so we can simply | ||
506 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
507 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
508 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
509 | |||
510 | tracehook_signal_handler(signr, &info, &ka, __frame, | ||
511 | test_thread_flag(TIF_SINGLESTEP)); | ||
512 | } | ||
513 | |||
514 | return; | 482 | return; |
515 | } | 483 | } |
516 | 484 | ||
517 | no_signal: | ||
518 | /* Did we come from a system call? */ | 485 | /* Did we come from a system call? */ |
519 | if (__frame->syscallno != -1) { | 486 | if (__frame->syscallno != -1) { |
520 | /* Restart the system call - no handlers present */ | 487 | /* Restart the system call - no handlers present */ |
@@ -536,11 +503,7 @@ no_signal: | |||
536 | 503 | ||
537 | /* if there's no signal to deliver, we just put the saved sigmask | 504 | /* if there's no signal to deliver, we just put the saved sigmask |
538 | * back */ | 505 | * back */ |
539 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 506 | restore_saved_sigmask(); |
540 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
541 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
542 | } | ||
543 | |||
544 | } /* end do_signal() */ | 507 | } /* end do_signal() */ |
545 | 508 | ||
546 | /*****************************************************************************/ | 509 | /*****************************************************************************/ |
@@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) | |||
555 | clear_thread_flag(TIF_SINGLESTEP); | 518 | clear_thread_flag(TIF_SINGLESTEP); |
556 | 519 | ||
557 | /* deal with pending signal delivery */ | 520 | /* deal with pending signal delivery */ |
558 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 521 | if (thread_info_flags & _TIF_SIGPENDING)) |
559 | do_signal(); | 522 | do_signal(); |
560 | 523 | ||
561 | /* deal with notification on about to resume userspace execution */ | 524 | /* deal with notification on about to resume userspace execution */ |