KVM: PPC: Book3S HV: POWER9 does not require secondary thread management
authorNicholas Piggin <npiggin@gmail.com>
Fri, 25 Aug 2017 04:30:33 +0000 (14:30 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 29 Aug 2017 04:48:59 +0000 (14:48 +1000)
POWER9 CPUs have independent MMU contexts per thread, so KVM does not
need to quiesce secondary threads, so the hwthread_req/hwthread_state
protocol does not have to be used. So patch it away on POWER9, and patch
away the branch from the Linux idle wakeup to kvm_start_guest that is
never used.

Add a warning and error out of kvmppc_grab_hwthread in case it is ever
called on POWER9.

This avoids a hwsync in the idle wakeup path on POWER9.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Acked-by: Paul Mackerras <paulus@ozlabs.org>
[mpe: Use WARN(...) instead of WARN_ON()/pr_err(...)]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/kernel/idle_book3s.S
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index 7cea76f11c26c66fc52e08aae5b37e6534ac79a8..83596f32f50b49672d7ced5f3ee806c921406114 100644 (file)
@@ -104,6 +104,10 @@ struct kvmppc_host_state {
        u8 napping;
 
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+       /*
+        * hwthread_req/hwthread_state pair is used to pull sibling threads
+        * out of guest on pre-ISAv3.0B CPUs where threads share MMU.
+        */
        u8 hwthread_req;
        u8 hwthread_state;
        u8 host_ipi;
index 516ebef905c063b6bdb696f5f6048da37f7822cd..294d024bfb61aa7613b2f329af02a819a759a33f 100644 (file)
@@ -242,13 +242,20 @@ enter_winkle:
 /*
  * r3 - PSSCR value corresponding to the requested stop state.
  */
-power_enter_stop:
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
-       /* Tell KVM we're entering idle */
+power_enter_stop_kvm_rm:
+       /*
+        * This is currently unused because POWER9 KVM does not have to
+        * gather secondary threads into sibling mode, but the code is
+        * here in case that function is required.
+        *
+        * Tell KVM we're entering idle.
+        */
        li      r4,KVM_HWTHREAD_IN_IDLE
        /* DO THIS IN REAL MODE!  See comment above. */
        stb     r4,HSTATE_HWTHREAD_STATE(r13)
 #endif
+power_enter_stop:
 /*
  * Check if we are executing the lite variant with ESL=EC=0
  */
@@ -411,6 +418,18 @@ pnv_powersave_wakeup_mce:
 
        b       pnv_powersave_wakeup
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+kvm_start_guest_check:
+       li      r0,KVM_HWTHREAD_IN_KERNEL
+       stb     r0,HSTATE_HWTHREAD_STATE(r13)
+       /* Order setting hwthread_state vs. testing hwthread_req */
+       sync
+       lbz     r0,HSTATE_HWTHREAD_REQ(r13)
+       cmpwi   r0,0
+       beqlr
+       b       kvm_start_guest
+#endif
+
 /*
  * Called from reset vector for powersave wakeups.
  * cr3 - set to gt if waking up with partial/complete hypervisor state loss
@@ -435,15 +454,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
        mr      r3,r12
 
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
-       li      r0,KVM_HWTHREAD_IN_KERNEL
-       stb     r0,HSTATE_HWTHREAD_STATE(r13)
-       /* Order setting hwthread_state vs. testing hwthread_req */
-       sync
-       lbz     r0,HSTATE_HWTHREAD_REQ(r13)
-       cmpwi   r0,0
-       beq     1f
-       b       kvm_start_guest
-1:
+BEGIN_FTR_SECTION
+       bl      kvm_start_guest_check
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
 #endif
 
        /* Return SRR1 from power7_nap() */
index 0b436df746fcb094d8bd8b3c928c0862d6a90df5..8bad44b46dc887bb034582b3b2df38ca498ded25 100644 (file)
@@ -2111,6 +2111,15 @@ static int kvmppc_grab_hwthread(int cpu)
        struct paca_struct *tpaca;
        long timeout = 10000;
 
+       /*
+        * ISA v3.0 idle routines do not set hwthread_state or test
+        * hwthread_req, so they can not grab idle threads.
+        */
+       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+               WARN(1, "KVM: can not control sibling threads\n");
+               return -EBUSY;
+       }
+
        tpaca = &paca[cpu];
 
        /* Ensure the thread won't go into the kernel if it wakes */
@@ -2145,10 +2154,12 @@ static void kvmppc_release_hwthread(int cpu)
        struct paca_struct *tpaca;
 
        tpaca = &paca[cpu];
-       tpaca->kvm_hstate.hwthread_req = 0;
        tpaca->kvm_hstate.kvm_vcpu = NULL;
        tpaca->kvm_hstate.kvm_vcore = NULL;
        tpaca->kvm_hstate.kvm_split_mode = NULL;
+       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+               tpaca->kvm_hstate.hwthread_req = 0;
+
 }
 
 static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu)
index cb44065e29463f99d6c44bf129ca01e82695a8ff..eacf3d06eb75cb2f97386ac1fa4b89d6006e0e45 100644 (file)
@@ -149,9 +149,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        subf    r4, r4, r3
        mtspr   SPRN_DEC, r4
 
+BEGIN_FTR_SECTION
        /* hwthread_req may have got set by cede or no vcpu, so clear it */
        li      r0, 0
        stb     r0, HSTATE_HWTHREAD_REQ(r13)
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
 
        /*
         * For external interrupts we need to call the Linux
@@ -314,6 +316,7 @@ kvm_novcpu_exit:
  * Relocation is off and most register values are lost.
  * r13 points to the PACA.
  * r3 contains the SRR1 wakeup value, SRR1 is trashed.
+ * This is not used by ISAv3.0B processors.
  */
        .globl  kvm_start_guest
 kvm_start_guest:
@@ -432,6 +435,9 @@ kvm_secondary_got_guest:
  * While waiting we also need to check if we get given a vcpu to run.
  */
 kvm_no_guest:
+BEGIN_FTR_SECTION
+       twi     31,0,0
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        lbz     r3, HSTATE_HWTHREAD_REQ(r13)
        cmpwi   r3, 0
        bne     53f
@@ -2466,8 +2472,10 @@ kvm_do_nap:
        clrrdi  r0, r0, 1
        mtspr   SPRN_CTRLT, r0
 
+BEGIN_FTR_SECTION
        li      r0,1
        stb     r0,HSTATE_HWTHREAD_REQ(r13)
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
        mfspr   r5,SPRN_LPCR
        ori     r5,r5,LPCR_PECE0 | LPCR_PECE1
 BEGIN_FTR_SECTION