Merge branch 'topic/paca' into next
[linux-2.6-microblaze.git] / arch / powerpc / kvm / book3s_hv_rmhandlers.S
index a1c6ea2..95c616f 100644 (file)
@@ -786,12 +786,18 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * Branch around the call if both CPU_FTR_TM and
+ * CPU_FTR_P9_TM_HV_ASSIST are off.
+ */
 BEGIN_FTR_SECTION
+       b       91f
+END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
        /*
         * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
         */
        bl      kvmppc_restore_tm
-END_FTR_SECTION_IFSET(CPU_FTR_TM)
+91:
 #endif
 
        /* Load guest PMU registers */
@@ -885,8 +891,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
        ld      r6, VCPU_DAWRX(r4)
        ld      r7, VCPU_CIABR(r4)
        ld      r8, VCPU_TAR(r4)
+       /*
+        * Handle broken DAWR case by not writing it. This means we
+        * can still store the DAWR register for migration.
+        */
+BEGIN_FTR_SECTION
        mtspr   SPRN_DAWR, r5
        mtspr   SPRN_DAWRX, r6
+END_FTR_SECTION_IFSET(CPU_FTR_DAWR)
        mtspr   SPRN_CIABR, r7
        mtspr   SPRN_TAR, r8
        ld      r5, VCPU_IC(r4)
@@ -914,11 +926,14 @@ BEGIN_FTR_SECTION
        mtspr   SPRN_ACOP, r6
        mtspr   SPRN_CSIGR, r7
        mtspr   SPRN_TACR, r8
+       nop
 FTR_SECTION_ELSE
        /* POWER9-only registers */
        ld      r5, VCPU_TID(r4)
        ld      r6, VCPU_PSSCR(r4)
+       lbz     r8, HSTATE_FAKE_SUSPEND(r13)
        oris    r6, r6, PSSCR_EC@h      /* This makes stop trap to HV */
+       rldimi  r6, r8, PSSCR_FAKE_SUSPEND_LG, 63 - PSSCR_FAKE_SUSPEND_LG
        ld      r7, VCPU_HFSCR(r4)
        mtspr   SPRN_TIDR, r5
        mtspr   SPRN_PSSCR, r6
@@ -1369,6 +1384,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        std     r3, VCPU_CTR(r9)
        std     r4, VCPU_XER(r9)
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* For softpatch interrupt, go off and do TM instruction emulation */
+       cmpwi   r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
+       beq     kvmppc_tm_emul
+#endif
+
        /* If this is a page table miss then see if it's theirs or ours */
        cmpwi   r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
        beq     kvmppc_hdsi
@@ -1728,12 +1749,18 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
        bl      kvmppc_save_fp
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * Branch around the call if both CPU_FTR_TM and
+ * CPU_FTR_P9_TM_HV_ASSIST are off.
+ */
 BEGIN_FTR_SECTION
+       b       91f
+END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
        /*
         * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
         */
        bl      kvmppc_save_tm
-END_FTR_SECTION_IFSET(CPU_FTR_TM)
+91:
 #endif
 
        /* Increment yield count if they have a VPA */
@@ -1833,6 +1860,10 @@ BEGIN_FTR_SECTION
        ld      r6, STACK_SLOT_DAWR(r1)
        ld      r7, STACK_SLOT_DAWRX(r1)
        mtspr   SPRN_CIABR, r5
+       /*
+        * If the DAWR doesn't work, it's ok to write these here as
+        * this value should always be zero
+       */
        mtspr   SPRN_DAWR, r6
        mtspr   SPRN_DAWRX, r7
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
@@ -2053,6 +2084,42 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
        mtlr    r0
        blr
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * Softpatch interrupt for transactional memory emulation cases
+ * on POWER9 DD2.2.  This is early in the guest exit path - we
+ * haven't saved registers or done a treclaim yet.
+ */
+kvmppc_tm_emul:
+       /* Save instruction image in HEIR */
+       mfspr   r3, SPRN_HEIR
+       stw     r3, VCPU_HEIR(r9)
+
+       /*
+        * The cases we want to handle here are those where the guest
+        * is in real suspend mode and is trying to transition to
+        * transactional mode.
+        */
+       lbz     r0, HSTATE_FAKE_SUSPEND(r13)
+       cmpwi   r0, 0           /* keep exiting guest if in fake suspend */
+       bne     guest_exit_cont
+       rldicl  r3, r11, 64 - MSR_TS_S_LG, 62
+       cmpwi   r3, 1           /* or if not in suspend state */
+       bne     guest_exit_cont
+
+       /* Call C code to do the emulation */
+       mr      r3, r9
+       bl      kvmhv_p9_tm_emulation_early
+       nop
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       li      r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
+       cmpwi   r3, 0
+       beq     guest_exit_cont         /* continue exiting if not handled */
+       ld      r10, VCPU_PC(r9)
+       ld      r11, VCPU_MSR(r9)
+       b       fast_interrupt_c_return /* go back to guest if handled */
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
 /*
  * Check whether an HDSI is an HPTE not found fault or something else.
  * If it is an HPTE not found fault that is due to the guest accessing
@@ -2505,8 +2572,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        li      r3,0
        blr
 
+2:
+BEGIN_FTR_SECTION
+       /* POWER9 with disabled DAWR */
+       li      r3, H_UNSUPPORTED
+       blr
+END_FTR_SECTION_IFCLR(CPU_FTR_DAWR)
        /* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
-2:     rlwimi  r5, r4, 5, DAWRX_DR | DAWRX_DW
+       rlwimi  r5, r4, 5, DAWRX_DR | DAWRX_DW
        rlwimi  r5, r4, 2, DAWRX_WT
        clrrdi  r4, r4, 3
        std     r4, VCPU_DAWR(r3)
@@ -2586,13 +2659,19 @@ _GLOBAL(kvmppc_h_cede)          /* r3 = vcpu pointer, r11 = msr, r13 = paca */
        bl      kvmppc_save_fp
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * Branch around the call if both CPU_FTR_TM and
+ * CPU_FTR_P9_TM_HV_ASSIST are off.
+ */
 BEGIN_FTR_SECTION
