]> Pileus Git - ~andy/linux/blobdiff - arch/sparc/kernel/signal_64.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[~andy/linux] / arch / sparc / kernel / signal_64.c
index 176e0e7b8f606fe3c2d0141ee9a59cc241ecab97..35923e8abd8234f8fe067c0ed4a5e6f49ee85cb8 100644 (file)
@@ -236,23 +236,6 @@ struct rt_signal_frame {
        __siginfo_rwin_t        *rwin_save;
 };
 
-static long _sigpause_common(old_sigset_t set)
-{
-       sigset_t blocked;
-       siginitset(&blocked, set);
-       return sigsuspend(&blocked);
-}
-
-asmlinkage long sys_sigpause(unsigned int set)
-{
-       return _sigpause_common(set);
-}
-
-asmlinkage long sys_sigsuspend(old_sigset_t set)
-{
-       return _sigpause_common(set);
-}
-
 void do_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_signal_frame __user *sf;
@@ -325,7 +308,7 @@ static int invalid_frame_pointer(void __user *fp)
        return 0;
 }
 
-static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
+static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
        unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
 
@@ -337,12 +320,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
                return (void __user *) -1L;
 
        /* This is the X/Open sanctioned signal stack switching.  */
-       if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (sas_ss_flags(sp) == 0)
-                       sp = current->sas_ss_sp + current->sas_ss_size;
-       }
-
-       sp -= framesize;
+       sp = sigsp(sp, ksig) - framesize;
 
        /* Always align the stack frame.  This handles two cases.  First,
         * sigaltstack need not be mindful of platform specific stack
@@ -356,8 +334,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
 }
 
 static inline int
-setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
-              int signo, sigset_t *oldset, siginfo_t *info)
+setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
 {
        struct rt_signal_frame __user *sf;
        int wsaved, err, sf_size;
@@ -375,10 +352,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        if (wsaved)
                sf_size += sizeof(__siginfo_rwin_t);
        sf = (struct rt_signal_frame __user *)
-               get_sigframe(ka, regs, sf_size);
+               get_sigframe(ksig, regs, sf_size);
 
-       if (invalid_frame_pointer (sf))
-               goto sigill;
+       if (invalid_frame_pointer (sf)) {
+               do_exit(SIGILL);        /* won't return, actually */
+               return -EINVAL;
+       }
 
        tail = (sf + 1);
 
@@ -406,7 +385,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        /* Setup sigaltstack */
        err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]);
 
-       err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
+       err |= copy_to_user(&sf->mask, sigmask_to_save(), sizeof(sigset_t));
 
        if (!wsaved) {
                err |= copy_in_user((u64 __user *)sf,
@@ -419,18 +398,18 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
                rp = &current_thread_info()->reg_window[wsaved - 1];
                err |= copy_to_user(sf, rp, sizeof(struct reg_window));
        }
-       if (info)
-               err |= copy_siginfo_to_user(&sf->info, info);
+       if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+               err |= copy_siginfo_to_user(&sf->info, &ksig->info);
        else {
-               err |= __put_user(signo, &sf->info.si_signo);
+               err |= __put_user(ksig->sig, &sf->info.si_signo);
                err |= __put_user(SI_NOINFO, &sf->info.si_code);
        }
        if (err)
-               goto sigsegv;
+               return err;
        
        /* 3. signal handler back-trampoline and parameters */
        regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
-       regs->u_regs[UREG_I0] = signo;
+       regs->u_regs[UREG_I0] = ksig->sig;
        regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
 
        /* The sigcontext is passed in this way because of how it
@@ -440,37 +419,15 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
 
        /* 5. signal handler */
-       regs->tpc = (unsigned long) ka->sa.sa_handler;
+       regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
        regs->tnpc = (regs->tpc + 4);
        if (test_thread_flag(TIF_32BIT)) {
                regs->tpc &= 0xffffffff;
                regs->tnpc &= 0xffffffff;
        }
        /* 4. return to kernel instructions */
-       regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
+       regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
        return 0;
-
-sigill:
-       do_exit(SIGILL);
-       return -EINVAL;
-
-sigsegv:
-       force_sigsegv(signo, current);
-       return -EFAULT;
-}
-
-static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
-                               siginfo_t *info,
-                               sigset_t *oldset, struct pt_regs *regs)
-{
-       int err;
-
-       err = setup_rt_frame(ka, regs, signr, oldset,
-                            (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
-       if (err)
-               return;
-
-       signal_delivered(signr, info, ka, regs, 0);
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -500,11 +457,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  */
 static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 {
-       struct k_sigaction ka;
+       struct ksignal ksig;
        int restart_syscall;
-       sigset_t *oldset = sigmask_to_save();
-       siginfo_t info;
-       int signr;
+       bool has_handler;
        
        /* It's a lot of work and synchronization to add a new ptrace
         * register for GDB to save and restore in order to get
@@ -530,13 +485,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
-               extern void do_signal32(sigset_t *, struct pt_regs *);
-               do_signal32(oldset, regs);
+               extern void do_signal32(struct pt_regs *);
+               do_signal32(regs);
                return;
        }
 #endif 
 
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+       has_handler = get_signal(&ksig);
 
        restart_syscall = 0;
        if (pt_regs_is_syscall(regs) &&
@@ -545,34 +500,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
                orig_i0 = regs->u_regs[UREG_G6];
        }
 
-       if (signr > 0) {
+       if (has_handler) {
                if (restart_syscall)
-                       syscall_restart(orig_i0, regs, &ka.sa);
-               handle_signal(signr, &ka, &info, oldset, regs);
-               return;
-       }
-       if (restart_syscall &&
-           (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
-            regs->u_regs[UREG_I0] == ERESTARTSYS ||
-            regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
-               /* replay the system call when we are done */
-               regs->u_regs[UREG_I0] = orig_i0;
-               regs->tpc -= 4;
-               regs->tnpc -= 4;
-               pt_regs_clear_syscall(regs);
-       }
-       if (restart_syscall &&
-           regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
-               regs->u_regs[UREG_G1] = __NR_restart_syscall;
-               regs->tpc -= 4;
-               regs->tnpc -= 4;
-               pt_regs_clear_syscall(regs);
+                       syscall_restart(orig_i0, regs, &ksig.ka.sa);
+               signal_setup_done(setup_rt_frame(&ksig, regs), &ksig, 0);
+       } else {
+               if (restart_syscall) {
+                       switch (regs->u_regs[UREG_I0]) {
+                       case ERESTARTNOHAND:
+                       case ERESTARTSYS:
+                       case ERESTARTNOINTR:
+                               /* replay the system call when we are done */
+                               regs->u_regs[UREG_I0] = orig_i0;
+                               regs->tpc -= 4;
+                               regs->tnpc -= 4;
+                               pt_regs_clear_syscall(regs);
+                       case ERESTART_RESTARTBLOCK:
+                               regs->u_regs[UREG_G1] = __NR_restart_syscall;
+                               regs->tpc -= 4;
+                               regs->tnpc -= 4;
+                               pt_regs_clear_syscall(regs);
+                       }
+               }
+               restore_saved_sigmask();
        }
-
-       /* If there's no signal to deliver, we just put the saved sigmask
-        * back
-        */
-       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)