aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2013-08-09 03:29:31 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-15 01:59:05 -0400
commitab9530578e03d7fc00f41f4c406d213d81579de0 (patch)
treec4ed80989afce2be4122bc4d36b4d67c34f197b6
parent80737512591c7b56b6e66e17d0b373218b1428b0 (diff)
powerpc/tm: Fix context switching TAR, PPR and DSCR SPRs
commit 28e61cc466d8daace4b0f04ba2b83e0bd68f5832 upstream. If a transaction is rolled back, the Target Address Register (TAR), Processor Priority Register (PPR) and Data Stream Control Register (DSCR) should be restored to the checkpointed values before the transaction began. Any changes to these SPRs inside the transaction should not be visible in the abort handler. Currently Linux doesn't save or restore the checkpointed TAR, PPR or DSCR. If we preempt a processes inside a transaction which has modified any of these, on process restore, that same transaction may be aborted we but we won't see the checkpointed versions of these SPRs. This adds checkpointed versions of these SPRs to the thread_struct and adds the save/restore of these three SPRs to the treclaim/trechkpt code. Without this if any of these SPRs are modified during a transaction, users may incorrectly see a speculated SPR value even if the transaction is aborted. 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/include/asm/processor.h4
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/tm.S20
3 files changed, 27 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 14a658363698..419e7125cce2 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -247,6 +247,10 @@ struct thread_struct {
247 unsigned long tm_orig_msr; /* Thread's MSR on ctx switch */ 247 unsigned long tm_orig_msr; /* Thread's MSR on ctx switch */
248 struct pt_regs ckpt_regs; /* Checkpointed registers */ 248 struct pt_regs ckpt_regs; /* Checkpointed registers */
249 249
250 unsigned long tm_tar;
251 unsigned long tm_ppr;
252 unsigned long tm_dscr;
253
250 /* 254 /*
251 * Transactional FP and VSX 0-31 register set. 255 * Transactional FP and VSX 0-31 register set.
252 * NOTE: the sense of these is the opposite of the integer ckpt_regs! 256 * NOTE: the sense of these is the opposite of the integer ckpt_regs!
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 6f16ffafa6f0..302886b77de2 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -139,6 +139,9 @@ int main(void)
139 DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar)); 139 DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar));
140 DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr)); 140 DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr));
141 DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar)); 141 DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar));
142 DEFINE(THREAD_TM_TAR, offsetof(struct thread_struct, tm_tar));
143 DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr));
144 DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr));
142 DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); 145 DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
143 DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct, 146 DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct,
144 transact_vr[0])); 147 transact_vr[0]));
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 2da67e7a16d5..1edd6c2a168d 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -224,6 +224,16 @@ dont_backup_fp:
224 std r5, _CCR(r7) 224 std r5, _CCR(r7)
225 std r6, _XER(r7) 225 std r6, _XER(r7)
226 226
227
228 /* ******************** TAR, PPR, DSCR ********** */
229 mfspr r3, SPRN_TAR
230 mfspr r4, SPRN_PPR
231 mfspr r5, SPRN_DSCR
232
233 std r3, THREAD_TM_TAR(r12)
234 std r4, THREAD_TM_PPR(r12)
235 std r5, THREAD_TM_DSCR(r12)
236
227 /* MSR and flags: We don't change CRs, and we don't need to alter 237 /* MSR and flags: We don't change CRs, and we don't need to alter
228 * MSR. 238 * MSR.
229 */ 239 */
@@ -338,6 +348,16 @@ dont_restore_fp:
338 mtmsr r6 /* FP/Vec off again! */ 348 mtmsr r6 /* FP/Vec off again! */
339 349
340restore_gprs: 350restore_gprs:
351
352 /* ******************** TAR, PPR, DSCR ********** */
353 ld r4, THREAD_TM_TAR(r3)
354 ld r5, THREAD_TM_PPR(r3)
355 ld r6, THREAD_TM_DSCR(r3)
356
357 mtspr SPRN_TAR, r4
358 mtspr SPRN_PPR, r5
359 mtspr SPRN_DSCR, r6
360
341 /* ******************** CR,LR,CCR,MSR ********** */ 361 /* ******************** CR,LR,CCR,MSR ********** */
342 ld r3, _CTR(r7) 362 ld r3, _CTR(r7)
343 ld r4, _LINK(r7) 363 ld r4, _LINK(r7)