KVM tracks End-of-Interrupts (EOIs) for the legacy RTC interrupt (GSI 8) to detect and report coalesced interrupts to userspace. This mechanism fundamentally relies on KVM having visibility into the guest's interrupt acknowledgment state. This assumption is invalid for guests with a protected APIC (e.g., Secure AVIC) for two main reasons: a. The guest's true In-Service Register (ISR) is not visible to KVM, making it impossible to know if the previous interrupt is still active. So, lazy pending EOI checks cannot be done. b. The RTC interrupt is edge-triggered, and its EOI is accelerated by the hardware without a VM-Exit. KVM never sees the EOI event. Since KVM can observe neither the interrupt's service status nor its EOI, the tracking logic is invalid. So, disable this feature for all protected APIC guests. This change means that userspace will no longer be able to detect coalesced RTC interrupts for these specific guest types. Signed-off-by: Neeraj Upadhyay --- arch/x86/kvm/ioapic.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 2b5d389bca5f..308778ba4f58 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -113,6 +113,9 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu) struct dest_map *dest_map = &ioapic->rtc_status.dest_map; union kvm_ioapic_redirect_entry *e; + if (vcpu->arch.apic->guest_apic_protected) + return; + e = &ioapic->redirtbl[RTC_GSI]; if (!kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT, e->fields.dest_id, @@ -476,6 +479,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status) { union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; struct kvm_lapic_irq irqe; + struct kvm_vcpu *vcpu; int ret; if (entry->fields.mask || @@ -505,7 +509,9 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status) BUG_ON(ioapic->rtc_status.pending_eoi != 0); ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, &ioapic->rtc_status.dest_map); - ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret); + vcpu = kvm_get_vcpu(ioapic->kvm, 0); + if (!vcpu->arch.apic->guest_apic_protected) + ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret); } else ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL); -- 2.34.1