KVM: PPC: Book3S HV: Work around XER[SO] bug in fake suspend mode
authorSuraj Jitindar Singh <sjitindarsingh@gmail.com>
Wed, 21 Mar 2018 10:32:02 +0000 (21:32 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 23 Mar 2018 13:39:16 +0000 (00:39 +1100)
This works around a hardware bug in "Nimbus" POWER9 DD2.2 processors,
where a treclaim performed in fake suspend mode can cause subsequent
reads from the XER register to return inconsistent values for the SO
(summary overflow) bit.  The inconsistent SO bit state can potentially
be observed on any thread in the core.  We have to do the treclaim
because that is the only way to get the thread out of suspend state
(fake or real) and into non-transactional state.

The workaround for the bug is to force the core into SMT4 mode before
doing the treclaim.  This patch adds the code to do that, conditional
on the CPU_FTR_P9_TM_XER_SO_BUG feature bit.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index 5af6174..11396c0 100644 (file)
@@ -3101,6 +3101,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 kvmppc_save_tm:
        mflr    r0
        std     r0, PPC_LR_STKOFF(r1)
+       stdu    r1, -PPC_MIN_STKFRM(r1)
 
        /* Turn on TM. */
        mfmsr   r8
@@ -3120,8 +3121,16 @@ BEGIN_FTR_SECTION
        mfspr   r6, SPRN_TEXASR
        std     r6, VCPU_ORIG_TEXASR(r9)
 
-       rldicl. r8, r8, 64 - MSR_TS_S_LG, 62
+       lbz     r0, HSTATE_FAKE_SUSPEND(r13) /* Were we fake suspended? */
+       cmpwi   r0, 0
        beq     3f
+       rldicl. r8, r8, 64 - MSR_TS_S_LG, 62 /* Did we actually hrfid? */
+       beq     4f
+BEGIN_FTR_SECTION_NESTED(96)
+       bl      pnv_power9_force_smt4_catch
+END_FTR_SECTION_NESTED(CPU_FTR_P9_TM_XER_SO_BUG, CPU_FTR_P9_TM_XER_SO_BUG, 96)
+       nop
+3:
 END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
 
        /* Clear the MSR RI since r1, r13 are all going to be foobar. */
@@ -3138,7 +3147,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
 
        /* If doing TM emulation on POWER9 DD2.2, check for fake suspend mode */
 BEGIN_FTR_SECTION
-3:
        lbz     r9, HSTATE_FAKE_SUSPEND(r13)
        cmpwi   r9, 0
        beq     2f
@@ -3150,13 +3158,18 @@ BEGIN_FTR_SECTION
        /* Reload stack pointer and TOC. */
        ld      r1, HSTATE_HOST_R1(r13)
        ld      r2, PACATOC(r13)
+       /* Set MSR RI now we have r1 and r13 back. */
        li      r5, MSR_RI
        mtmsrd  r5, 1
        HMT_MEDIUM
        ld      r6, HSTATE_DSCR(r13)
        mtspr   SPRN_DSCR, r6
-       li      r0, 0
-       stb     r0, HSTATE_FAKE_SUSPEND(r13)
+BEGIN_FTR_SECTION_NESTED(96)
+       bl      pnv_power9_force_smt4_release
+END_FTR_SECTION_NESTED(CPU_FTR_P9_TM_XER_SO_BUG, CPU_FTR_P9_TM_XER_SO_BUG, 96)
+       nop
+
+4:
        mfspr   r3, SPRN_PSSCR
        /* PSSCR_FAKE_SUSPEND is a write-only bit, but clear it anyway */
        li      r0, PSSCR_FAKE_SUSPEND
@@ -3244,6 +3257,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
        std     r6, VCPU_TFIAR(r9)
        std     r7, VCPU_TEXASR(r9)
 
+       addi    r1, r1, PPC_MIN_STKFRM
        ld      r0, PPC_LR_STKOFF(r1)
        mtlr    r0
        blr
@@ -3278,6 +3292,8 @@ kvmppc_restore_tm:
        mtspr   SPRN_TFIAR, r6
        mtspr   SPRN_TEXASR, r7
 
+       li      r0, 0
+       stb     r0, HSTATE_FAKE_SUSPEND(r13)
        ld      r5, VCPU_MSR(r4)
        rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
        beqlr           /* TM not active in guest */