]> git.karo-electronics.de Git - linux-beck.git/commitdiff
alpha: pass k_sigaction and siginfo_t using ksignal pointer
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 7 Nov 2012 22:38:51 +0000 (17:38 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 14 Feb 2013 14:21:16 +0000 (09:21 -0500)
... and use the new helpers

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/alpha/kernel/signal.c

index b5f385055244b037b41013a7dd77149e119584a5..6cec2881acbf2fe7f21195fb7eb036b4b5d75c80 100644 (file)
@@ -272,12 +272,9 @@ give_sigsegv:
  */
 
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
 {
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-               sp = current->sas_ss_sp + current->sas_ss_size;
-
-       return (void __user *)((sp - frame_size) & -32ul);
+       return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
 }
 
 static long
@@ -338,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 }
 
 static int
-setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
-           struct pt_regs *regs)
+setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
        unsigned long oldsp, r26, err = 0;
        struct sigframe __user *frame;
 
        oldsp = rdusp();
-       frame = get_sigframe(ka, oldsp, sizeof(*frame));
+       frame = get_sigframe(ksig, oldsp, sizeof(*frame));
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                return -EFAULT;
 
@@ -355,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
-       if (ka->ka_restorer) {
-               r26 = (unsigned long) ka->ka_restorer;
-       } else {
+       r26 = (unsigned long) ksig->ka.ka_restorer;
+       if (!r26) {
                err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
                err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
                err |= __put_user(INSN_CALLSYS, frame->retcode+2);
@@ -371,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
        /* "Return" to the handler */
        regs->r26 = r26;
-       regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
-       regs->r16 = sig;                        /* a0: signal number */
+       regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+       regs->r16 = ksig->sig;                  /* a0: signal number */
        regs->r17 = 0;                          /* a1: exception code */
        regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
        wrusp((unsigned long) frame);
@@ -385,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 }
 
 static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-              sigset_t *set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
        unsigned long oldsp, r26, err = 0;
        struct rt_sigframe __user *frame;
 
        oldsp = rdusp();
-       frame = get_sigframe(ka, oldsp, sizeof(*frame));
+       frame = get_sigframe(ksig, oldsp, sizeof(*frame));
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                return -EFAULT;
 
-       err |= copy_siginfo_to_user(&frame->info, info);
+       err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->uc.uc_flags);
@@ -411,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
-       if (ka->ka_restorer) {
-               r26 = (unsigned long) ka->ka_restorer;
-       } else {
+       r26 = (unsigned long) ksig->ka.ka_restorer;
+       if (!r26) {
                err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
                err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
                                  frame->retcode+1);
@@ -427,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* "Return" to the handler */
        regs->r26 = r26;
-       regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
-       regs->r16 = sig;                          /* a0: signal number */
+       regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+       regs->r16 = ksig->sig;                    /* a0: signal number */
        regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
        regs->r18 = (unsigned long) &frame->uc;   /* a2: ucontext pointer */
        wrusp((unsigned long) frame);
@@ -446,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  * OK, we're invoking a handler.
  */
 static inline void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-             struct pt_regs * regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
        sigset_t *oldset = sigmask_to_save();
        int ret;
 
-       if (ka->sa.sa_flags & SA_SIGINFO)
-               ret = setup_rt_frame(sig, ka, info, oldset, regs);
+       if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+               ret = setup_rt_frame(ksig, oldset, regs);
        else
-               ret = setup_frame(sig, ka, oldset, regs);
+               ret = setup_frame(ksig, oldset, regs);
 
-       if (ret) {
-               force_sigsegv(sig, current);
-               return;
-       }
-       signal_delivered(sig, info, ka, regs, 0);
+       signal_setup_done(ret, ksig, 0);
 }
 
 static inline void
@@ -504,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19,
 static void
 do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
 {
-       siginfo_t info;
-       int signr;
        unsigned long single_stepping = ptrace_cancel_bpt(current);
-       struct k_sigaction ka;
+       struct ksignal ksig;
 
        /* This lets the debugger run, ... */
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
-       /* ... so re-check the single stepping. */
-       single_stepping |= ptrace_cancel_bpt(current);
-
-       if (signr > 0) {
+       if (get_signal(&ksig)) {
+               /* ... so re-check the single stepping. */
+               single_stepping |= ptrace_cancel_bpt(current);
                /* Whee!  Actually deliver the signal.  */
                if (r0)
-                       syscall_restart(r0, r19, regs, &ka);
-               handle_signal(signr, &ka, &info, regs);
-               if (single_stepping) 
-                       ptrace_set_bpt(current); /* re-set bpt */
-               return;
-       }
-
-       if (r0) {
-               switch (regs->r0) {
-               case ERESTARTNOHAND:
-               case ERESTARTSYS:
-               case ERESTARTNOINTR:
-                       /* Reset v0 and a3 and replay syscall.  */
-                       regs->r0 = r0;
-                       regs->r19 = r19;
-                       regs->pc -= 4;
-                       break;
-               case ERESTART_RESTARTBLOCK:
-                       /* Force v0 to the restart syscall and reply.  */
-                       regs->r0 = __NR_restart_syscall;
-                       regs->pc -= 4;
-                       break;
+                       syscall_restart(r0, r19, regs, &ksig.ka);
+               handle_signal(&ksig, regs);
+       } else {
+               single_stepping |= ptrace_cancel_bpt(current);
+               if (r0) {
+                       switch (regs->r0) {
+                       case ERESTARTNOHAND:
+                       case ERESTARTSYS:
+                       case ERESTARTNOINTR:
+                               /* Reset v0 and a3 and replay syscall.  */
+                               regs->r0 = r0;
+                               regs->r19 = r19;
+                               regs->pc -= 4;
+                               break;
+                       case ERESTART_RESTARTBLOCK:
+                               /* Set v0 to the restart_syscall and replay */
+                               regs->r0 = __NR_restart_syscall;
+                               regs->pc -= 4;
+                               break;
+                       }
                }
+               restore_saved_sigmask();
        }
-
-       /* If there's no signal to deliver, we just restore the saved mask.  */
-       restore_saved_sigmask();
        if (single_stepping)
                ptrace_set_bpt(current);        /* re-set breakpoint */
 }