aboutsummaryrefslogtreecommitdiffstats
path: root/arch/frv
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
commit86c47b70f62a7072d441ba212aab33c2f82627c2 (patch)
treed03988bd2226966352bb7f3c2e82ff545353d2c4 /arch/frv
parent1193755ac6328ad240ba987e6ec41d5e8baf0680 (diff)
parent44fbbb3dc687c9709a6f2236197316e5c79ab1eb (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.h16
-rw-r--r--arch/frv/kernel/entry.S29
-rw-r--r--arch/frv/kernel/signal.c57
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
33struct fdpic_func_descriptor { 31struct 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 */
429static int handle_signal(unsigned long sig, siginfo_t *info, 425static 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 = &current->saved_sigmask;
497 else
498 oldset = &current->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
517no_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, &current->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 */