Commit 86c47b70 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 1193755a 44fbbb3d
...@@ -226,7 +226,6 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -226,7 +226,6 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
if (__get_user(set.sig[0], &sc->sc_mask)) if (__get_user(set.sig[0], &sc->sc_mask))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(sc, regs, sw)) if (restore_sigcontext(sc, regs, sw))
...@@ -261,7 +260,6 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, ...@@ -261,7 +260,6 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
...@@ -468,12 +466,9 @@ static inline void ...@@ -468,12 +466,9 @@ static inline void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
struct pt_regs * regs, struct switch_stack *sw) struct pt_regs * regs, struct switch_stack *sw)
{ {
sigset_t *oldset = &current->blocked; sigset_t *oldset = sigmask_to_save();
int ret; int ret;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
else else
...@@ -483,12 +478,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -483,12 +478,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
force_sigsegv(sig, current); force_sigsegv(sig, current);
return; return;
} }
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
/* A signal was successfully delivered, and the
saved sigmask was stored on the signal frame,
and will be restored by sigreturn. So we can
simply clear the restore sigmask flag. */
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
static inline void static inline void
...@@ -572,9 +562,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, ...@@ -572,9 +562,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
} }
/* If there's no signal to deliver, we just restore the saved mask. */ /* If there's no signal to deliver, we just restore the saved mask. */
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) restore_saved_sigmask();
set_current_blocked(&current->saved_sigmask);
if (single_stepping) if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */ ptrace_set_bpt(current); /* re-set breakpoint */
} }
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
#include "signal.h" #include "signal.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* For ARM syscalls, we encode the syscall number into the instruction. * For ARM syscalls, we encode the syscall number into the instruction.
*/ */
...@@ -210,10 +208,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) ...@@ -210,10 +208,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
int err; int err;
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
if (err == 0) { if (err == 0)
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
}
__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
__get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
...@@ -528,13 +524,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, ...@@ -528,13 +524,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, struct pt_regs *regs)
struct pt_regs * regs)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current; struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save();
int usig = sig; int usig = sig;
int ret; int ret;
...@@ -559,17 +555,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -559,17 +555,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
if (ret != 0) { if (ret != 0) {
force_sigsegv(sig, tsk); force_sigsegv(sig, tsk);
return ret; return;
} }
signal_delivered(sig, info, ka, regs, 0);
/*
* Block the signal if we were successful.
*/
block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, regs, 0);
return 0;
} }
/* /*
...@@ -617,8 +605,6 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -617,8 +605,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
*/ */
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
sigset_t *oldset;
/* /*
* Depending on the signal settings we may need to revert the * Depending on the signal settings we may need to revert the
* decision to restart the system call. But skip this if a * decision to restart the system call. But skip this if a
...@@ -635,20 +621,7 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -635,20 +621,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
clear_thread_flag(TIF_SYSCALL_RESTARTSYS); clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
} }
if (test_thread_flag(TIF_RESTORE_SIGMASK)) handle_signal(signr, &ka, &info, regs);
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
if (handle_signal(signr, &ka, &info, oldset, regs) == 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);
}
return; return;
} }
...@@ -663,11 +636,7 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -663,11 +636,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
set_thread_flag(TIF_SYSCALL_RESTARTSYS); set_thread_flag(TIF_SYSCALL_RESTARTSYS);
} }
/* If there's no signal to deliver, we just put the saved sigmask restore_saved_sigmask();
* back.
*/
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
set_current_blocked(&current->saved_sigmask);
} }
asmlinkage void asmlinkage void
......
...@@ -281,7 +281,7 @@ syscall_exit_work: ...@@ -281,7 +281,7 @@ syscall_exit_work:
ld.w r1, r0[TI_flags] ld.w r1, r0[TI_flags]
rjmp 1b rjmp 1b
2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME 2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
tst r1, r2 tst r1, r2
breq 3f breq 3f
unmask_interrupts unmask_interrupts
...@@ -587,7 +587,7 @@ fault_exit_work: ...@@ -587,7 +587,7 @@ fault_exit_work:
ld.w r1, r0[TI_flags] ld.w r1, r0[TI_flags]
rjmp fault_exit_work rjmp fault_exit_work
1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME 1: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
tst r1, r2 tst r1, r2
breq 2f breq 2f
unmask_interrupts unmask_interrupts
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/syscalls.h> #include <asm/syscalls.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
struct pt_regs *regs) struct pt_regs *regs)
{ {
...@@ -89,7 +87,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) ...@@ -89,7 +87,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
...@@ -224,30 +221,27 @@ static inline void setup_syscall_restart(struct pt_regs *regs) ...@@ -224,30 +221,27 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
static inline void static inline void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs, int syscall) struct pt_regs *regs, int syscall)
{ {
int ret; int ret;
/* /*
* Set up the stack frame * Set up the stack frame
*/ */
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
/* /*
* Check that the resulting registers are sane * Check that the resulting registers are sane
*/ */
ret |= !valid_user_regs(regs); ret |= !valid_user_regs(regs);
if (ret != 0) {
force_sigsegv(sig, current);
return;
}
/* /*
* Block the signal if we were successful. * Block the signal if we were successful.
*/ */
block_sigmask(ka, sig); if (ret != 0)
clear_thread_flag(TIF_RESTORE_SIGMASK); force_sigsegv(sig, current);
else
signal_delivered(sig, info, ka, regs, 0);
} }
/* /*
...@@ -255,7 +249,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -255,7 +249,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
* doesn't want to handle. Thus you cannot kill init even with a * doesn't want to handle. Thus you cannot kill init even with a
* SIGKILL even by mistake. * SIGKILL even by mistake.
*/ */
int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) static void do_signal(struct pt_regs *regs, int syscall)
{ {
siginfo_t info; siginfo_t info;
int signr; int signr;
...@@ -267,12 +261,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) ...@@ -267,12 +261,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
* without doing anything if so. * without doing anything if so.
*/ */
if (!user_mode(regs)) if (!user_mode(regs))
return 0; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (syscall) { if (syscall) {
...@@ -297,15 +286,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) ...@@ -297,15 +286,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
if (signr == 0) { if (signr == 0) {
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK); return;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
} }
handle_signal(signr, &ka, &info, oldset, regs, syscall); handle_signal(signr, &ka, &info, regs, syscall);
return 1;
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
...@@ -315,8 +300,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) ...@@ -315,8 +300,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
syscall = 1; syscall = 1;
if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (ti->flags & _TIF_SIGPENDING))
do_signal(regs, &current->blocked, syscall); do_signal(regs, syscall);
if (ti->flags & _TIF_NOTIFY_RESUME) { if (ti->flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME); clear_thread_flag(TIF_NOTIFY_RESUME);
......
...@@ -100,7 +100,6 @@ static inline struct thread_info *current_thread_info(void) ...@@ -100,7 +100,6 @@ static inline struct thread_info *current_thread_info(void)
TIF_NEED_RESCHED */ TIF_NEED_RESCHED */
#define TIF_MEMDIE 4 /* is terminating due to OOM killer */ #define TIF_MEMDIE 4 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
#define TIF_FREEZE 6 /* is freezing for suspend */
#define TIF_IRQ_SYNC 7 /* sync pipeline stage */ #define TIF_IRQ_SYNC 7 /* sync pipeline stage */
#define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ #define TIF_NOTIFY_RESUME 8 /* callback before returning to user */
#define TIF_SINGLESTEP 9 #define TIF_SINGLESTEP 9
...@@ -111,7 +110,6 @@ static inline struct thread_info *current_thread_info(void) ...@@ -111,7 +110,6 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC) #define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <asm/fixed_code.h> #include <asm/fixed_code.h>
#include <asm/syscall.h> #include <asm/syscall.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* Location of the trace bit in SYSCFG. */ /* Location of the trace bit in SYSCFG. */
#define TRACE_BITS 0x0001 #define TRACE_BITS 0x0001
...@@ -98,7 +96,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) ...@@ -98,7 +96,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
...@@ -190,17 +187,22 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, ...@@ -190,17 +187,22 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
wrusp((unsigned long)frame);
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor *) ka->sa.sa_handler; (struct fdpic_func_descriptor *) ka->sa.sa_handler;
__get_user(regs->pc, &funcptr->text); u32 pc, p3;
__get_user(regs->p3, &funcptr->GOT); err |= __get_user(pc, &funcptr->text);
err |= __get_user(p3, &funcptr->GOT);
if (err)
return -EFAULT;
regs->pc = pc;
regs->p3 = p3;
} else } else
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ka->sa.sa_handler;
wrusp((unsigned long)frame);
regs->rets = SIGRETURN_STUB; regs->rets = SIGRETURN_STUB;
regs->r0 = frame->sig; regs->r0 = frame->sig;
...@@ -208,10 +210,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, ...@@ -208,10 +210,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
regs->r2 = (unsigned long)(&frame->uc); regs->r2 = (unsigned long)(&frame->uc);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static inline void static inline void
...@@ -247,24 +245,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -247,24 +245,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
int ret;
/* are we from a system call? to see pt_regs->orig_p0 */ /* are we from a system call? to see pt_regs->orig_p0 */
if (regs->orig_p0 >= 0) if (regs->orig_p0 >= 0)
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
handle_restart(regs, ka, 1); handle_restart(regs, ka, 1);
/* set up the stack frame */ /* set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs); if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
force_sigsegv(sig, current);
if (ret == 0) else
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return ret;
} }
/* /*
...@@ -281,37 +276,16 @@ asmlinkage void do_signal(struct pt_regs *regs) ...@@ -281,37 +276,16 @@ asmlinkage void do_signal(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
current->thread.esp0 = (unsigned long)regs; current->thread.esp0 = (unsigned long)regs;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/* 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, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->orig_p0 >= 0) if (regs->orig_p0 >= 0)
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
...@@ -319,10 +293,7 @@ asmlinkage void do_signal(struct pt_regs *regs) ...@@ -319,10 +293,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
...@@ -330,7 +301,7 @@ asmlinkage void do_signal(struct pt_regs *regs) ...@@ -330,7 +301,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
*/ */
asmlinkage void do_notify_resume(struct pt_regs *regs) asmlinkage void do_notify_resume(struct pt_regs *regs)
{ {
if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK)) if (test_thread_flag(TIF_SIGPENDING))
do_signal(regs); do_signal(regs);
if (test_thread_flag(TIF_NOTIFY_RESUME)) { if (test_thread_flag(TIF_NOTIFY_RESUME)) {
......
...@@ -711,8 +711,6 @@ ENTRY(_system_call) ...@@ -711,8 +711,6 @@ ENTRY(_system_call)
jump .Lresume_userspace_1; jump .Lresume_userspace_1;
.Lsyscall_sigpending: .Lsyscall_sigpending:
cc = BITTST(r7, TIF_RESTORE_SIGMASK);
if cc jump .Lsyscall_do_signals;
cc = BITTST(r7, TIF_SIGPENDING); cc = BITTST(r7, TIF_SIGPENDING);
if cc jump .Lsyscall_do_signals; if cc jump .Lsyscall_do_signals;
cc = BITTST(r7, TIF_NOTIFY_RESUME); cc = BITTST(r7, TIF_NOTIFY_RESUME);
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* Do a signal return, undo the signal stack. * Do a signal return, undo the signal stack.
*/ */
...@@ -87,7 +85,6 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs) ...@@ -87,7 +85,6 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
...@@ -248,10 +245,9 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -248,10 +245,9 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
/* /*
* handle the actual delivery of a signal to userspace * handle the actual delivery of a signal to userspace
*/ */
static int handle_signal(int sig, static void handle_signal(int sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs, struct pt_regs *regs, int syscall)
int syscall)
{ {
int ret; int ret;
...@@ -278,11 +274,9 @@ static int handle_signal(int sig, ...@@ -278,11 +274,9 @@ static int handle_signal(int sig,
} }
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs); if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
if (ret == 0) return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
/* /*
...@@ -292,7 +286,6 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -292,7 +286,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
sigset_t *oldset;
int signr; int signr;
/* we want the common case to go fast, which is why we may in certain /* we want the common case to go fast, which is why we may in certain
...@@ -300,25 +293,9 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -300,25 +293,9 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &info, &ka, oldset, handle_signal(signr, &info, &ka, regs, syscall);
regs, syscall) == 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, regs, 0);
}
return; return;
} }
...@@ -343,10 +320,7 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -343,10 +320,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
...@@ -357,8 +331,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags, ...@@ -357,8 +331,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
int syscall) int syscall)
{ {
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & ((1 << TIF_SIGPENDING) | if (thread_info_flags & (1 << TIF_SIGPENDING))
(1 << TIF_RESTORE_SIGMASK)))
do_signal(regs, syscall); do_signal(regs, syscall);
if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) {
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */ /* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */
/* manipulate regs so that upon return, it will be re-executed */ /* manipulate regs so that upon return, it will be re-executed */
...@@ -176,7 +174,6 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, ...@@ -176,7 +174,6 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc)) if (restore_sigcontext(regs, &frame->sc))
...@@ -212,7 +209,6 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, ...@@ -212,7 +209,6 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
...@@ -415,10 +411,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -415,10 +411,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static inline int handle_signal(int canrestart, unsigned long sig, static inline void handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
...@@ -456,9 +453,7 @@ static inline int handle_signal(int canrestart, unsigned long sig, ...@@ -456,9 +453,7 @@ static inline int handle_signal(int canrestart, unsigned long sig,
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret == 0)
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
/* /*
...@@ -478,7 +473,6 @@ void do_signal(int canrestart, struct pt_regs *regs) ...@@ -478,7 +473,6 @@ void do_signal(int canrestart, struct pt_regs *regs)
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -489,23 +483,10 @@ void do_signal(int canrestart, struct pt_regs *regs) ...@@ -489,23 +483,10 @@ void do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(canrestart, signr, &info, &ka, handle_signal(canrestart, signr, &info, &ka, regs);
oldset, regs)) {
/* 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);
}
return; return;
} }
...@@ -525,8 +506,5 @@ void do_signal(int canrestart, struct pt_regs *regs) ...@@ -525,8 +506,5 @@ void do_signal(int canrestart, struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
...@@ -24,9 +24,6 @@ ...@@ -24,9 +24,6 @@
extern unsigned long cris_signal_return_page; extern unsigned long cris_signal_return_page;
/* Flag to check if a signal is blockable. */
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* A syscall in CRIS is really a "break 13" instruction, which is 2 * A syscall in CRIS is really a "break 13" instruction, which is 2
* bytes. The registers is manipulated so upon return the instruction * bytes. The registers is manipulated so upon return the instruction
...@@ -167,7 +164,6 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, ...@@ -167,7 +164,6 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc)) if (restore_sigcontext(regs, &frame->sc))
...@@ -208,7 +204,6 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, ...@@ -208,7 +204,6 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
...@@ -434,11 +429,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -434,11 +429,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
/* Invoke a signal handler to, well, handle the signal. */ /* Invoke a signal handler to, well, handle the signal. */
static inline int static inline void
handle_signal(int canrestart, unsigned long sig, handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Check if this got called from a system call. */ /* Check if this got called from a system call. */
...@@ -489,9 +485,7 @@ handle_signal(int canrestart, unsigned long sig, ...@@ -489,9 +485,7 @@ handle_signal(int canrestart, unsigned long sig,
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret == 0)
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
/* /*
...@@ -511,7 +505,6 @@ do_signal(int canrestart, struct pt_regs *regs) ...@@ -511,7 +505,6 @@ do_signal(int canrestart, struct pt_regs *regs)
int signr; int signr;
siginfo_t info; siginfo_t info;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
/* /*
* The common case should go fast, which is why this point is * The common case should go fast, which is why this point is
...@@ -521,25 +514,11 @@ do_signal(int canrestart, struct pt_regs *regs) ...@@ -521,25 +514,11 @@ do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(canrestart, signr, &info, &ka, handle_signal(canrestart, signr, &info, &ka, regs);
oldset, regs)) {
/* 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);
}
return; return;
} }
...@@ -560,10 +539,7 @@ do_signal(int canrestart, struct pt_regs *regs) ...@@ -560,10 +539,7 @@ do_signal(int canrestart, struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
asmlinkage void asmlinkage void
......
...@@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15"); ...@@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ #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_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */ #define TIF_MEMDIE 7 /* is terminating due to OOM killer */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
...@@ -105,8 +105,16 @@ register struct thread_info *__current_thread_info asm("gr15"); ...@@ -105,8 +105,16 @@ register struct thread_info *__current_thread_info asm("gr15");
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ #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. * Thread-synchronous status.
......
...@@ -905,18 +905,19 @@ __syscall_call: ...@@ -905,18 +905,19 @@ __syscall_call:
__syscall_exit: __syscall_exit:
LEDS 0x6300 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 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 srli gr22,#1,gr5
andi.p gr22,#~PSR_PS,gr22 andi.p gr22,#~PSR_PS,gr22
andi gr5,#PSR_PS,gr5 andi gr5,#PSR_PS,gr5
or gr5,gr22,gr22 or gr5,gr22,gr22
ori gr22,#PSR_S,gr22 ori.p gr22,#PSR_S,gr22
# keep current PSR in GR23
movsg psr,gr23
# make sure we don't miss an interrupt setting need_resched or sigpending between # make sure we don't miss an interrupt setting need_resched or sigpending between
# sampling and the RETT # sampling and the RETT
...@@ -924,9 +925,7 @@ __syscall_exit: ...@@ -924,9 +925,7 @@ __syscall_exit:
movgs gr23,psr movgs gr23,psr
ldi @(gr15,#TI_FLAGS),gr4 ldi @(gr15,#TI_FLAGS),gr4
sethi.p %hi(_TIF_ALLWORK_MASK),gr5 andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0
setlo %lo(_TIF_ALLWORK_MASK),gr5
andcc gr4,gr5,gr0,icc0
bne icc0,#0,__syscall_exit_work bne icc0,#0,__syscall_exit_work
# restore all registers and return # restore all registers and return
...@@ -1111,9 +1110,7 @@ __entry_resume_userspace: ...@@ -1111,9 +1110,7 @@ __entry_resume_userspace:
__entry_return_from_user_interrupt: __entry_return_from_user_interrupt:
LEDS 0x6402 LEDS 0x6402
ldi @(gr15,#TI_FLAGS),gr4 ldi @(gr15,#TI_FLAGS),gr4
sethi.p %hi(_TIF_WORK_MASK),gr5 andicc gr4,#_TIF_WORK_MASK,gr0,icc0
setlo %lo(_TIF_WORK_MASK),gr5
andcc gr4,gr5,gr0,icc0
beq icc0,#1,__entry_return_direct beq icc0,#1,__entry_return_direct
__entry_work_pending: __entry_work_pending:
...@@ -1133,9 +1130,7 @@ __entry_work_resched: ...@@ -1133,9 +1130,7 @@ __entry_work_resched:
LEDS 0x6401 LEDS 0x6401
ldi @(gr15,#TI_FLAGS),gr4 ldi @(gr15,#TI_FLAGS),gr4
sethi.p %hi(_TIF_WORK_MASK),gr5 andicc gr4,#_TIF_WORK_MASK,gr0,icc0
setlo %lo(_TIF_WORK_MASK),gr5
andcc gr4,gr5,gr0,icc0
beq icc0,#1,__entry_return_direct beq icc0,#1,__entry_return_direct
andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
bne icc0,#1,__entry_work_resched bne icc0,#1,__entry_work_resched
...@@ -1163,7 +1158,9 @@ __syscall_trace_entry: ...@@ -1163,7 +1158,9 @@ __syscall_trace_entry:
# perform syscall exit tracing # perform syscall exit tracing
__syscall_exit_work: __syscall_exit_work:
LEDS 0x6340 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 beq icc0,#1,__entry_work_pending
movsg psr,gr23 movsg psr,gr23
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
struct fdpic_func_descriptor { struct fdpic_func_descriptor {
unsigned long text; unsigned long text;
unsigned long GOT; unsigned long GOT;
...@@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void) ...@@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void)
__copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(&frame->sc, &gr8)) if (restore_sigcontext(&frame->sc, &gr8))
...@@ -172,7 +169,6 @@ asmlinkage int sys_rt_sigreturn(void) ...@@ -172,7 +169,6 @@ asmlinkage int sys_rt_sigreturn(void)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
...@@ -426,9 +422,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -426,9 +422,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset) struct k_sigaction *ka)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
...@@ -460,11 +457,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, ...@@ -460,11 +457,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
else else
ret = setup_frame(sig, ka, oldset); ret = setup_frame(sig, ka, oldset);
if (ret == 0) if (ret)
block_sigmask(ka, sig); return;
return ret;
signal_delivered(sig, info, ka, __frame,
test_thread_flag(TIF_SINGLESTEP));
} /* end handle_signal() */ } /* end handle_signal() */
/*****************************************************************************/ /*****************************************************************************/
...@@ -477,44 +474,14 @@ static void do_signal(void) ...@@ -477,44 +474,14 @@ static void do_signal(void)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
sigset_t *oldset;
int signr; 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 = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, __frame, NULL); signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &info, &ka, oldset) == 0) { handle_signal(signr, &info, &ka);
/* 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));
}
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (__frame->syscallno != -1) { if (__frame->syscallno != -1) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
...@@ -536,11 +503,7 @@ static void do_signal(void) ...@@ -536,11 +503,7 @@ static void do_signal(void)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} /* end do_signal() */ } /* end do_signal() */
/*****************************************************************************/ /*****************************************************************************/
...@@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) ...@@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
clear_thread_flag(TIF_SINGLESTEP); clear_thread_flag(TIF_SINGLESTEP);
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (thread_info_flags & _TIF_SIGPENDING))
do_signal(); do_signal();
/* deal with notification on about to resume userspace execution */ /* deal with notification on about to resume userspace execution */
......
...@@ -47,8 +47,6 @@ ...@@ -47,8 +47,6 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
...@@ -186,7 +184,6 @@ asmlinkage int do_sigreturn(unsigned long __unused,...) ...@@ -186,7 +184,6 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, &er0)) if (restore_sigcontext(regs, &frame->sc, &er0))
...@@ -211,7 +208,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...) ...@@ -211,7 +208,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
...@@ -412,8 +408,9 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -412,8 +408,9 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_er0 >= 0) { if (regs->orig_er0 >= 0) {
...@@ -441,10 +438,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -441,10 +438,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (!ret) { if (!ret)
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
} }
/* /*
...@@ -457,7 +452,6 @@ statis void do_signal(struct pt_regs *regs) ...@@ -457,7 +452,6 @@ statis void do_signal(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -468,23 +462,14 @@ statis void do_signal(struct pt_regs *regs) ...@@ -468,23 +462,14 @@ statis void do_signal(struct pt_regs *regs)
if ((regs->ccr & 0x10)) if ((regs->ccr & 0x10))
return; return;
if (try_to_freeze())
goto no_signal;
current->thread.esp0 = (unsigned long) regs; current->thread.esp0 = (unsigned long) regs;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, oldset, regs); handle_signal(signr, &info, &ka, regs);
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->orig_er0 >= 0) { if (regs->orig_er0 >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
...@@ -501,8 +486,7 @@ statis void do_signal(struct pt_regs *regs) ...@@ -501,8 +486,7 @@ statis void do_signal(struct pt_regs *regs)
} }
/* If there's no signal to deliver, we just restore the saved mask. */ /* If there's no signal to deliver, we just restore the saved mask. */
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) restore_saved_sigmask();
set_current_blocked(&current->saved_sigmask);
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#include <asm/signal.h> #include <asm/signal.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
struct rt_sigframe { struct rt_sigframe {
unsigned long tramp[2]; unsigned long tramp[2];
struct siginfo info; struct siginfo info;
...@@ -149,11 +147,9 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -149,11 +147,9 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
/* /*
* Setup invocation of signal handler * Setup invocation of signal handler
*/ */
static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
int rc;
/* /*
* If we're handling a signal that aborted a system call, * If we're handling a signal that aborted a system call,
* set up the error return value before adding the signal * set up the error return value before adding the signal
...@@ -186,15 +182,12 @@ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -186,15 +182,12 @@ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
* Set up the stack frame; not doing the SA_SIGINFO thing. We * Set up the stack frame; not doing the SA_SIGINFO thing. We
* only set up the rt_frame flavor. * only set up the rt_frame flavor.
*/ */
rc = setup_rt_frame(sig, ka, info, oldset, regs);
/* If there was an error on setup, no signal was delivered. */ /* If there was an error on setup, no signal was delivered. */
if (rc) if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
return rc; return;
block_sigmask(ka, sig);
return 0; signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
...@@ -209,34 +202,13 @@ static void do_signal(struct pt_regs *regs) ...@@ -209,34 +202,13 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (try_to_freeze())
goto no_signal;
signo = get_signal_to_deliver(&info, &sigact, regs, NULL); signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
if (signo > 0) { if (signo > 0) {
sigset_t *oldset; handle_signal(signo, &info, &sigact, regs);
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
/*
* Successful delivery case. The saved sigmask is
* stored in the signal frame, and will be restored
* by sigreturn. We can clear the TIF flag.
*/
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signo, &info, &sigact, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }
no_signal:
/* /*
* If we came from a system call, handle the restart. * If we came from a system call, handle the restart.
*/ */
...@@ -259,10 +231,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -259,10 +231,7 @@ static void do_signal(struct pt_regs *regs)
no_restart: no_restart:
/* If there's no signal to deliver, put the saved sigmask back */ /* If there's no signal to deliver, put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
...@@ -301,7 +270,6 @@ asmlinkage int sys_rt_sigreturn(void) ...@@ -301,7 +270,6 @@ asmlinkage int sys_rt_sigreturn(void)
if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked))) if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
goto badframe; goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
set_current_blocked(&blocked); set_current_blocked(&blocked);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
......
...@@ -141,7 +141,23 @@ static inline void set_restore_sigmask(void) ...@@ -141,7 +141,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, &ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define STACK_ALIGN 16 /* minimal alignment for stack pointer */ #define STACK_ALIGN 16 /* minimal alignment for stack pointer */
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#if _NSIG_WORDS > 1 #if _NSIG_WORDS > 1
# define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t)) # define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t))
...@@ -200,7 +199,6 @@ ia64_rt_sigreturn (struct sigscratch *scr) ...@@ -200,7 +199,6 @@ ia64_rt_sigreturn (struct sigscratch *scr)
if (GET_SIGSET(&set, &sc->sc_mask)) if (GET_SIGSET(&set, &sc->sc_mask))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(sc, scr)) if (restore_sigcontext(sc, scr))
...@@ -415,18 +413,13 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, ...@@ -415,18 +413,13 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
} }
static long static long
handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
struct sigscratch *scr) struct sigscratch *scr)
{ {
if (!setup_frame(sig, ka, info, oldset, scr)) if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
return 0; return 0;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, &scr->pt,
/*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(sig, info, ka, &scr->pt,
test_thread_flag(TIF_SINGLESTEP)); test_thread_flag(TIF_SINGLESTEP));
return 1; return 1;
...@@ -440,7 +433,6 @@ void ...@@ -440,7 +433,6 @@ void
ia64_do_signal (struct sigscratch *scr, long in_syscall) ia64_do_signal (struct sigscratch *scr, long in_syscall)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
long restart = in_syscall; long restart = in_syscall;
long errno = scr->pt.r8; long errno = scr->pt.r8;
...@@ -453,11 +445,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) ...@@ -453,11 +445,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
if (!user_mode(&scr->pt)) if (!user_mode(&scr->pt))
return; return;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
/* /*
* This only loops in the rare cases of handle_signal() failing, in which case we * This only loops in the rare cases of handle_signal() failing, in which case we
* need to push through a forced SIGSEGV. * need to push through a forced SIGSEGV.
...@@ -507,16 +494,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) ...@@ -507,16 +494,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to * Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV... * continue to iterate in this loop so we can deliver the SIGSEGV...
*/ */
if (handle_signal(signr, &ka, &info, oldset, scr)) { if (handle_signal(signr, &ka, &info, scr))
/*
* 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 TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
return; return;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
...@@ -538,8 +517,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) ...@@ -538,8 +517,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r2, unsigned long r3, unsigned long r4,
...@@ -111,7 +109,6 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1, ...@@ -111,7 +109,6 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
...@@ -267,9 +264,9 @@ static int prev_insn(struct pt_regs *regs) ...@@ -267,9 +264,9 @@ static int prev_insn(struct pt_regs *regs)
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->syscall_nr >= 0) { if (regs->syscall_nr >= 0) {
...@@ -294,11 +291,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -294,11 +291,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
} }
/* Set up the stack frame */ /* Set up the stack frame */
if (setup_rt_frame(sig, ka, info, oldset, regs)) if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
return -EFAULT; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return 0;
} }
/* /*
...@@ -311,7 +307,6 @@ static void do_signal(struct pt_regs *regs) ...@@ -311,7 +307,6 @@ static void do_signal(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -322,14 +317,6 @@ static void do_signal(struct pt_regs *regs) ...@@ -322,14 +317,6 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Re-enable any watchpoints before delivering the /* Re-enable any watchpoints before delivering the
...@@ -339,13 +326,11 @@ static void do_signal(struct pt_regs *regs) ...@@ -339,13 +326,11 @@ static void do_signal(struct pt_regs *regs)
*/ */
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) handle_signal(signr, &ka, &info, regs);
clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->syscall_nr >= 0) { if (regs->syscall_nr >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
...@@ -360,10 +345,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -360,10 +345,7 @@ static void do_signal(struct pt_regs *regs)
prev_insn(regs); prev_insn(regs);
} }
} }
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
......
...@@ -51,8 +51,6 @@ ...@@ -51,8 +51,6 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
/* /*
...@@ -795,7 +793,6 @@ asmlinkage int do_sigreturn(unsigned long __unused) ...@@ -795,7 +793,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, frame + 1)) if (restore_sigcontext(regs, &frame->sc, frame + 1))
...@@ -820,7 +817,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) ...@@ -820,7 +817,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (rt_restore_ucontext(regs, sw, &frame->uc)) if (rt_restore_ucontext(regs, sw, &frame->uc))
...@@ -1123,8 +1119,9 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -1123,8 +1119,9 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
*/ */
static void static void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int err; int err;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_d0 >= 0) if (regs->orig_d0 >= 0)
...@@ -1140,14 +1137,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -1140,14 +1137,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err) if (err)
return; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
if (test_thread_flag(TIF_DELAYED_TRACE)) { if (test_thread_flag(TIF_DELAYED_TRACE)) {
regs->sr &= ~0x8000; regs->sr &= ~0x8000;
send_sig(SIGTRAP, current, 1); send_sig(SIGTRAP, current, 1);
} }
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
/* /*
...@@ -1160,19 +1155,13 @@ static void do_signal(struct pt_regs *regs) ...@@ -1160,19 +1155,13 @@ static void do_signal(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
struct k_sigaction ka; struct k_sigaction ka;
int signr; int signr;
sigset_t *oldset;
current->thread.esp0 = (unsigned long) regs; current->thread.esp0 = (unsigned long) regs;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs); handle_signal(signr, &ka, &info, regs);
return; return;
} }
...@@ -1182,10 +1171,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -1182,10 +1171,7 @@ static void do_signal(struct pt_regs *regs)
handle_restart(regs, NULL, 0); handle_restart(regs, NULL, 0);
/* If there's no signal to deliver, we just restore the saved mask. */ /* If there's no signal to deliver, we just restore the saved mask. */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
void do_notify_resume(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs)
......
...@@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void) ...@@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
#endif #endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment