]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.9.30/powerpc-tm-fix-fp-and-vmx-register-corruption.patch
Linux 4.14.95
[thirdparty/kernel/stable-queue.git] / releases / 4.9.30 / powerpc-tm-fix-fp-and-vmx-register-corruption.patch
1 From f48e91e87e67b56bef63393d1a02c6e22c1d7078 Mon Sep 17 00:00:00 2001
2 From: Michael Neuling <mikey@neuling.org>
3 Date: Mon, 8 May 2017 17:16:26 +1000
4 Subject: powerpc/tm: Fix FP and VMX register corruption
5
6 From: Michael Neuling <mikey@neuling.org>
7
8 commit f48e91e87e67b56bef63393d1a02c6e22c1d7078 upstream.
9
10 In commit dc3106690b20 ("powerpc: tm: Always use fp_state and vr_state
11 to store live registers"), a section of code was removed that copied
12 the current state to checkpointed state. That code should not have been
13 removed.
14
15 When an FP (Floating Point) unavailable is taken inside a transaction,
16 we need to abort the transaction. This is because at the time of the
17 tbegin, the FP state is bogus so the state stored in the checkpointed
18 registers is incorrect. To fix this, we treclaim (to get the
19 checkpointed GPRs) and then copy the thread_struct FP live state into
20 the checkpointed state. We then trecheckpoint so that the FP state is
21 correctly restored into the CPU.
22
23 The copying of the FP registers from live to checkpointed is what was
24 missing.
25
26 This simplifies the logic slightly from the original patch.
27 tm_reclaim_thread() will now always write the checkpointed FP
28 state. Either the checkpointed FP state will be written as part of
29 the actual treclaim (in tm.S), or it'll be a copy of the live
30 state. Which one we use is based on MSR[FP] from userspace.
31
32 Similarly for VMX.
33
34 Fixes: dc3106690b20 ("powerpc: tm: Always use fp_state and vr_state to store live registers")
35 Signed-off-by: Michael Neuling <mikey@neuling.org>
36 Reviewed-by: cyrilbur@gmail.com
37 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
38 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39
40 ---
41 arch/powerpc/kernel/process.c | 19 +++++++++++++++++++
42 1 file changed, 19 insertions(+)
43
44 --- a/arch/powerpc/kernel/process.c
45 +++ b/arch/powerpc/kernel/process.c
46 @@ -839,6 +839,25 @@ static void tm_reclaim_thread(struct thr
47 if (!MSR_TM_SUSPENDED(mfmsr()))
48 return;
49
50 + /*
51 + * If we are in a transaction and FP is off then we can't have
52 + * used FP inside that transaction. Hence the checkpointed
53 + * state is the same as the live state. We need to copy the
54 + * live state to the checkpointed state so that when the
55 + * transaction is restored, the checkpointed state is correct
56 + * and the aborted transaction sees the correct state. We use
57 + * ckpt_regs.msr here as that's what tm_reclaim will use to
58 + * determine if it's going to write the checkpointed state or
59 + * not. So either this will write the checkpointed registers,
60 + * or reclaim will. Similarly for VMX.
61 + */
62 + if ((thr->ckpt_regs.msr & MSR_FP) == 0)
63 + memcpy(&thr->ckfp_state, &thr->fp_state,
64 + sizeof(struct thread_fp_state));
65 + if ((thr->ckpt_regs.msr & MSR_VEC) == 0)
66 + memcpy(&thr->ckvr_state, &thr->vr_state,
67 + sizeof(struct thread_vr_state));
68 +
69 giveup_all(container_of(thr, struct task_struct, thread));
70
71 tm_reclaim(thr, thr->ckpt_regs.msr, cause);