[RFC PATCH 03/14] powerpc/tm: Recheckpoint when exiting from kernel
Breno Leitao
leitao at debian.org
Tue Nov 6 23:40:17 AEDT 2018
This is the only place we are going to recheckpoint now. Now the task
needs to have TIF_RESTORE_TM flag set, which will get into
restore_tm_state() at exception exit path, and execute the recheckpoint
depending on the MSR.
Every time a task is required to recheckpoint, or just have the TM SPRs
restore, the TIF_RESTORE_TM flag should be set and the task MSR should
properly be in a transactional state, which will be checked by
restore_tm_state().
After the facility registers are recheckpointed, they are clobbered with
the values that were recheckpointed (and are now also in the checkpoint
area).
If facility is enabled at MSR that is being returned to user space, then
the facility registers need to be restored, otherwise userspace will see
invalid values.
This patch simplify the restore_tm_state() to just restore the facility
registers that are enabled when returning to userspace, i.e. the MSR will
be the same that will be put into SRR1, which will be the MSR after RFID.
Signed-off-by: Breno Leitao <leitao at debian.org>
---
arch/powerpc/kernel/process.c | 38 ++++++++++++++++++++++++-----------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 4d5322cfad25..c7e758a42b8f 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1049,8 +1049,6 @@ static inline void __switch_to_tm(struct task_struct *prev,
*/
void restore_tm_state(struct pt_regs *regs)
{
- unsigned long msr_diff;
-
/*
* This is the only moment we should clear TIF_RESTORE_TM as
* it is here that ckpt_regs.msr and pt_regs.msr become the same
@@ -1061,19 +1059,35 @@ void restore_tm_state(struct pt_regs *regs)
if (!MSR_TM_ACTIVE(regs->msr))
return;
- msr_diff = current->thread.ckpt_regs.msr & ~regs->msr;
- msr_diff &= MSR_FP | MSR_VEC | MSR_VSX;
+ tm_enable();
+ /* The only place we recheckpoint */
+ tm_recheckpoint(¤t->thread);
- /* Ensure that restore_math() will restore */
- if (msr_diff & MSR_FP)
- current->thread.load_fp = 1;
+ /*
+ * Restore the facility registers that were clobbered during
+ * recheckpoint.
+ */
+ if (regs->msr & MSR_FP) {
+ /*
+ * Using load_fp_state() instead of restore_fp() because we
+ * want to force the restore, independent of
+ * tsk->thread.load_fp. Same for other cases below.
+ */
+ load_fp_state(¤t->thread.fp_state);
+ }
#ifdef CONFIG_ALTIVEC
- if (cpu_has_feature(CPU_FTR_ALTIVEC) && msr_diff & MSR_VEC)
- current->thread.load_vec = 1;
+ if (cpu_has_feature(CPU_FTR_ALTIVEC) && regs->msr & MSR_VEC)
+ load_vr_state(¤t->thread.vr_state);
+#endif
+#ifdef CONFIG_VSX
+ if (cpu_has_feature(CPU_FTR_VSX) && regs->msr & MSR_VSX) {
+ /*
+ * If VSX is enabled, it is expected that VEC and FP are
+ * also enabled and already restored the full register set.
+ * Cause a warning if that is not the case.
+ */
+ WARN_ON(!(regs->msr & MSR_VEC) || !(regs->msr & MSR_FP)); }
#endif
- restore_math(regs);
-
- regs->msr |= msr_diff;
}
#else
--
2.19.0
More information about the Linuxppc-dev
mailing list