diff mbox

[Zesty] powerpc/tm: Fix FP and VMX register corruption

Message ID 1495030779-29745-1-git-send-email-leitao@debian.org
State New
Headers show

Commit Message

Breno Leitao May 17, 2017, 2:19 p.m. UTC
From: Michael Neuling <mikey@neuling.org>

BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1691477

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")
Cc: stable@vger.kernel.org # 4.9+
Signed-off-by: Michael Neuling <mikey@neuling.org>
Reviewed-by: cyrilbur@gmail.com
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
(cherry picked from commit f48e91e87e67b56bef63393d1a02c6e22c1d7078)
Signed-off-by: Breno Leitao <breno.leitao@gmail.com>
---
 arch/powerpc/kernel/process.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

Comments

Brad Figg May 17, 2017, 7:46 p.m. UTC | #1

Stefan Bader May 18, 2017, 9:40 a.m. UTC | #2

Seth Forshee May 24, 2017, 12:41 p.m. UTC | #3
On Wed, May 17, 2017 at 11:19:39AM -0300, Breno Leitao wrote:
> From: Michael Neuling <mikey@neuling.org>
> 
> BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1691477
> 
> 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")
> Cc: stable@vger.kernel.org # 4.9+
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> Reviewed-by: cyrilbur@gmail.com
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> (cherry picked from commit f48e91e87e67b56bef63393d1a02c6e22c1d7078)
> Signed-off-by: Breno Leitao <breno.leitao@gmail.com>

Applied to artful/master-next.
Thadeu Lima de Souza Cascardo May 30, 2017, 7:07 p.m. UTC | #4
Applied to zesty master-next branch.

Thanks.
Cascardo.
diff mbox

Patch

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 5dd056df0baa..b58cbcae7aad 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,
 	if (!MSR_TM_SUSPENDED(mfmsr()))
 		return;
 
+	/*
+	 * If we are in a transaction and FP is off then we can't have
+	 * used FP inside that transaction. Hence the checkpointed
+	 * state is the same as the live state. We need to copy the
+	 * live state to the checkpointed state so that when the
+	 * transaction is restored, the checkpointed state is correct
+	 * and the aborted transaction sees the correct state. We use
+	 * ckpt_regs.msr here as that's what tm_reclaim will use to
+	 * determine if it's going to write the checkpointed state or
+	 * not. So either this will write the checkpointed registers,
+	 * or reclaim will. Similarly for VMX.
+	 */
+	if ((thr->ckpt_regs.msr & MSR_FP) == 0)
+		memcpy(&thr->ckfp_state, &thr->fp_state,
+		       sizeof(struct thread_fp_state));
+	if ((thr->ckpt_regs.msr & MSR_VEC) == 0)
+		memcpy(&thr->ckvr_state, &thr->vr_state,
+		       sizeof(struct thread_vr_state));
+
 	giveup_all(container_of(thr, struct task_struct, thread));
 
 	tm_reclaim(thr, thr->ckpt_regs.msr, cause);