diff options
Diffstat (limited to 'arch/mn10300/kernel/signal.c')
| -rw-r--r-- | arch/mn10300/kernel/signal.c | 179 |
1 files changed, 37 insertions, 142 deletions
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index a21f43bc68e..9dfac5cd16e 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -31,69 +31,6 @@ #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -/* - * atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask) -{ - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - -/* - * set signal action syscall - */ -asmlinkage long 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 (verify_area(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 (verify_area(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; -} - -/* - * set alternate signal stack syscall - */ -asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss) -{ - return do_sigaltstack(uss, uoss, __frame->sp); -} - /* * do a signal return; undo the signal stack. */ @@ -102,6 +39,9 @@ static int restore_sigcontext(struct pt_regs *regs, { unsigned int err = 0; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + if (is_using_fpu(current)) fpu_kill_state(current); @@ -153,10 +93,11 @@ badframe: */ asmlinkage long sys_sigreturn(void) { - struct sigframe __user *frame = (struct sigframe __user *) __frame->sp; + struct sigframe __user *frame; sigset_t set; long d0; + frame = (struct sigframe __user *) current_frame()->sp; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask)) @@ -167,13 +108,9 @@ asmlinkage long sys_sigreturn(void) 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(__frame, &frame->sc, &d0)) + if (restore_sigcontext(current_frame(), &frame->sc, &d0)) goto badframe; return d0; @@ -188,26 +125,22 @@ badframe: */ asmlinkage long sys_rt_sigreturn(void) { - struct rt_sigframe __user *frame = - (struct rt_sigframe __user *) __frame->sp; + struct rt_sigframe __user *frame; sigset_t set; - unsigned long d0; + long d0; + frame = (struct rt_sigframe __user *) current_frame()->sp; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; 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(__frame, &frame->uc.uc_mcontext, &d0)) + if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; return d0; @@ -264,7 +197,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, /* this is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } @@ -330,12 +263,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, regs->d0 = sig; regs->d1 = (unsigned long) &frame->sc; - set_fs(USER_DS); - - /* the tracer may want to single-step inside the handler */ - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); - #if DEBUG_SIG printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", sig, current->comm, current->pid, frame, regs->pc, @@ -345,7 +272,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } @@ -378,9 +305,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || __put_user(0, &frame->uc.uc_link) || - __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || - __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) || - __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size) || + __save_altstack(&frame->uc.uc_stack, regs->sp) || setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpuctx, regs, set->sig[0]) || __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) @@ -413,12 +338,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->d0 = sig; regs->d1 = (long) &frame->info; - set_fs(USER_DS); - - /* the tracer may want to single-step inside the handler */ - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); - #if DEBUG_SIG printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", sig, current->comm, current->pid, frame, regs->pc, @@ -428,17 +347,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } +static inline void stepback(struct pt_regs *regs) +{ + regs->pc -= 2; + regs->orig_d0 = -1; +} + /* * handle the actual delivery of a signal to userspace */ static int handle_signal(int 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; /* Are we from a system call? */ @@ -459,7 +385,7 @@ static int handle_signal(int sig, /* fallthrough */ case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; - regs->pc -= 2; + stepback(regs); } } @@ -468,18 +394,12 @@ static int handle_signal(int sig, ret = setup_rt_frame(sig, ka, info, oldset, regs); else ret = setup_frame(sig, ka, oldset, regs); + if (ret) + return ret; - 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); - } - - return ret; + signal_delivered(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + return 0; } /* @@ -489,31 +409,11 @@ static void do_signal(struct pt_regs *regs) { 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 */ - if (!user_mode(regs)) - return; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - if (handle_signal(signr, &info, &ka, 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); - - tracehook_signal_handler(signr, &info, &ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + if (handle_signal(signr, &info, &ka, regs) == 0) { } return; @@ -527,22 +427,19 @@ static void do_signal(struct pt_regs *regs) case -ERESTARTSYS: case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; - regs->pc -= 2; + stepback(regs); break; case -ERESTART_RESTARTBLOCK: regs->d0 = __NR_restart_syscall; - regs->pc -= 2; + stepback(regs); break; } } /* 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(); } /* @@ -562,13 +459,11 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) } /* deal with pending signal delivery */ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(__frame); - if (current->replacement_session_keyring) - key_replace_session_keyring(); + tracehook_notify_resume(current_frame()); } } |
