aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2013-11-20 16:18:54 +1100
committerBen Hutchings <ben@decadent.org.uk>2014-01-03 04:33:23 +0000
commit3bf4e8c8072d395099cde6f6f84b69ea015b70d8 (patch)
tree9ae5af2bda7afd89e8d2c3ad3344e1bbe10b7eed
parent36d04a55f34ab580aab001e497b97410f0ad5079 (diff)
downloadkernel_samsung_smdk4412-3bf4e8c8072d395099cde6f6f84b69ea015b70d8.zip
kernel_samsung_smdk4412-3bf4e8c8072d395099cde6f6f84b69ea015b70d8.tar.gz
kernel_samsung_smdk4412-3bf4e8c8072d395099cde6f6f84b69ea015b70d8.tar.bz2
powerpc/signals: Mark VSX not saved with small contexts
commit c13f20ac48328b05cd3b8c19e31ed6c132b44b42 upstream. The VSX MSR bit in the user context indicates if the context contains VSX state. Currently we set this when the process has touched VSX at any stage. Unfortunately, if the user has not provided enough space to save the VSX state, we can't save it but we currently still set the MSR VSX bit. This patch changes this to clear the MSR VSX bit when the user doesn't provide enough space. This indicates that there is no valid VSX state in the user context. This is needed to support get/set/make/swapcontext for applications that use VSX but only provide a small context. For example, getcontext in glibc provides a smaller context since the VSX registers don't need to be saved over the glibc function call. But since the program calling getcontext may have used VSX, the kernel currently says the VSX state is valid when it's not. If the returned context is then used in setcontext (ie. a small context without VSX but with MSR VSX set), the kernel will refuse the context. This situation has been reported by the glibc community. Based on patch from Carlos O'Donell. Tested-by: Haren Myneni <haren@linux.vnet.ibm.com> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--arch/powerpc/kernel/signal_32.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 836a5a1..5eed5f3 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -457,7 +457,15 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
if (copy_vsx_to_user(&frame->mc_vsregs, current))
return 1;
msr |= MSR_VSX;
- }
+ } else if (!ctx_has_vsx_region)
+ /*
+ * With a small context structure we can't hold the VSX
+ * registers, hence clear the MSR value to indicate the state
+ * was not saved.
+ */
+ msr &= ~MSR_VSX;
+
+
#endif /* CONFIG_VSX */
#ifdef CONFIG_SPE
/* save spe registers */