* [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS @ 2026-10-17 9:30 Amirmohammad Eftekhar 2026-10-17 9:40 ` sashiko-bot 2026-10-17 16:33 ` Amirmohammad Eftekhar 0 siblings, 2 replies; 4+ messages in thread From: Amirmohammad Eftekhar @ 2026-10-17 9:30 UTC (permalink / raw) To: seanjc, pbonzini; +Cc: kvm, linux-kernel vmx_load_eoi_exitmap() writes EOI_EXIT_BITMAP0..3 directly with vmcs_write64() and, unlike its siblings vmx_hwapic_isr_update() and vmx_sync_pir_to_irr(), does not take guard(vmx_vmcs01). The EOI-exit bitmap belongs to L1's APIC, but with nested virtual-interrupt-delivery an L2 can be active when KVM refreshes it (e.g. via kvm_vcpu_reload_apic_access_page() / vcpu_scan_ioapic()), so the writes land in vmcs02 instead of vmcs01: L2's EOI-exit bitmap is corrupted and vmcs01's is left stale until the next L1 refresh. Add guard(vmx_vmcs01), matching the sibling APICv callbacks. Signed-off-by: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de> --- arch/x86/kvm/vmx/vmx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b341af4c6..1f802cdbe 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7082,6 +7082,13 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) if (!kvm_vcpu_apicv_active(vcpu)) return; + /* + * The EOI-exit bitmap tracks L1's APIC, so it must land in vmcs01, not + * whichever VMCS is currently loaded; a nested VID L2 can be active + * here. Mirror vmx_hwapic_isr_update()/vmx_sync_pir_to_irr(). + */ + guard(vmx_vmcs01)(vcpu); + vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]); -- 2.54.0 (Apple Git-157) ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS 2026-10-17 9:30 [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS Amirmohammad Eftekhar @ 2026-10-17 9:40 ` sashiko-bot 2026-10-17 14:46 ` Sean Christopherson 2026-10-17 16:33 ` Amirmohammad Eftekhar 1 sibling, 1 reply; 4+ messages in thread From: sashiko-bot @ 2026-10-17 9:40 UTC (permalink / raw) To: Amirmohammad Eftekhar; +Cc: kvm Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] KVM: VMX: vmx_load_eoi_exitmap() comment mismatch and deferred L2 update -- commit b2b472dc800418ff9ed851c85722ed6e99a11a91 Author: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de> KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS This commit adds guard(vmx_vmcs01) to vmx_load_eoi_exitmap() so that updates to EOI_EXIT_BITMAP0..3 target vmcs01 rather than whichever VMCS happens to be loaded on the CPU. > KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS > > vmx_load_eoi_exitmap() writes EOI_EXIT_BITMAP0..3 directly with > vmcs_write64() and, unlike its siblings vmx_hwapic_isr_update() and > vmx_sync_pir_to_irr(), > does not take guard(vmx_vmcs01). The EOI-exit bitmap belongs to L1's APIC, > but with nested virtual-interrupt-delivery an L2 can be active when KVM > refreshes it (e.g. via kvm_vcpu_reload_apic_access_page() / > vcpu_scan_ioapic()), so the writes land in vmcs02 instead of vmcs01: L2's > EOI-exit bitmap is corrupted and vmcs01's is left stale until the next L1 > refresh. > > Add guard(vmx_vmcs01), matching the sibling APICv callbacks. > > Signed-off-by: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de> > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index 612ab07d4100f..ec2ea3e1d14d8 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -7139,6 +7139,13 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) > if (!kvm_vcpu_apicv_active(vcpu)) > return; > > + /* > + * The EOI-exit bitmap tracks L1's APIC, so it must land in vmcs01, not > + * whichever VMCS is currently loaded; a nested VID L2 can be active > + * here. Mirror vmx_hwapic_isr_update()/vmx_sync_pir_to_irr(). > + */ > + guard(vmx_vmcs01)(vcpu); > + > vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); > vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); > vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]); [Severity: Medium] Can vcpu_scan_ioapic() or kvm_vcpu_reload_apic_access_page() actually trigger vmx_load_eoi_exitmap() while L2 is active, as described in the commit message and comment? Looking at arch/x86/kvm/x86.c, kvm_vcpu_reload_apic_access_page() only calls set_apic_access_page_addr: static void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu) { if (!lapic_in_kernel(vcpu)) return; kvm_x86_call(set_apic_access_page_addr)(vcpu); } Meanwhile, vcpu_scan_ioapic() in arch/x86/kvm/x86.c explicitly defers KVM_REQ_LOAD_EOI_EXITMAP when the vCPU is in guest mode: if (is_guest_mode(vcpu)) vcpu->arch.load_eoi_exitmap_pending = true; else kvm_make_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu); And leave_guest_mode() in arch/x86/kvm/regs.h only raises KVM_REQ_LOAD_EOI_EXITMAP when leaving L2: if (vcpu->arch.load_eoi_exitmap_pending) { vcpu->arch.load_eoi_exitmap_pending = false; kvm_make_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu); } With load_eoi_exitmap_pending still in place, vcpu_scan_ioapic() will not invoke vmx_load_eoi_exitmap() while L2 is active (it seems vmx_load_eoi_exitmap() is only reached with is_guest_mode(vcpu) true if leave_guest_mode() raises KVM_REQ_LOAD_EOI_EXITMAP and guest mode is re-entered before vcpu_enter_guest() processes requests, such as via vmx_set_nested_state()). Now that vmx_load_eoi_exitmap() uses guard(vmx_vmcs01), should the load_eoi_exitmap_pending deferral in vcpu_scan_ioapic() and leave_guest_mode() be removed so that KVM_REQ_LOAD_EOI_EXITMAP is raised immediately while L2 is active, or should the commit message and comment be updated to reflect the actual call path? Also, both the commit message and the new comment state that this mirrors vmx_sync_pir_to_irr() taking guard(vmx_vmcs01), but vmx_sync_pir_to_irr() in arch/x86/kvm/vmx/vmx.c checks !is_guest_mode(vcpu) instead of using guard(vmx_vmcs01): if (!is_guest_mode(vcpu) && kvm_vcpu_apicv_active(vcpu)) vmx_set_rvi(max_irr); else if (max_irr_is_from_pir) kvm_make_request(KVM_REQ_EVENT, vcpu); Should the reference to vmx_sync_pir_to_irr() in the comment and commit message be adjusted as well? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261017093016.32348-2-amirmohammad.eftekhar@cispa.de?part=1 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS 2026-10-17 9:40 ` sashiko-bot @ 2026-10-17 14:46 ` Sean Christopherson 0 siblings, 0 replies; 4+ messages in thread From: Sean Christopherson @ 2026-10-17 14:46 UTC (permalink / raw) To: sashiko-reviews; +Cc: Amirmohammad Eftekhar, kvm On Sat, Oct 17, 2026, sashiko-bot@kernel.org wrote: > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: > - [Medium] KVM: VMX: vmx_load_eoi_exitmap() comment mismatch and deferred L2 update > -- > > commit b2b472dc800418ff9ed851c85722ed6e99a11a91 > Author: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de> > > KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS > > This commit adds guard(vmx_vmcs01) to vmx_load_eoi_exitmap() so that updates > to EOI_EXIT_BITMAP0..3 target vmcs01 rather than whichever VMCS happens to be > loaded on the CPU. > > > KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS > > > > vmx_load_eoi_exitmap() writes EOI_EXIT_BITMAP0..3 directly with > > vmcs_write64() and, unlike its siblings vmx_hwapic_isr_update() and > > vmx_sync_pir_to_irr(), > > does not take guard(vmx_vmcs01). The EOI-exit bitmap belongs to L1's APIC, > > but with nested virtual-interrupt-delivery an L2 can be active when KVM > > refreshes it (e.g. via kvm_vcpu_reload_apic_access_page() / > > vcpu_scan_ioapic()), so the writes land in vmcs02 instead of vmcs01: L2's > > EOI-exit bitmap is corrupted and vmcs01's is left stale until the next L1 > > refresh. > > > > Add guard(vmx_vmcs01), matching the sibling APICv callbacks. > > > > Signed-off-by: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de> > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > > index 612ab07d4100f..ec2ea3e1d14d8 100644 > > --- a/arch/x86/kvm/vmx/vmx.c > > +++ b/arch/x86/kvm/vmx/vmx.c > > @@ -7139,6 +7139,13 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) > > if (!kvm_vcpu_apicv_active(vcpu)) > > return; > > > > + /* > > + * The EOI-exit bitmap tracks L1's APIC, so it must land in vmcs01, not > > + * whichever VMCS is currently loaded; a nested VID L2 can be active > > + * here. Mirror vmx_hwapic_isr_update()/vmx_sync_pir_to_irr(). > > + */ > > + guard(vmx_vmcs01)(vcpu); > > + > > vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); > > vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); > > vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]); > > [Severity: Medium] > Can vcpu_scan_ioapic() or kvm_vcpu_reload_apic_access_page() actually trigger > vmx_load_eoi_exitmap() while L2 is active, as described in the commit message > and comment? Not in normal operation, no. Maybe if userspace does something bizarre and forces the vCPU back into L2 after the exit, but before KVM_RUN? Regardless, we should rip out the deferred update, I simply missed it when removing all the others, probably because it was buring in kvm_vcpu_arch instead of vcpu_vmx. Not yet tested... --- From: Sean Christopherson <seanjc@google.com> Date: Sat, 17 Oct 2026 07:33:11 -0700 Subject: [PATCH] KVM: x86: Switch to vmcs01 to update EOIT exiting bitmap on-demand if L2 is active If KVM needs to update the EOI bitmap while L2 is running, temporarily load vmcs01 and immediately refresh the bitmap in vmcs01 instead of deferring the update until the next nested VM-Exit. I.e. give the EOI bitmap the same treatment as the many other updates that were previously deferred. Reported-by: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de> Closes: https://lore.kernel.org/all/20261017093016.32348-2-amirmohammad.eftekhar@cispa.de Signed-off-by: Sean Christopherson <seanjc@google.com> --- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/regs.h | 6 ------ arch/x86/kvm/vmx/vmx.c | 2 ++ arch/x86/kvm/x86.c | 13 ------------- 4 files changed, 3 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index e2eef7057bd3..9583bde5c848 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -108,7 +108,7 @@ #define KVM_REQ_HV_RESET KVM_ARCH_REQ(20) #define KVM_REQ_HV_EXIT KVM_ARCH_REQ(21) #define KVM_REQ_HV_STIMER KVM_ARCH_REQ(22) -#define KVM_REQ_LOAD_EOI_EXITMAP KVM_ARCH_REQ(23) +/*#define FREE!!! USE ME!!! KVM_ARCH_REQ(23) */ #define KVM_REQ_GET_NESTED_STATE_PAGES KVM_ARCH_REQ(24) #define KVM_REQ_APICV_UPDATE \ KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h index 97c17b120a57..04d047f46753 100644 --- a/arch/x86/kvm/regs.h +++ b/arch/x86/kvm/regs.h @@ -463,12 +463,6 @@ static inline void enter_guest_mode(struct kvm_vcpu *vcpu) static inline void leave_guest_mode(struct kvm_vcpu *vcpu) { vcpu->arch.hflags &= ~HF_GUEST_MASK; - - if (vcpu->arch.load_eoi_exitmap_pending) { - vcpu->arch.load_eoi_exitmap_pending = false; - kvm_make_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu); - } - vcpu->stat.guest_mode = 0; } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index b341af4c6057..59b48d959ee0 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7082,6 +7082,8 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) if (!kvm_vcpu_apicv_active(vcpu)) return; + guard(vmx_vmcs01)(vcpu); + vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 32563a91fba9..0028d57e964a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8062,17 +8062,6 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu) kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors); #endif - if (is_guest_mode(vcpu)) - vcpu->arch.load_eoi_exitmap_pending = true; - else - kvm_make_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu); -} - -static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu) -{ - if (!kvm_apic_hw_enabled(vcpu->arch.apic)) - return; - #ifdef CONFIG_KVM_HYPERV if (to_hv_vcpu(vcpu)) { u64 eoi_exit_bitmap[4]; @@ -8240,8 +8229,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) } if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu)) vcpu_scan_ioapic(vcpu); - if (kvm_check_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu)) - vcpu_load_eoi_exitmap(vcpu); if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu)) kvm_vcpu_reload_apic_access_page(vcpu); #ifdef CONFIG_KVM_HYPERV base-commit: dea4f6380f4ec96e8f3b0aaf2343764bd0d25ef4 -- ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS 2026-10-17 9:30 [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS Amirmohammad Eftekhar 2026-10-17 9:40 ` sashiko-bot @ 2026-10-17 16:33 ` Amirmohammad Eftekhar 1 sibling, 0 replies; 4+ messages in thread From: Amirmohammad Eftekhar @ 2026-10-17 16:33 UTC (permalink / raw) To: seanjc; +Cc: kvm, linux-kernel, pbonzini, sashiko-reviews Thanks, and agreed on all of it. You're right that it isn't reachable in normal operation. The deferral (load_eoi_exitmap_pending) is what kept it off the L2 path, and ripping that out reads cleaner than adding the guard alone, so your version is the better fix. My changelog was wrong about the trigger and about vmx_sync_pir_to_irr(); sorry for the noise there. Thanks for the Reported-by. Would you like me to test your version (nested VID with APICv active, deferral removed) before it goes in? Thanks, Amirmohammad ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-17 16:33 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-17 9:30 [PATCH] KVM: VMX: Load the EOI-exit bitmap into vmcs01, not the active VMCS Amirmohammad Eftekhar 2026-10-17 9:40 ` sashiko-bot 2026-10-17 14:46 ` Sean Christopherson 2026-10-17 16:33 ` Amirmohammad Eftekhar
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.