aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2017-05-08 03:16:26 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 09:44:43 -0400
commita685601f85331ec7f8cda1975bddba311441f333 (patch)
treeaa4b11a76a95b441f3b07adfc373d5674222cf49
parent018b91870856035f9bdff45f690b933d67f6efc3 (diff)
powerpc/tm: Fix FP and VMX register corruption
commit f48e91e87e67b56bef63393d1a02c6e22c1d7078 upstream. In commit dc3106690b20 ("powerpc: tm: Always use fp_state and vr_state to store live registers"), a section of code was removed that copied the current state to checkpointed state. That code should not have been removed. When an FP (Floating Point) unavailable is taken inside a transaction, we need to abort the transaction. This is because at the time of the tbegin, the FP state is bogus so the state stored in the checkpointed registers is incorrect. To fix this, we treclaim (to get the checkpointed GPRs) and then copy the thread_struct FP live state into the checkpointed state. We then trecheckpoint so that the FP state is correctly restored into the CPU. The copying of the FP registers from live to checkpointed is what was missing. This simplifies the logic slightly from the original patch. tm_reclaim_thread() will now always write the checkpointed FP state. Either the checkpointed FP state will be written as part of the actual treclaim (in tm.S), or it'll be a copy of the live state. Which one we use is based on MSR[FP] from userspace. Similarly for VMX. Fixes: dc3106690b20 ("powerpc: tm: Always use fp_state and vr_state to store live registers") Signed-off-by: Michael Neuling <mikey@neuling.org> Reviewed-by: cyrilbur@gmail.com Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/powerpc/kernel/process.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 49a680d5ae37..c7164739dc75 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -839,6 +839,25 @@ static void tm_reclaim_thread(struct thread_struct *thr,
839 if (!MSR_TM_SUSPENDED(mfmsr())) 839 if (!MSR_TM_SUSPENDED(mfmsr()))
840 return; 840 return;
841 841
842 /*
843 * If we are in a transaction and FP is off then we can't have
844 * used FP inside that transaction. Hence the checkpointed
845 * state is the same as the live state. We need to copy the
846 * live state to the checkpointed state so that when the
847 * transaction is restored, the checkpointed state is correct
848 * and the aborted transaction sees the correct state. We use
849 * ckpt_regs.msr here as that's what tm_reclaim will use to
850 * determine if it's going to write the checkpointed state or
851 * not. So either this will write the checkpointed registers,
852 * or reclaim will. Similarly for VMX.
853 */
854 if ((thr->ckpt_regs.msr & MSR_FP) == 0)
855 memcpy(&thr->ckfp_state, &thr->fp_state,
856 sizeof(struct thread_fp_state));
857 if ((thr->ckpt_regs.msr & MSR_VEC) == 0)
858 memcpy(&thr->ckvr_state, &thr->vr_state,
859 sizeof(struct thread_vr_state));
860
842 giveup_all(container_of(thr, struct task_struct, thread)); 861 giveup_all(container_of(thr, struct task_struct, thread));
843 862
844 tm_reclaim(thr, thr->ckpt_regs.msr, cause); 863 tm_reclaim(thr, thr->ckpt_regs.msr, cause);