diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 20:53:44 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 20:53:44 +0200 |
commit | 86c47b70f62a7072d441ba212aab33c2f82627c2 (patch) | |
tree | d03988bd2226966352bb7f3c2e82ff545353d2c4 /arch/frv | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vir... (diff) | |
parent | x86: get rid of calling do_notify_resume() when returning to kernel mode (diff) | |
download | linux-86c47b70f62a7072d441ba212aab33c2f82627c2.tar.xz linux-86c47b70f62a7072d441ba212aab33c2f82627c2.zip |
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"); #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ -#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ -#define TIF_MEMDIE 17 /* is terminating due to OOM killer */ +#define TIF_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_MEMDIE 7 /* is terminating due to OOM killer */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) @@ -105,8 +105,16 @@ register struct thread_info *__current_thread_info asm("gr15"); #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) -#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ -#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ +/* work to do on interrupt/exception return */ +#define _TIF_WORK_MASK \ + (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP) + +/* work to do on any return to u-space */ +#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE) + +#if _TIF_ALLWORK_MASK >= 0x2000 +#error "_TIF_ALLWORK_MASK won't fit in an ANDI now (see entry.S)" +#endif /* * 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: __syscall_exit: LEDS 0x6300 - sti gr8,@(gr28,#REG_GR(8)) ; save return value + # keep current PSR in GR23 + movsg psr,gr23 - # rebuild saved psr - execve will change it for init/main.c ldi @(gr28,#REG_PSR),gr22 + + sti.p gr8,@(gr28,#REG_GR(8)) ; save return value + + # rebuild saved psr - execve will change it for init/main.c srli gr22,#1,gr5 andi.p gr22,#~PSR_PS,gr22 andi gr5,#PSR_PS,gr5 or gr5,gr22,gr22 - ori gr22,#PSR_S,gr22 - - # keep current PSR in GR23 - movsg psr,gr23 + ori.p gr22,#PSR_S,gr22 # make sure we don't miss an interrupt setting need_resched or sigpending between # sampling and the RETT @@ -924,9 +925,7 @@ __syscall_exit: movgs gr23,psr ldi @(gr15,#TI_FLAGS),gr4 - sethi.p %hi(_TIF_ALLWORK_MASK),gr5 - setlo %lo(_TIF_ALLWORK_MASK),gr5 - andcc gr4,gr5,gr0,icc0 + andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0 bne icc0,#0,__syscall_exit_work # restore all registers and return @@ -1111,9 +1110,7 @@ __entry_resume_userspace: __entry_return_from_user_interrupt: LEDS 0x6402 ldi @(gr15,#TI_FLAGS),gr4 - sethi.p %hi(_TIF_WORK_MASK),gr5 - setlo %lo(_TIF_WORK_MASK),gr5 - andcc gr4,gr5,gr0,icc0 + andicc gr4,#_TIF_WORK_MASK,gr0,icc0 beq icc0,#1,__entry_return_direct __entry_work_pending: @@ -1133,9 +1130,7 @@ __entry_work_resched: LEDS 0x6401 ldi @(gr15,#TI_FLAGS),gr4 - sethi.p %hi(_TIF_WORK_MASK),gr5 - setlo %lo(_TIF_WORK_MASK),gr5 - andcc gr4,gr5,gr0,icc0 + andicc gr4,#_TIF_WORK_MASK,gr0,icc0 beq icc0,#1,__entry_return_direct andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 bne icc0,#1,__entry_work_resched @@ -1163,7 +1158,9 @@ __syscall_trace_entry: # perform syscall exit tracing __syscall_exit_work: LEDS 0x6340 - andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 + andicc gr22,#PSR_PS,gr0,icc1 ; don't handle on return to kernel mode + andicc.p gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 + bne icc1,#0,__entry_return_direct beq icc0,#1,__entry_work_pending 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 @@ #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - struct fdpic_func_descriptor { unsigned long text; unsigned long GOT; @@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void) __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(&frame->sc, &gr8)) @@ -172,7 +169,6 @@ asmlinkage int sys_rt_sigreturn(void) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) @@ -426,9 +422,10 @@ give_sigsegv: /* * OK, we're invoking a handler */ -static int handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, sigset_t *oldset) +static void handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka) { + sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ @@ -460,11 +457,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, else ret = setup_frame(sig, ka, oldset); - if (ret == 0) - block_sigmask(ka, sig); - - return ret; + if (ret) + return; + signal_delivered(sig, info, ka, __frame, + test_thread_flag(TIF_SINGLESTEP)); } /* end handle_signal() */ /*****************************************************************************/ @@ -477,44 +474,14 @@ static void do_signal(void) { struct k_sigaction ka; siginfo_t info; - sigset_t *oldset; int signr; - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(__frame)) - return; - - if (try_to_freeze()) - goto no_signal; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, __frame, NULL); if (signr > 0) { - if (handle_signal(signr, &info, &ka, oldset) == 0) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - tracehook_signal_handler(signr, &info, &ka, __frame, - test_thread_flag(TIF_SINGLESTEP)); - } - + handle_signal(signr, &info, &ka); return; } -no_signal: /* Did we come from a system call? */ if (__frame->syscallno != -1) { /* Restart the system call - no handlers present */ @@ -536,11 +503,7 @@ no_signal: /* if there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - + restore_saved_sigmask(); } /* end do_signal() */ /*****************************************************************************/ @@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) clear_thread_flag(TIF_SINGLESTEP); /* deal with pending signal delivery */ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + if (thread_info_flags & _TIF_SIGPENDING)) do_signal(); /* deal with notification on about to resume userspace execution */ |