@@ -109,6 +109,9 @@ int main(void)
OFFSET(THREAD_FPSAVEAREA, thread_struct, fp_save_area);
OFFSET(FPSTATE_FPSCR, thread_fp_state, fpscr);
OFFSET(THREAD_LOAD_FP, thread_struct, load_fp);
+ OFFSET(THREAD_DSCR, thread_struct, dscr);
+ OFFSET(THREAD_TAR, thread_struct, tar);
+
#ifdef CONFIG_ALTIVEC
OFFSET(THREAD_VRSTATE, thread_struct, vr_state.vr);
OFFSET(THREAD_VRSAVEAREA, thread_struct, vr_save_area);
@@ -311,6 +314,7 @@ int main(void)
STACK_PT_REGS_OFFSET(ORIG_GPR3, orig_gpr3);
STACK_PT_REGS_OFFSET(RESULT, result);
STACK_PT_REGS_OFFSET(_TRAP, trap);
+ STACK_PT_REGS_OFFSET(_PPR, ppr);
#ifndef CONFIG_PPC64
/*
* The PowerPC 400-class & Book-E processors have neither the DAR
@@ -79,6 +79,9 @@
#endif
extern unsigned long _get_SP(void);
+static inline void save_sprs(struct thread_struct *t);
+static inline void restore_sprs_after_recheckpoint(struct thread_struct
+ *thread);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/*
@@ -883,6 +886,8 @@ static void tm_reclaim_thread(struct thread_struct *thr, uint8_t cause)
thr->regs->msr);
giveup_all(container_of(thr, struct task_struct, thread));
+ /* Save SPRS before reclaim */
+ save_sprs(thr);
tm_reclaim(thr, cause);
/* Tag it so restore_tm_state will pay attention to this task */
@@ -939,6 +944,7 @@ void tm_recheckpoint(struct thread_struct *thread)
__tm_recheckpoint(thread);
+ restore_sprs_after_recheckpoint(thread);
local_irq_restore(flags);
}
@@ -1166,6 +1172,19 @@ static inline void restore_sprs(struct thread_struct *old_thread,
thread_pkey_regs_restore(new_thread, old_thread);
}
+static inline void restore_sprs_after_recheckpoint(struct thread_struct *thread)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (cpu_has_feature(CPU_FTR_DSCR))
+ mtspr(SPRN_DSCR, thread->dscr);
+
+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+ mtspr(SPRN_TAR, thread->tar);
+ mtspr(SPRN_FSCR, thread->fscr);
+ }
+#endif
+}
+
#ifdef CONFIG_PPC_BOOK3S_64
#define CP_SIZE 128
static const u8 dummy_copy_buffer[CP_SIZE] __attribute__((aligned(CP_SIZE)));
@@ -326,9 +326,18 @@ _GLOBAL(tm_reclaim)
mtlr r0
ld r2, STK_GOT(r1)
- /* Load CPU's default DSCR */
- ld r0, PACA_DSCR_DEFAULT(r13)
- mtspr SPRN_DSCR, r0
+ /*
+ * Load transactional SPRs, as all other registers have the
+ * transacional value, which will be seen by save_sprs and so
+ * forth. Checkpointed SPRs are in the thread->tm_tar/dscr.
+ */
+ ld r0, THREAD_DSCR(r12)
+ mtspr SPRN_DSCR, r0
+ ld r0, THREAD_TAR(r12)
+ mtspr SPRN_TAR, r0
+ ld r0, _PPR(r7)
+ mtspr SPRN_PPR, r0
+
blr
@@ -518,10 +527,6 @@ restore_gprs:
mtlr r0
ld r2, STK_GOT(r1)
- /* Load CPU's default DSCR */
- ld r0, PACA_DSCR_DEFAULT(r13)
- mtspr SPRN_DSCR, r0
-
blr
/* ****************************************************************** */
In the previous TM code, trecheckpoint was being executed in the middle of an exception, thus, SPRs were being restored to default kernel SPRs (as DSCR) value after trecheckpoint was done. With this current patchset, trecheckpoint is executed just before getting to userspace, at ret_from_except_lite, for example. Thus, SPRs need to be restored to transactional value. In order to so, a function, called restore_sprs_after_recheckpoint(), was created to restore the SPRs after recheckpoint. This function should be called after trecheckpoint to restore transactional SPRs, otherwise the SPRs will be clobbered (with checkpointed values) after recheckpoint. I understand it is preferred to have it done as a C function instead of embedding it in the ASM code. This patch also changes tm_reclaim() that now always return with transactional SPRs value (instead of checkpointed value), as NVGPRs. Previously tm_reclaim() was returning with transactional NVGPRS and checkpointed SPRS, intermixing them. With the current patch, tm_reclaim() just fill out thread->ck and thread->tm values, and return with transactional values in a uniform way (for SPRS and NVGPRS). In this case, a later save_spr() at switch_to() will not overwrite thread->sprs with checkpointed values, but with transactional values. Facility registers, as VEC and FP, continue to be clobbered after tm_reclaim(), tho. These are the SPRs that are checkpointed by the hardware: CR fields other than CR0, LR, CTR, FPSCR, AMR, PPR, VRSAVE, VSCR, DSCR, and TAR. This patch only cares about PPR, TAR and DSCR, because others SPRS either volatiles, restored as part of facilities or not being handled currently as AMR/CRs. Signed-off-by: Breno Leitao <leitao@debian.org> --- arch/powerpc/kernel/asm-offsets.c | 4 ++++ arch/powerpc/kernel/process.c | 19 +++++++++++++++++++ arch/powerpc/kernel/tm.S | 19 ++++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-)