]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] ppc64: fix signal handler arguments
authorPaul Mackerras <paulus@samba.org>
Fri, 17 Dec 2004 01:19:44 +0000 (17:19 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 17 Dec 2004 01:19:44 +0000 (17:19 -0800)
This is the first of 3 patches from David Woodhouse which fix various
problems with signal handling on ppc64.  (This is David's patch plus a
couple of comment fixes from me.)

Without this patch, a signal handler that is called as a result of delivery
of a signal while a process is waiting in sigsuspend() will have wrong
values given to it for the second and third arguments.  The reason is that
we were returning to userspace via the syscall return path, which doesn't
bother to restore r4 and r5.  This patch arranges for the return to
userspace to be done via ret_from_except in this case, which restores all
registers.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal32.c

index cdeca63ff55dd1d41f5bc121868d38660a1bc7e7..2dc052f6a0758199358027278b9c04e7824f2435 100644 (file)
@@ -265,16 +265,21 @@ _GLOBAL(save_nvgprs)
 _GLOBAL(ppc32_sigsuspend)
        bl      .save_nvgprs
        bl      .sys32_sigsuspend
-       b       syscall_exit
+       b       70f
 
 _GLOBAL(ppc64_rt_sigsuspend)
        bl      .save_nvgprs
        bl      .sys_rt_sigsuspend
-       b       syscall_exit
+       b       70f
 
 _GLOBAL(ppc32_rt_sigsuspend)
        bl      .save_nvgprs
        bl      .sys32_rt_sigsuspend
+       /* If sigsuspend() returns zero, we are going into a signal handler */
+70:    cmpdi   0,r3,0
+       beq     .ret_from_except
+       /* If it returned -EINTR, we need to return via syscall_exit to set
+          the SO bit in cr0 and potentially stop for ptrace. */
        b       syscall_exit
 
 _GLOBAL(ppc_fork)
index 3d284a39c9e28c9cbfaabc23bb8ae7315a8dc072..82da5a8ea65a14532e9e079cce681f6e775b2dad 100644 (file)
@@ -98,7 +98,7 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int
                current->state = TASK_INTERRUPTIBLE;
                schedule();
                if (do_signal(&saveset, regs))
-                       return regs->gpr[3];
+                       return 0;
        }
 }
 
index 642268815700eef8db7306e189e824152a928fda..42f3bd641760d5a1138a655497cfd75a4ffad220 100644 (file)
@@ -284,14 +284,12 @@ long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
                schedule();
                if (do_signal32(&saveset, regs))
                        /*
-                        * If a signal handler needs to be called,
-                        * do_signal32() has set R3 to the signal number (the
-                        * first argument of the signal handler), so don't
-                        * overwrite that with EINTR !
-                        * In the other cases, do_signal32() doesn't touch 
-                        * R3, so it's still set to -EINTR (see above).
+                        * Returning 0 means we return to userspace via
+                        * ret_from_except and thus restore all user
+                        * registers from *regs.  This is what we need
+                        * to do when a signal has been delivered.
                         */
-                       return regs->gpr[3];
+                       return 0;
        }
 }
 
@@ -587,14 +585,12 @@ int sys32_rt_sigsuspend(compat_sigset_t __user * unewset, size_t sigsetsize, int
                schedule();
                if (do_signal32(&saveset, regs))
                        /*
-                        * If a signal handler needs to be called,
-                        * do_signal32() has set R3 to the signal number (the
-                        * first argument of the signal handler), so don't
-                        * overwrite that with EINTR !
-                        * In the other cases, do_signal32() doesn't touch 
-                        * R3, so it's still set to -EINTR (see above).
+                        * Returning 0 means we return to userspace via
+                        * ret_from_except and thus restore all user
+                        * registers from *regs.  This is what we need
+                        * to do when a signal has been delivered.
                         */
-                       return regs->gpr[3];
+                       return 0;
        }
 }