| From 2b4a5a5d56881ece3c66b9a9a8943a6f41bd7349 Mon Sep 17 00:00:00 2001 |
| From: Sean Christopherson <seanjc@google.com> |
| Date: Thu, 25 Nov 2021 01:49:43 +0000 |
| Subject: KVM: nVMX: Flush current VPID (L1 vs. L2) for KVM_REQ_TLB_FLUSH_GUEST |
| |
| From: Sean Christopherson <seanjc@google.com> |
| |
| commit 2b4a5a5d56881ece3c66b9a9a8943a6f41bd7349 upstream. |
| |
| Flush the current VPID when handling KVM_REQ_TLB_FLUSH_GUEST instead of |
| always flushing vpid01. Any TLB flush that is triggered when L2 is |
| active is scoped to L2's VPID (if it has one), e.g. if L2 toggles CR4.PGE |
| and L1 doesn't intercept PGE writes, then KVM's emulation of the TLB |
| flush needs to be applied to L2's VPID. |
| |
| Reported-by: Lai Jiangshan <jiangshanlai+lkml@gmail.com> |
| Fixes: 07ffaf343e34 ("KVM: nVMX: Sync all PGDs on nested transition with shadow paging") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Sean Christopherson <seanjc@google.com> |
| Message-Id: <20211125014944.536398-2-seanjc@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/kvm/vmx/vmx.c | 23 ++++++++++++++--------- |
| 1 file changed, 14 insertions(+), 9 deletions(-) |
| |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -2908,6 +2908,13 @@ static void vmx_flush_tlb_all(struct kvm |
| } |
| } |
| |
| +static inline int vmx_get_current_vpid(struct kvm_vcpu *vcpu) |
| +{ |
| + if (is_guest_mode(vcpu)) |
| + return nested_get_vpid02(vcpu); |
| + return to_vmx(vcpu)->vpid; |
| +} |
| + |
| static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) |
| { |
| struct kvm_mmu *mmu = vcpu->arch.mmu; |
| @@ -2920,31 +2927,29 @@ static void vmx_flush_tlb_current(struct |
| if (enable_ept) |
| ept_sync_context(construct_eptp(vcpu, root_hpa, |
| mmu->shadow_root_level)); |
| - else if (!is_guest_mode(vcpu)) |
| - vpid_sync_context(to_vmx(vcpu)->vpid); |
| else |
| - vpid_sync_context(nested_get_vpid02(vcpu)); |
| + vpid_sync_context(vmx_get_current_vpid(vcpu)); |
| } |
| |
| static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr) |
| { |
| /* |
| - * vpid_sync_vcpu_addr() is a nop if vmx->vpid==0, see the comment in |
| + * vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in |
| * vmx_flush_tlb_guest() for an explanation of why this is ok. |
| */ |
| - vpid_sync_vcpu_addr(to_vmx(vcpu)->vpid, addr); |
| + vpid_sync_vcpu_addr(vmx_get_current_vpid(vcpu), addr); |
| } |
| |
| static void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu) |
| { |
| /* |
| - * vpid_sync_context() is a nop if vmx->vpid==0, e.g. if enable_vpid==0 |
| - * or a vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit |
| - * are required to flush GVA->{G,H}PA mappings from the TLB if vpid is |
| + * vpid_sync_context() is a nop if vpid==0, e.g. if enable_vpid==0 or a |
| + * vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit are |
| + * required to flush GVA->{G,H}PA mappings from the TLB if vpid is |
| * disabled (VM-Enter with vpid enabled and vpid==0 is disallowed), |
| * i.e. no explicit INVVPID is necessary. |
| */ |
| - vpid_sync_context(to_vmx(vcpu)->vpid); |
| + vpid_sync_context(vmx_get_current_vpid(vcpu)); |
| } |
| |
| void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu) |