Re: [PATCH v5 1/3] KVM: x86: Refactor suppress EOI broadcast logic
From: Sean Christopherson
Date: Tue Jan 13 2026 - 18:11:03 EST
On Mon, Dec 29, 2025, Khushit Shah wrote:
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 0ae7f913d782..2c24fd8d815f 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -105,6 +105,39 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
> apic_test_vector(vector, apic->regs + APIC_IRR);
> }
>
> +bool kvm_lapic_advertise_suppress_eoi_broadcast(struct kvm *kvm)
This can be static, its only caller is kvm_apic_set_version().
> +{
> + /*
> + * The default in-kernel I/O APIC emulates the 82093AA and does not
> + * implement an EOI register. Some guests (e.g. Windows with the
> + * Hyper-V role enabled) disable LAPIC EOI broadcast without checking
> + * the I/O APIC version, which can cause level-triggered interrupts to
> + * never be EOI'd.
> + *
> + * To avoid this, KVM must not advertise Suppress EOI Broadcast support
> + * when using the default in-kernel I/O APIC.
> + *
> + * Historically, in split IRQCHIP mode, KVM always advertised Suppress
> + * EOI Broadcast support but did not actually suppress EOIs, resulting
> + * in quirky behavior.
> + */
> + return !ioapic_in_kernel(kvm);
> +}
> +
> +bool kvm_lapic_respect_suppress_eoi_broadcast(struct kvm *kvm)
I don't see any point in forcing every caller to check SPIV *and* this helper.
Just do:
bool kvm_lapic_suppress_eoi_broadcast(struct kvm_lapic *apic)
{
struct kvm *kvm = apic->vcpu->kvm;
if (!(kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI))
return false;
switch (kvm->arch.suppress_eoi_broadcast_mode) {
...
}
}
And then callers are much more readable, e.g. (spoiler alert if you haven't read
my other mail, which I haven't sent yet):
if (trigger_mode != IOAPIC_LEVEL_TRIG ||
kvm_lapic_suppress_eoi_broadcast(apic))
return;
and
/* Request a KVM exit to inform the userspace IOAPIC. */
if (irqchip_split(apic->vcpu->kvm)) {
/*
* Don't exit to userspace if the guest has enabled Directed
* EOI, a.k.a. Suppress EOI Broadcasts, in which case the local
* APIC doesn't broadcast EOIs (the guest must EOI the target
* I/O APIC(s) directly).
*/
if (kvm_lapic_suppress_eoi_broadcast(apic))
return;
apic->vcpu->arch.pending_ioapic_eoi = vector;
kvm_make_request(KVM_REQ_IOAPIC_EOI_EXIT, apic->vcpu);
return;
}