+       b       91f
+END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
        /*
         * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
         */
        ld      r9, HSTATE_KVM_VCPU(r13)
        bl      kvmppc_save_tm
-END_FTR_SECTION_IFSET(CPU_FTR_TM)
+91:
 #endif
 
        /*
@@ -2699,12 +2778,18 @@ kvm_end_cede:
 #endif
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * Branch around the call if both CPU_FTR_TM and
+ * CPU_FTR_P9_TM_HV_ASSIST are off.
+ */
 BEGIN_FTR_SECTION
+       b       91f
+END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
        /*
         * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
         */
        bl      kvmppc_restore_tm
-END_FTR_SECTION_IFSET(CPU_FTR_TM)
+91:
 #endif
 
        /* load up FP state */
@@ -3031,6 +3116,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
@@ -3045,6 +3131,24 @@ kvmppc_save_tm:
        std     r1, HSTATE_HOST_R1(r13)
        li      r3, TM_CAUSE_KVM_RESCHED
 
+BEGIN_FTR_SECTION
+       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
+       b       6f
+3:
+       /* Emulation of the treclaim instruction needs TEXASR before treclaim */
+       mfspr   r6, SPRN_TEXASR
+       std     r6, VCPU_ORIG_TEXASR(r9)
+6:
+END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
+
        /* Clear the MSR RI since r1, r13 are all going to be foobar. */
        li      r5, 0
        mtmsrd  r5, 1
@@ -3056,6 +3160,43 @@ kvmppc_save_tm:
        SET_SCRATCH0(r13)
        GET_PACA(r13)
        std     r9, PACATMSCRATCH(r13)
+
+       /* If doing TM emulation on POWER9 DD2.2, check for fake suspend mode */
+BEGIN_FTR_SECTION
+       lbz     r9, HSTATE_FAKE_SUSPEND(r13)
+       cmpwi   r9, 0
+       beq     2f
+       /*
+        * We were in fake suspend, so we are not going to save the
+        * register state as the guest checkpointed state (since
+        * we already have it), therefore we can now use any volatile GPR.
+        */
+       /* 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
+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
+       andc    r3, r3, r0
+       mtspr   SPRN_PSSCR, r3
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       /* Don't save TEXASR, use value from last exit in real suspend state */
+       b       11f
+2:
+END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
+
        ld      r9, HSTATE_KVM_VCPU(r13)
 
        /* Get a few more GPRs free. */
@@ -3126,13 +3267,15 @@ kvmppc_save_tm:
         * change these outside of a transaction, so they must always be
         * context switched.
         */
+       mfspr   r7, SPRN_TEXASR
+       std     r7, VCPU_TEXASR(r9)
+11:
        mfspr   r5, SPRN_TFHAR
        mfspr   r6, SPRN_TFIAR
-       mfspr   r7, SPRN_TEXASR
        std     r5, VCPU_TFHAR(r9)
        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
@@ -3167,6 +3310,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 */
@@ -3180,6 +3325,15 @@ kvmppc_restore_tm:
        oris    r7, r7, (TEXASR_FS)@h
        mtspr   SPRN_TEXASR, r7
 
+       /*
+        * If we are doing TM emulation for the guest on a POWER9 DD2,
+        * then we don't actually do a trechkpt -- we either set up
+        * fake-suspend mode, or emulate a TM rollback.
+        */
+BEGIN_FTR_SECTION
+       b       .Ldo_tm_fake_load
+END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
+
        /*
         * We need to load up the checkpointed state for the guest.
         * We need to do this early as it will blow away any GPRs, VSRs and
@@ -3252,10 +3406,24 @@ kvmppc_restore_tm:
        /* Set the MSR RI since we have our registers back. */
        li      r5, MSR_RI
        mtmsrd  r5, 1
-
+9:
        ld      r0, PPC_LR_STKOFF(r1)
        mtlr    r0
        blr
+
+.Ldo_tm_fake_load:
+       cmpwi   r5, 1           /* check for suspended state */
+       bgt     10f
+       stb     r5, HSTATE_FAKE_SUSPEND(r13)
+       b       9b              /* and return */
+10:    stdu    r1, -PPC_MIN_STKFRM(r1)
+       /* guest is in transactional state, so simulate rollback */
+       mr      r3, r4
+       bl      kvmhv_emulate_tm_rollback
+       nop
+       ld      r4, HSTATE_KVM_VCPU(r13) /* our vcpu pointer has been trashed */
+       addi    r1, r1, PPC_MIN_STKFRM
+       b       9b
 #endif
 
 /*