Commit b832c335 authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] ppc64: fix signal handler arguments

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: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f6febf2c
......@@ -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)
......
......@@ -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;
}
}
......
......@@ -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;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment