KVM: PPC: Book3S HV: Do SLB load/unload with guest LPCR value loaded
authorPaul Mackerras <paulus@ozlabs.org>
Thu, 11 Jan 2018 03:51:02 +0000 (14:51 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Wed, 17 Jan 2018 00:19:02 +0000 (11:19 +1100)
This moves the code that loads and unloads the guest SLB values so that
it is done while the guest LPCR value is loaded in the LPCR register.
The reason for doing this is that on POWER9, the behaviour of the
slbmte instruction depends on the LPCR[UPRT] bit.  If UPRT is 1, as
it is for a radix host (or guest), the SLB index is truncated to
2 bits.  This means that for a HPT guest on a radix host, the SLB
was not being loaded correctly, causing the guest to crash.

The SLB is now loaded much later in the guest entry path, after the
LPCR is loaded, which for a secondary thread is after it sees that
the primary thread has switched the MMU to the guest.  The loop that
waits for the primary thread has a branch out to the exit code that
is taken if it sees that other threads have commenced exiting the
guest.  Since we have now not loaded the SLB at this point, we make
this path branch to a new label 'guest_bypass' and we move the SLB
unload code to before this label.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index 76332a3..30ece4c 100644 (file)
@@ -617,13 +617,6 @@ kvmppc_hv_entry:
        lbz     r0, KVM_RADIX(r9)
        cmpwi   cr7, r0, 0
 
-       /* Clear out SLB if hash */
-       bne     cr7, 2f
-       li      r6,0
-       slbmte  r6,r6
-       slbia
-       ptesync
-2:
        /*
         * POWER7/POWER8 host -> guest partition switch code.
         * We don't have to lock against concurrent tlbies,
@@ -738,19 +731,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 10:    cmpdi   r4, 0
        beq     kvmppc_primary_no_guest
 kvmppc_got_guest:
-
-       /* Load up guest SLB entries (N.B. slb_max will be 0 for radix) */
-       lwz     r5,VCPU_SLB_MAX(r4)
-       cmpwi   r5,0
-       beq     9f
-       mtctr   r5
-       addi    r6,r4,VCPU_SLB
-1:     ld      r8,VCPU_SLB_E(r6)
-       ld      r9,VCPU_SLB_V(r6)
-       slbmte  r9,r8
-       addi    r6,r6,VCPU_SLB_SIZE
-       bdnz    1b
-9:
        /* Increment yield count if they have a VPA */
        ld      r3, VCPU_VPA(r4)
        cmpdi   r3, 0
@@ -1017,6 +997,29 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
        cmpdi   r3, 512         /* 1 microsecond */
        blt     hdec_soon
 
+       /* For hash guest, clear out and reload the SLB */
+       ld      r6, VCPU_KVM(r4)
+       lbz     r0, KVM_RADIX(r6)
+       cmpwi   r0, 0
+       bne     9f
+       li      r6, 0
+       slbmte  r6, r6
+       slbia
+       ptesync
+
+       /* Load up guest SLB entries (N.B. slb_max will be 0 for radix) */
+       lwz     r5,VCPU_SLB_MAX(r4)
+       cmpwi   r5,0
+       beq     9f
+       mtctr   r5
+       addi    r6,r4,VCPU_SLB
+1:     ld      r8,VCPU_SLB_E(r6)
+       ld      r9,VCPU_SLB_V(r6)
+       slbmte  r9,r8
+       addi    r6,r6,VCPU_SLB_SIZE
+       bdnz    1b
+9:
+
 #ifdef CONFIG_KVM_XICS
        /* We are entering the guest on that thread, push VCPU to XIVE */
        ld      r10, HSTATE_XIVE_TIMA_PHYS(r13)
@@ -1193,7 +1196,7 @@ hdec_soon:
        addi    r3, r4, VCPU_TB_RMEXIT
        bl      kvmhv_accumulate_time
 #endif
-       b       guest_exit_cont
+       b       guest_bypass
 
 /******************************************************************************
  *                                                                            *
@@ -1481,34 +1484,12 @@ mc_cont:
 1:
 #endif /* CONFIG_KVM_XICS */
 
-       mr      r3, r12
-       /* Increment exit count, poke other threads to exit */
-       bl      kvmhv_commence_exit
-       nop
-       ld      r9, HSTATE_KVM_VCPU(r13)
-       lwz     r12, VCPU_TRAP(r9)
-
-       /* Stop others sending VCPU interrupts to this physical CPU */
-       li      r0, -1
-       stw     r0, VCPU_CPU(r9)
-       stw     r0, VCPU_THREAD_CPU(r9)
-
-       /* Save guest CTRL register, set runlatch to 1 */
-       mfspr   r6,SPRN_CTRLF
-       stw     r6,VCPU_CTRL(r9)
-       andi.   r0,r6,1
-       bne     4f
-       ori     r6,r6,1
-       mtspr   SPRN_CTRLT,r6
-4:
-       /* Check if we are running hash or radix and store it in cr2 */
+       /* For hash guest, read the guest SLB and save it away */
        ld      r5, VCPU_KVM(r9)
        lbz     r0, KVM_RADIX(r5)
-       cmpwi   cr2,r0,0
-
-       /* Read the guest SLB and save it away */
        li      r5, 0
-       bne     cr2, 3f                 /* for radix, save 0 entries */
+       cmpwi   r0, 0
+       bne     3f                      /* for radix, save 0 entries */
        lwz     r0,VCPU_SLB_NR(r9)      /* number of entries in SLB */
        mtctr   r0
        li      r6,0
@@ -1524,8 +1505,34 @@ mc_cont:
        addi    r5,r5,1
 2:     addi    r6,r6,1
        bdnz    1b
+       /* Finally clear out the SLB */
+       li      r0,0
+       slbmte  r0,r0
+       slbia
+       ptesync
 3:     stw     r5,VCPU_SLB_MAX(r9)
 
+guest_bypass:
+       mr      r3, r12
+       /* Increment exit count, poke other threads to exit */
+       bl      kvmhv_commence_exit
+       nop
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       lwz     r12, VCPU_TRAP(r9)
+
+       /* Stop others sending VCPU interrupts to this physical CPU */
+       li      r0, -1
+       stw     r0, VCPU_CPU(r9)
+       stw     r0, VCPU_THREAD_CPU(r9)
+
+       /* Save guest CTRL register, set runlatch to 1 */
+       mfspr   r6,SPRN_CTRLF
+       stw     r6,VCPU_CTRL(r9)
+       andi.   r0,r6,1
+       bne     4f
+       ori     r6,r6,1
+       mtspr   SPRN_CTRLT,r6
+4:
        /*
         * Save the guest PURR/SPURR
         */
@@ -1803,7 +1810,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        ld      r5, VCPU_KVM(r9)
        lbz     r0, KVM_RADIX(r5)
        cmpwi   cr2, r0, 0
-       beq     cr2, 3f
+       beq     cr2, 4f
 
        /* Radix: Handle the case where the guest used an illegal PID */
        LOAD_REG_ADDR(r4, mmu_base_pid)
@@ -1839,15 +1846,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 BEGIN_FTR_SECTION
        PPC_INVALIDATE_ERAT
 END_FTR_SECTION_IFSET(CPU_FTR_POWER9_DD1)
-       b       4f
+4:
 #endif /* CONFIG_PPC_RADIX_MMU */
 
-       /* Hash: clear out SLB */
-3:     li      r5,0
-       slbmte  r5,r5
-       slbia
-       ptesync
-4:
        /*
         * POWER7/POWER8 guest -> host partition switch code.
         * We don't have to lock against tlbies but we do