summaryrefslogtreecommitdiff
path: root/arch/tile/include
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-12-14 16:07:25 -0500
committerChris Metcalf <cmetcalf@tilera.com>2010-12-17 16:59:29 -0500
commit81711cee933599fa114abb0d258d8bbabef8adfb (patch)
treecef17c099689b15b3b8bb29b0eae84acd474ed8a /arch/tile/include
parentbc4cf2bb271b2d557fc510426755da786fc985be (diff)
arch/tile: handle rt_sigreturn() more cleanly
The current tile rt_sigreturn() syscall pattern uses the common idiom of loading up pt_regs with all the saved registers from the time of the signal, then anticipating the fact that we will clobber the ABI "return value" register (r0) as we return from the syscall by setting the rt_sigreturn return value to whatever random value was in the pt_regs for r0. However, this breaks in our 64-bit kernel when running "compat" tasks, since we always sign-extend the "return value" register to properly handle returned pointers that are in the upper 2GB of the 32-bit compat address space. Doing this to the sigreturn path then causes occasional random corruption of the 64-bit r0 register. Instead, we stop doing the crazy "load the return-value register" hack in sigreturn. We already have some sigreturn-specific assembly code that we use to pass the pt_regs pointer to C code. We extend that code to also set the link register to point to a spot a few instructions after the usual syscall return address so we don't clobber the saved r0. Now it no longer matters what the rt_sigreturn syscall returns, and the pt_regs structure can be cleanly and completely reloaded. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/include')
-rw-r--r--arch/tile/include/asm/signal.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h
index c1ee1d61d44c..81d92a45cd4b 100644
--- a/arch/tile/include/asm/signal.h
+++ b/arch/tile/include/asm/signal.h
@@ -25,7 +25,7 @@
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
struct pt_regs;
-int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
+int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
void do_signal(struct pt_regs *regs);
#endif