]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: x86: Add a helper to deduplicate I/O APIC EOI interception logic
authorSean Christopherson <seanjc@google.com>
Tue, 4 Mar 2025 01:33:34 +0000 (17:33 -0800)
committerSean Christopherson <seanjc@google.com>
Thu, 24 Apr 2025 18:18:36 +0000 (11:18 -0700)
Extract the vCPU specific EOI interception logic for I/O APIC emulation
into a common helper for userspace and in-kernel emulation in anticipation
of optimizing the "pending EOI" case.

No functional change intended.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Link: https://lore.kernel.org/r/20250304013335.4155703-3-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/ioapic.c
arch/x86/kvm/ioapic.h
arch/x86/kvm/irq_comm.c

index 995eb50543601f70f8162ef1dfc2a79f6d21d032..45dae2d5d2f1f6ed025ee7e7f2db9d8adc5634e1 100644 (file)
@@ -296,11 +296,8 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, ulong *ioapic_handled_vectors)
                    index == RTC_GSI) {
                        u16 dm = kvm_lapic_irq_dest_mode(!!e->fields.dest_mode);
 
-                       if (kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
-                                               e->fields.dest_id, dm) ||
-                           kvm_apic_pending_eoi(vcpu, e->fields.vector))
-                               __set_bit(e->fields.vector,
-                                         ioapic_handled_vectors);
+                       kvm_scan_ioapic_irq(vcpu, e->fields.dest_id, dm,
+                                           e->fields.vector, ioapic_handled_vectors);
                }
        }
        spin_unlock(&ioapic->lock);
index 539333ac4b38082f01e0407908441aa39b9ca136..aa8cb4ac0479809de8b3a7e99dd5de845bf9d6c4 100644 (file)
@@ -120,4 +120,6 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu,
                           ulong *ioapic_handled_vectors);
 void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
                            ulong *ioapic_handled_vectors);
+void kvm_scan_ioapic_irq(struct kvm_vcpu *vcpu, u32 dest_id, u16 dest_mode,
+                        u8 vector, unsigned long *ioapic_handled_vectors);
 #endif
index 866f84392797ba21ca5c81cc98e7da48f3986539..14590d9c4a3715ee7a25a7ad6d649ca56f45b7f5 100644 (file)
@@ -402,6 +402,21 @@ void kvm_arch_post_irq_routing_update(struct kvm *kvm)
        kvm_make_scan_ioapic_request(kvm);
 }
 
+void kvm_scan_ioapic_irq(struct kvm_vcpu *vcpu, u32 dest_id, u16 dest_mode,
+                        u8 vector, unsigned long *ioapic_handled_vectors)
+{
+       /*
+        * Intercept EOI if the vCPU is the target of the new IRQ routing, or
+        * the vCPU has a pending IRQ from the old routing, i.e. if the vCPU
+        * may receive a level-triggered IRQ in the future, or already received
+        * level-triggered IRQ.  The EOI needs to be intercepted and forwarded
+        * to I/O APIC emulation so that the IRQ can be de-asserted.
+        */
+       if (kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT, dest_id, dest_mode) ||
+           kvm_apic_pending_eoi(vcpu, vector))
+               __set_bit(vector, ioapic_handled_vectors);
+}
+
 void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
                            ulong *ioapic_handled_vectors)
 {
@@ -427,10 +442,8 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
                        if (!irq.trig_mode)
                                continue;
 
-                       if (kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
-                                               irq.dest_id, irq.dest_mode) ||
-                            kvm_apic_pending_eoi(vcpu, irq.vector))
-                               __set_bit(irq.vector, ioapic_handled_vectors);
+                       kvm_scan_ioapic_irq(vcpu, irq.dest_id, irq.dest_mode,
+                                           irq.vector, ioapic_handled_vectors);
                }
        }
        srcu_read_unlock(&kvm->irq_srcu, idx);