KVM: PPC: Book3S HV P9: Avoid SPR scoreboard stalls
authorNicholas Piggin <npiggin@gmail.com>
Tue, 23 Nov 2021 09:52:03 +0000 (19:52 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 24 Nov 2021 10:08:59 +0000 (21:08 +1100)
Avoid interleaving mfSPR and mtSPR to reduce SPR scoreboard stalls.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20211123095231.1036501-26-npiggin@gmail.com
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_p9_entry.c

index 3a9447f75a9ecf14b4078dca7970abf73256cd3f..75a674b5cd848797b0dcf8bf6b7087f99885d9b3 100644 (file)
@@ -4321,10 +4321,6 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
 
        store_spr_state(vcpu);
 
-       timer_rearm_host_dec(*tb);
-
-       restore_p9_host_os_sprs(vcpu, &host_os_sprs);
-
        store_fp_state(&vcpu->arch.fp);
 #ifdef CONFIG_ALTIVEC
        store_vr_state(&vcpu->arch.vr);
@@ -4339,6 +4335,10 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
 
        switch_pmu_to_host(vcpu, &host_os_sprs);
 
+       timer_rearm_host_dec(*tb);
+
+       restore_p9_host_os_sprs(vcpu, &host_os_sprs);
+
        vc->entry_exit_map = 0x101;
        vc->in_guest = 0;
 
index 2bd96d8256d11eb95c4ff1a57a0dd494f127ddcb..bd0021cd3a674f8962d419fe3461792b9459ad9c 100644 (file)
@@ -228,6 +228,9 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpc
                host_dawrx1 = mfspr(SPRN_DAWRX1);
        }
 
+       local_paca->kvm_hstate.host_purr = mfspr(SPRN_PURR);
+       local_paca->kvm_hstate.host_spurr = mfspr(SPRN_SPURR);
+
        if (vc->tb_offset) {
                u64 new_tb = *tb + vc->tb_offset;
                mtspr(SPRN_TBU40, new_tb);
@@ -244,8 +247,6 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpc
        mtspr(SPRN_DPDES, vc->dpdes);
        mtspr(SPRN_VTB, vc->vtb);
 
-       local_paca->kvm_hstate.host_purr = mfspr(SPRN_PURR);
-       local_paca->kvm_hstate.host_spurr = mfspr(SPRN_SPURR);
        mtspr(SPRN_PURR, vcpu->arch.purr);
        mtspr(SPRN_SPURR, vcpu->arch.spurr);
 
@@ -448,10 +449,8 @@ tm_return_to_guest:
        /* Advance host PURR/SPURR by the amount used by guest */
        purr = mfspr(SPRN_PURR);
        spurr = mfspr(SPRN_SPURR);
-       mtspr(SPRN_PURR, local_paca->kvm_hstate.host_purr +
-             purr - vcpu->arch.purr);
-       mtspr(SPRN_SPURR, local_paca->kvm_hstate.host_spurr +
-             spurr - vcpu->arch.spurr);
+       local_paca->kvm_hstate.host_purr += purr - vcpu->arch.purr;
+       local_paca->kvm_hstate.host_spurr += spurr - vcpu->arch.spurr;
        vcpu->arch.purr = purr;
        vcpu->arch.spurr = spurr;
 
@@ -464,6 +463,9 @@ tm_return_to_guest:
        vcpu->arch.shregs.sprg2 = mfspr(SPRN_SPRG2);
        vcpu->arch.shregs.sprg3 = mfspr(SPRN_SPRG3);
 
+       vc->dpdes = mfspr(SPRN_DPDES);
+       vc->vtb = mfspr(SPRN_VTB);
+
        dec = mfspr(SPRN_DEC);
        if (!(lpcr & LPCR_LD)) /* Sign extend if not using large decrementer */
                dec = (s32) dec;
@@ -481,6 +483,9 @@ tm_return_to_guest:
                vc->tb_offset_applied = 0;
        }
 
+       mtspr(SPRN_PURR, local_paca->kvm_hstate.host_purr);
+       mtspr(SPRN_SPURR, local_paca->kvm_hstate.host_spurr);
+
        /* Preserve PSSCR[FAKE_SUSPEND] until we've called kvmppc_save_tm_hv */
        mtspr(SPRN_PSSCR, host_psscr |
              (local_paca->kvm_hstate.fake_suspend << PSSCR_FAKE_SUSPEND_LG));
@@ -509,8 +514,6 @@ tm_return_to_guest:
        if (cpu_has_feature(CPU_FTR_ARCH_31))
                asm volatile(PPC_CP_ABORT);
 
-       vc->dpdes = mfspr(SPRN_DPDES);
-       vc->vtb = mfspr(SPRN_VTB);
        mtspr(SPRN_DPDES, 0);
        if (vc->pcr)
                mtspr(SPRN_PCR, PCR_MASK);