Flush both L1 and L2 ASIDs in svm_flush_tlb_all() to appropriately handle KVM_REQ_TLB_FLUSH by flushing all TLB entries in all contexts (e.g. for kvm_flush_remote_tlbs()). Since both L1 and L2 currently share an ASID, this is effectively a noop, but it won't be once L2 has a separate ASID. Purge all Hyper-V TLB FIFOs (for both L1 and L2), since both ASIDs are flushed, and an ASID flush is a superset of Hyper-V's fine-grained flushing (see comment in svm_flush_tlb_asid()). Note that if one TLB flush FIFO is purged (e.g. as a result of KVM_REQ_TLB_FLUSH_CURRENT), it will consume KVM_REQ_HV_TLB_FLUSH, and a subsequent KVM_REQ_TLB_FLUSH will not flush the other FIFO. This is alright as flushing both FIFOs is a (newly introduced) optimization anyway. The other FIFO will be checked after a nested transition, as KVM_REQ_HV_TLB_FLUSH is always set on nested transitions. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/hyperv.h | 6 ++++++ arch/x86/kvm/svm/nested.c | 1 - arch/x86/kvm/svm/svm.c | 8 +++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index a23ef05c1075c..b82f70e6fcea1 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -337,6 +337,11 @@ static inline void kvm_hv_purge_tlb_flush_fifo(struct kvm_vcpu *vcpu) __kvm_hv_purge_tlb_flush_fifo(vcpu, fifo); } +static inline void kvm_hv_purge_all_tlb_flush_fifos(struct kvm_vcpu *vcpu) +{ + __kvm_hv_purge_tlb_flush_fifo(vcpu, NULL); +} + static inline bool guest_hv_cpuid_has_l2_tlb_flush(struct kvm_vcpu *vcpu) { struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); @@ -408,6 +413,7 @@ static inline int kvm_hv_hypercall(struct kvm_vcpu *vcpu) return HV_STATUS_ACCESS_DENIED; } static inline void kvm_hv_purge_tlb_flush_fifo(struct kvm_vcpu *vcpu) {} +static inline void kvm_hv_purge_all_tlb_flush_fifos(struct kvm_vcpu *vcpu) {} static inline bool kvm_hv_synic_has_vector(struct kvm_vcpu *vcpu, int vector) { return false; diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index a8bf847209618..a6a49a5e0d90a 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -694,7 +694,6 @@ static void nested_svm_transition_tlb_flush(struct kvm_vcpu *vcpu) * TODO: optimize unconditional TLB flush/MMU sync. A partial list of * things to fix before this can be conditional: * - * - Flush TLBs for both L1 and L2 remote TLB flush * - Honor L1's request to flush an ASID on nested VMRUN * - Sync nested NPT MMU on VMRUN that flushes L2's ASID[*] * - Don't crush a pending TLB flush in vmcb02 on nested VMRUN diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 991171df83486..1a8dae05f4ab5 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4225,6 +4225,8 @@ static void svm_flush_tlb_current(struct kvm_vcpu *vcpu) static void svm_flush_tlb_all(struct kvm_vcpu *vcpu) { + struct vcpu_svm *svm = to_svm(vcpu); + /* * When running on Hyper-V with EnlightenedNptTlb enabled, remote TLB * flushes should be routed to hv_flush_remote_tlbs() without requesting @@ -4235,7 +4237,11 @@ static void svm_flush_tlb_all(struct kvm_vcpu *vcpu) if (WARN_ON_ONCE(svm_hv_is_enlightened_tlb_enabled(vcpu))) hv_flush_remote_tlbs(vcpu->kvm); - svm_flush_tlb_asid(vcpu); + kvm_hv_purge_all_tlb_flush_fifos(vcpu); + + vmcb_set_flush_asid(svm->vmcb01.ptr); + if (svm->nested.vmcb02.ptr) + vmcb_set_flush_asid(svm->nested.vmcb02.ptr); } static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva) -- 2.55.0.229.g6434b31f56-goog