Skip to content

Commit 249cc1a

Browse files
committed
KVM: nVMX: Switch to vmcs01 to set virtual APICv mode on-demand if L2 is active
If L1's virtual APIC mode changes while L2 is active, e.g. because L1 doesn't intercept writes to the APIC_BASE MSR and L2 changes the mode, temporarily load vmcs01 and do all of the necessary actions instead of deferring the update until the next nested VM-Exit. This will help in fixing yet more issues related to updates while L2 is active, e.g. KVM neglects to update vmcs02 MSR intercepts if vmcs01's MSR intercepts are modified while L2 is active. Not updating x2APIC MSRs is benign because vmcs01's settings are not factored into vmcs02's bitmap, but deferring the x2APIC MSR updates would create a weird, inconsistent state. Reviewed-by: Chao Gao <chao.gao@intel.com> Link: https://patch.msgid.link/20260109034532.1012993-8-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 51c821d commit 249cc1a

3 files changed

Lines changed: 11 additions & 13 deletions

File tree

arch/x86/kvm/vmx/nested.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5122,11 +5122,6 @@ void __nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
51225122
if (kvm_caps.has_tsc_control)
51235123
vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio);
51245124

5125-
if (vmx->nested.change_vmcs01_virtual_apic_mode) {
5126-
vmx->nested.change_vmcs01_virtual_apic_mode = false;
5127-
vmx_set_virtual_apic_mode(vcpu);
5128-
}
5129-
51305125
nested_put_vmcs12_pages(vcpu);
51315126

51325127
if ((vm_exit_reason != -1) &&

arch/x86/kvm/vmx/vmx.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6851,11 +6851,7 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
68516851
!cpu_has_vmx_virtualize_x2apic_mode())
68526852
return;
68536853

6854-
/* Postpone execution until vmcs01 is the current VMCS. */
6855-
if (is_guest_mode(vcpu)) {
6856-
vmx->nested.change_vmcs01_virtual_apic_mode = true;
6857-
return;
6858-
}
6854+
guard(vmx_vmcs01)(vcpu);
68596855

68606856
sec_exec_control = secondary_exec_controls_get(vmx);
68616857
sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
@@ -6878,8 +6874,17 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
68786874
* only do so if its physical address has changed, but
68796875
* the guest may have inserted a non-APIC mapping into
68806876
* the TLB while the APIC access page was disabled.
6877+
*
6878+
* If L2 is active, immediately flush L1's TLB instead
6879+
* of requesting a flush of the current TLB, because
6880+
* the current TLB context is L2's.
68816881
*/
6882-
kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
6882+
if (!is_guest_mode(vcpu))
6883+
kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
6884+
else if (!enable_ept)
6885+
vpid_sync_context(vmx->vpid);
6886+
else if (VALID_PAGE(vcpu->arch.root_mmu.root.hpa))
6887+
vmx_flush_tlb_ept_root(vcpu->arch.root_mmu.root.hpa);
68836888
}
68846889
break;
68856890
case LAPIC_MODE_X2APIC:

arch/x86/kvm/vmx/vmx.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ struct nested_vmx {
131131
*/
132132
bool vmcs02_initialized;
133133

134-
bool change_vmcs01_virtual_apic_mode;
135-
136134
/*
137135
* Enlightened VMCS has been enabled. It does not mean that L1 has to
138136
* use it. However, VMX features available to L1 will be limited based

0 commit comments

Comments
 (0)