aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2013-06-09 07:23:17 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-25 17:07:20 -0400
commitbc8ae5222e9e42582bd32028c638a5b4517e69e2 (patch)
treee2fd74eaa62ae549d87fbd7900576e00dd5918e9
parent743834135bc07e3bb9d6166607b874443fe1537c (diff)
powerpc/tm: Fix restoration of MSR on 32bit signal return
commit 2c27a18f8736da047bef2b997bdd48efc667e3c9 upstream. Currently we clear out the MSR TM bits on signal return assuming that the signal should never return to an active transaction. This is bogus as the user may do this. It's most likely the transaction will be doomed due to a treclaim but that's a problem for the HW not the kernel. The current code is a legacy of earlier kernel implementations which did software rollback of active transactions in the kernel. That code has now gone but we didn't correctly fix up this part of the signals code which still makes the assumption that it must be returning to a suspended transaction. This pulls out both MSR TM bits from the user supplied context rather than just setting TM suspend. We pull out only the bits needed to ensure the user can't do anything dangerous to the MSR. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/powerpc/kernel/signal_32.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index fa81462f6987..364cb1e7300e 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -754,7 +754,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
754 struct mcontext __user *tm_sr) 754 struct mcontext __user *tm_sr)
755{ 755{
756 long err; 756 long err;
757 unsigned long msr; 757 unsigned long msr, msr_hi;
758#ifdef CONFIG_VSX 758#ifdef CONFIG_VSX
759 int i; 759 int i;
760#endif 760#endif
@@ -859,8 +859,11 @@ static long restore_tm_user_regs(struct pt_regs *regs,
859 tm_enable(); 859 tm_enable();
860 /* This loads the checkpointed FP/VEC state, if used */ 860 /* This loads the checkpointed FP/VEC state, if used */
861 tm_recheckpoint(&current->thread, msr); 861 tm_recheckpoint(&current->thread, msr);
862 /* The task has moved into TM state S, so ensure MSR reflects this */ 862 /* Get the top half of the MSR */
863 regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S; 863 if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
864 return 1;
865 /* Pull in MSR TM from user context */
866 regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK);
864 867
865 /* This loads the speculative FP/VEC state, if used */ 868 /* This loads the speculative FP/VEC state, if used */
866 if (msr & MSR_FP) { 869 if (msr & MSR_FP) {