KVM: PPC: Book3S HV P9: Implement TM fastpath for guest entry/exit
authorNicholas Piggin <npiggin@gmail.com>
Tue, 23 Nov 2021 09:52:10 +0000 (19:52 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 24 Nov 2021 10:09:00 +0000 (21:09 +1100)
If TM is not active, only TM register state needs to be saved and
restored, avoiding several mfmsr/mtmsrd instructions and improving
performance.

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-33-npiggin@gmail.com
arch/powerpc/kvm/book3s_hv_p9_entry.c

index fa08053..6bef509 100644 (file)
@@ -287,11 +287,20 @@ bool load_vcpu_state(struct kvm_vcpu *vcpu,
 {
        bool ret = false;
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (cpu_has_feature(CPU_FTR_TM) ||
            cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) {
-               kvmppc_restore_tm_hv(vcpu, vcpu->arch.shregs.msr, true);
-               ret = true;
+               unsigned long guest_msr = vcpu->arch.shregs.msr;
+               if (MSR_TM_ACTIVE(guest_msr)) {
+                       kvmppc_restore_tm_hv(vcpu, guest_msr, true);
+                       ret = true;
+               } else {
+                       mtspr(SPRN_TEXASR, vcpu->arch.texasr);
+                       mtspr(SPRN_TFHAR, vcpu->arch.tfhar);
+                       mtspr(SPRN_TFIAR, vcpu->arch.tfiar);
+               }
        }
+#endif
 
        load_spr_state(vcpu, host_os_sprs);
 
@@ -315,9 +324,19 @@ void store_vcpu_state(struct kvm_vcpu *vcpu)
 #endif
        vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (cpu_has_feature(CPU_FTR_TM) ||
-           cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
-               kvmppc_save_tm_hv(vcpu, vcpu->arch.shregs.msr, true);
+           cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) {
+               unsigned long guest_msr = vcpu->arch.shregs.msr;
+               if (MSR_TM_ACTIVE(guest_msr)) {
+                       kvmppc_save_tm_hv(vcpu, guest_msr, true);
+               } else {
+                       vcpu->arch.texasr = mfspr(SPRN_TEXASR);
+                       vcpu->arch.tfhar = mfspr(SPRN_TFHAR);
+                       vcpu->arch.tfiar = mfspr(SPRN_TFIAR);
+               }
+       }
+#endif
 }
 EXPORT_SYMBOL_GPL(store_vcpu_state);