diff options
Diffstat (limited to 'arch/sh/kernel/signal_64.c')
| -rw-r--r-- | arch/sh/kernel/signal_64.c | 200 | 
1 files changed, 19 insertions, 181 deletions
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 5a9f1f10ebf..23d4c71c91a 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -18,7 +18,6 @@  #include <linux/errno.h>  #include <linux/wait.h>  #include <linux/personality.h> -#include <linux/freezer.h>  #include <linux/ptrace.h>  #include <linux/unistd.h>  #include <linux/stddef.h> @@ -41,11 +40,9 @@  #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -static int +static void  handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, -		sigset_t *oldset, struct pt_regs * regs); +		struct pt_regs * regs);  static inline void  handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) @@ -83,7 +80,7 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)   * the kernel can handle, and then we build all the user-level signal handling   * stack-frames in one go after that.   */ -static int do_signal(struct pt_regs *regs, sigset_t *oldset) +static void do_signal(struct pt_regs *regs)  {  	siginfo_t info;  	int signr; @@ -96,36 +93,17 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)  	 * if so.  	 */  	if (!user_mode(regs)) -		return 1; - -	if (try_to_freeze()) -		goto no_signal; - -	if (current_thread_info()->status & TS_RESTORE_SIGMASK) -		oldset = ¤t->saved_sigmask; -	else if (!oldset) -		oldset = ¤t->blocked; +		return;  	signr = get_signal_to_deliver(&info, &ka, regs, 0);  	if (signr > 0) {  		handle_syscall_restart(regs, &ka.sa);  		/* Whee!  Actually deliver the signal.  */ -		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { -			/* -			 * If a signal was successfully delivered, the -			 * saved sigmask is in its frame, and we can -			 * clear the TS_RESTORE_SIGMASK flag. -			 */ -			current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - -			tracehook_signal_handler(signr, &info, &ka, regs, -					test_thread_flag(TIF_SINGLESTEP)); -			return 1; -		} +		handle_signal(signr, &info, &ka, regs); +		return;  	} -no_signal:  	/* Did we come from a system call? */  	if (regs->syscall_nr >= 0) {  		/* Restart the system call - no handlers present */ @@ -146,121 +124,7 @@ no_signal:  	}  	/* No signal to deliver -- put the saved sigmask back */ -	if (current_thread_info()->status & TS_RESTORE_SIGMASK) { -		current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -		sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); -	} - -	return 0; -} - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys_sigsuspend(old_sigset_t mask, -	       unsigned long r3, unsigned long r4, unsigned long r5, -	       unsigned long r6, unsigned long r7, -	       struct pt_regs * regs) -{ -	sigset_t saveset; - -	mask &= _BLOCKABLE; -	spin_lock_irq(¤t->sighand->siglock); -	saveset = current->blocked; -	siginitset(¤t->blocked, mask); -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); - -	REF_REG_RET = -EINTR; -	while (1) { -		current->state = TASK_INTERRUPTIBLE; -		schedule(); -		set_restore_sigmask(); -		regs->pc += 4;    /* because sys_sigreturn decrements the pc */ -		if (do_signal(regs, &saveset)) { -			/* pc now points at signal handler. Need to decrement -			   it because entry.S will increment it. */ -			regs->pc -= 4; -			return -EINTR; -		} -	} -} - -asmlinkage int -sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, -	          unsigned long r4, unsigned long r5, unsigned long r6, -	          unsigned long r7, -	          struct pt_regs * regs) -{ -	sigset_t saveset, newset; - -	/* XXX: Don't preclude handling different sized sigset_t's.  */ -	if (sigsetsize != sizeof(sigset_t)) -		return -EINVAL; - -	if (copy_from_user(&newset, unewset, sizeof(newset))) -		return -EFAULT; -	sigdelsetmask(&newset, ~_BLOCKABLE); -	spin_lock_irq(¤t->sighand->siglock); -	saveset = current->blocked; -	current->blocked = newset; -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); - -	REF_REG_RET = -EINTR; -	while (1) { -		current->state = TASK_INTERRUPTIBLE; -		schedule(); -		regs->pc += 4;    /* because sys_sigreturn decrements the pc */ -		if (do_signal(regs, &saveset)) { -			/* pc now points at signal handler. Need to decrement -			   it because entry.S will increment it. */ -			regs->pc -= 4; -			return -EINTR; -		} -	} -} - -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction __user *act, -	      struct old_sigaction __user *oact) -{ -	struct k_sigaction new_ka, old_ka; -	int ret; - -	if (act) { -		old_sigset_t mask; -		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || -		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) || -		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) -			return -EFAULT; -		__get_user(new_ka.sa.sa_flags, &act->sa_flags); -		__get_user(mask, &act->sa_mask); -		siginitset(&new_ka.sa.sa_mask, mask); -	} - -	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - -	if (!ret && oact) { -		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || -		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || -		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) -			return -EFAULT; -		__put_user(old_ka.sa.sa_flags, &oact->sa_flags); -		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); -	} - -	return ret; -} - -asmlinkage int -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, -	        unsigned long r4, unsigned long r5, unsigned long r6, -	        unsigned long r7, -	        struct pt_regs * regs) -{ -	return do_sigaltstack(uss, uoss, REF_REG_SP); +	restore_saved_sigmask();  }  /* @@ -411,12 +275,7 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,  				    sizeof(frame->extramask))))  		goto badframe; -	sigdelsetmask(&set, ~_BLOCKABLE); - -	spin_lock_irq(¤t->sighand->siglock); -	current->blocked = set; -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); +	set_current_blocked(&set);  	if (restore_sigcontext(regs, &frame->sc, &ret))  		goto badframe; @@ -436,7 +295,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,  {  	struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;  	sigset_t set; -	stack_t __user st;  	long long ret;  	/* Always make any pending restarted system calls return -EINTR */ @@ -448,21 +306,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,  	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))  		goto badframe; -	sigdelsetmask(&set, ~_BLOCKABLE); -	spin_lock_irq(¤t->sighand->siglock); -	current->blocked = set; -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); +	set_current_blocked(&set);  	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))  		goto badframe;  	regs->pc -= 4; -	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) +	if (restore_altstack(&frame->uc.uc_stack))  		goto badframe; -	/* It is more difficult to avoid calling this function than to -	   call it and ignore errors.  */ -	do_sigaltstack(&st, NULL, REF_REG_SP);  	return (int) ret; @@ -655,11 +506,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  	/* Create the ucontext.  */  	err |= __put_user(0, &frame->uc.uc_flags);  	err |= __put_user(0, &frame->uc.uc_link); -	err |= __put_user((void *)current->sas_ss_sp, -			  &frame->uc.uc_stack.ss_sp); -	err |= __put_user(sas_ss_flags(regs->regs[REG_SP]), -			  &frame->uc.uc_stack.ss_flags); -	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); +	err |= __save_altstack(&frame->uc.uc_stack, regs->regs[REG_SP]);  	err |= setup_sigcontext(&frame->uc.uc_mcontext,  			        regs, set->sig[0]);  	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -726,10 +573,11 @@ give_sigsegv:  /*   * OK, we're invoking a handler   */ -static int +static void  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;  	/* Set up the stack frame */ @@ -738,30 +586,20 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,  	else  		ret = setup_frame(sig, ka, oldset, regs); -	if (ka->sa.sa_flags & SA_ONESHOT) -		ka->sa.sa_handler = SIG_DFL; - -	if (ret == 0) { -		spin_lock_irq(¤t->sighand->siglock); -		sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); -		if (!(ka->sa.sa_flags & SA_NODEFER)) -			sigaddset(¤t->blocked,sig); -		recalc_sigpending(); -		spin_unlock_irq(¤t->sighand->siglock); -	} +	if (ret) +		return; -	return ret; +	signal_delivered(sig, info, ka, regs, +			test_thread_flag(TIF_SINGLESTEP));  }  asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)  {  	if (thread_info_flags & _TIF_SIGPENDING) -		do_signal(regs, 0); +		do_signal(regs);  	if (thread_info_flags & _TIF_NOTIFY_RESUME) {  		clear_thread_flag(TIF_NOTIFY_RESUME);  		tracehook_notify_resume(regs); -		if (current->replacement_session_keyring) -			key_replace_session_keyring();  	}  }  | 
