aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2018-09-24 03:27:04 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2018-09-25 08:51:08 -0400
commitcf13435b730a502e814c63c84d93db131e563f5f (patch)
tree46d7d088182d0ca86b7f5b7b45ecbf5dfa82e66f
parent8604895a34d92f5e186ceb931b0d1b384030ea3d (diff)
powerpc/tm: Fix userspace r13 corruption
When we treclaim we store the userspace checkpointed r13 to a scratch SPR and then later save the scratch SPR to the user thread struct. Unfortunately, this doesn't work as accessing the user thread struct can take an SLB fault and the SLB fault handler will write the same scratch SPRG that now contains the userspace r13. To fix this, we store r13 to the kernel stack (which can't fault) before we access the user thread struct. Found by running P8 guest + powervm + disable_1tb_segments + TM. Seen as a random userspace segfault with r13 looking like a kernel address. Signed-off-by: Michael Neuling <mikey@neuling.org> Reviewed-by: Breno Leitao <leitao@debian.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/tm.S11
1 files changed, 9 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 6bffbc5affe7..183e8d75936f 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -176,13 +176,20 @@ _GLOBAL(tm_reclaim)
176 std r1, PACATMSCRATCH(r13) 176 std r1, PACATMSCRATCH(r13)
177 ld r1, PACAR1(r13) 177 ld r1, PACAR1(r13)
178 178
179 /* Store the PPR in r11 and reset to decent value */
180 std r11, GPR11(r1) /* Temporary stash */ 179 std r11, GPR11(r1) /* Temporary stash */
181 180
181 /*
182 * Store r13 away so we can free up the scratch SPR for the SLB fault
183 * handler (needed once we start accessing the thread_struct).
184 */
185 GET_SCRATCH0(r11)
186 std r11, GPR13(r1)
187
182 /* Reset MSR RI so we can take SLB faults again */ 188 /* Reset MSR RI so we can take SLB faults again */
183 li r11, MSR_RI 189 li r11, MSR_RI
184 mtmsrd r11, 1 190 mtmsrd r11, 1
185 191
192 /* Store the PPR in r11 and reset to decent value */
186 mfspr r11, SPRN_PPR 193 mfspr r11, SPRN_PPR
187 HMT_MEDIUM 194 HMT_MEDIUM
188 195
@@ -211,7 +218,7 @@ _GLOBAL(tm_reclaim)
211 ld r4, GPR7(r1) /* user r7 */ 218 ld r4, GPR7(r1) /* user r7 */
212 ld r5, GPR11(r1) /* user r11 */ 219 ld r5, GPR11(r1) /* user r11 */
213 ld r6, GPR12(r1) /* user r12 */ 220 ld r6, GPR12(r1) /* user r12 */
214 GET_SCRATCH0(8) /* user r13 */ 221 ld r8, GPR13(r1) /* user r13 */
215 std r3, GPR1(r7) 222 std r3, GPR1(r7)
216 std r4, GPR7(r7) 223 std r4, GPR7(r7)
217 std r5, GPR11(r7) 224 std r5, GPR11(r7)