]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: x86: Move IRQ mask notifier infrastructure to I/O APIC emulation
authorSean Christopherson <seanjc@google.com>
Wed, 11 Jun 2025 21:35:56 +0000 (14:35 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 20 Jun 2025 20:52:52 +0000 (13:52 -0700)
Move the IRQ mask logic to ioapic.c as KVM's only user is its in-kernel
I/O APIC emulation.  In addition to encapsulating more I/O APIC specific
code, trimming down irq_comm.c helps pave the way for removing it entirely.

Acked-by: Kai Huang <kai.huang@intel.com>
Link: https://lore.kernel.org/r/20250611213557.294358-18-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/i8254.h
arch/x86/kvm/i8259.c
arch/x86/kvm/ioapic.c
arch/x86/kvm/ioapic.h
arch/x86/kvm/irq_comm.c
arch/x86/kvm/x86.c

index 8d511eb039337c1ea061498c3439abd04df1e339..44fd9ccc06248fe7c0fd46b24fa88c52f358c8c3 100644 (file)
@@ -1427,9 +1427,6 @@ struct kvm_arch {
        struct delayed_work kvmclock_update_work;
        struct delayed_work kvmclock_sync_work;
 
-       /* reads protected by irq_srcu, writes by irq_lock */
-       struct hlist_head mask_notifier_list;
-
 #ifdef CONFIG_KVM_HYPERV
        struct kvm_hv hyperv;
 #endif
@@ -2039,19 +2036,6 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
 int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
                          const void *val, int bytes);
 
-struct kvm_irq_mask_notifier {
-       void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked);
-       int irq;
-       struct hlist_node link;
-};
-
-void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
-                                   struct kvm_irq_mask_notifier *kimn);
-void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
-                                     struct kvm_irq_mask_notifier *kimn);
-void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
-                            bool mask);
-
 extern bool tdp_enabled;
 
 u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
index e8bd59ad8a7c446007b66db2dcf36dd57518f4a7..60fa499d2f8aa00699c8cc30dac0ac85b2cefdb9 100644 (file)
@@ -8,6 +8,8 @@
 
 #include <uapi/asm/kvm.h>
 
+#include "ioapic.h"
+
 #ifdef CONFIG_KVM_IOAPIC
 struct kvm_kpit_channel_state {
        u32 count; /* can be 65536 */
index 4de055efc4eec87886c74e20df2c2a212a2079cc..2ac7f1678c462b82b21e82f8662290b5bcc963c3 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
+
+#include "ioapic.h"
 #include "irq.h"
 
 #include <linux/kvm_host.h>
index fa7481814bc6c827baed8f44c196680b8af282bb..2b5d389bca5f18fb856d74f563231a54027d6b1e 100644 (file)
@@ -310,6 +310,42 @@ void kvm_arch_post_irq_ack_notifier_list_update(struct kvm *kvm)
        kvm_make_scan_ioapic_request(kvm);
 }
 
+void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
+                                   struct kvm_irq_mask_notifier *kimn)
+{
+       struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+
+       mutex_lock(&kvm->irq_lock);
+       kimn->irq = irq;
+       hlist_add_head_rcu(&kimn->link, &ioapic->mask_notifier_list);
+       mutex_unlock(&kvm->irq_lock);
+}
+
+void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
+                                     struct kvm_irq_mask_notifier *kimn)
+{
+       mutex_lock(&kvm->irq_lock);
+       hlist_del_rcu(&kimn->link);
+       mutex_unlock(&kvm->irq_lock);
+       synchronize_srcu(&kvm->irq_srcu);
+}
+
+void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
+                            bool mask)
+{
+       struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+       struct kvm_irq_mask_notifier *kimn;
+       int idx, gsi;
+
+       idx = srcu_read_lock(&kvm->irq_srcu);
+       gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
+       if (gsi != -1)
+               hlist_for_each_entry_rcu(kimn, &ioapic->mask_notifier_list, link)
+                       if (kimn->irq == gsi)
+                               kimn->func(kimn, mask);
+       srcu_read_unlock(&kvm->irq_srcu, idx);
+}
+
 static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 {
        unsigned index;
@@ -710,6 +746,7 @@ int kvm_ioapic_init(struct kvm *kvm)
                return -ENOMEM;
        spin_lock_init(&ioapic->lock);
        INIT_DELAYED_WORK(&ioapic->eoi_inject, kvm_ioapic_eoi_inject_work);
+       INIT_HLIST_HEAD(&ioapic->mask_notifier_list);
        kvm->arch.vioapic = ioapic;
        kvm_ioapic_reset(ioapic);
        kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops);
index dc92bd7c37bc43ce3acc65cabeec752b12987dac..bf28dbc11ff68db4900d52a6a645279cadb806cc 100644 (file)
@@ -86,8 +86,24 @@ struct kvm_ioapic {
        struct delayed_work eoi_inject;
        u32 irq_eoi[IOAPIC_NUM_PINS];
        u32 irr_delivered;
+
+       /* reads protected by irq_srcu, writes by irq_lock */
+       struct hlist_head mask_notifier_list;
+};
+
+struct kvm_irq_mask_notifier {
+       void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked);
+       int irq;
+       struct hlist_node link;
 };
 
+void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
+                                   struct kvm_irq_mask_notifier *kimn);
+void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
+                                     struct kvm_irq_mask_notifier *kimn);
+void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
+                            bool mask);
+
 #ifdef DEBUG
 #define ASSERT(x)                                                      \
 do {                                                                   \
index 14fc8db0206c1a01d75bef7c25f077e5eaf3c0aa..76d1c85a1011f84eeff471bba14c69adeadb6cb9 100644 (file)
@@ -161,39 +161,6 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
        return -EWOULDBLOCK;
 }
 
-void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
-                                   struct kvm_irq_mask_notifier *kimn)
-{
-       mutex_lock(&kvm->irq_lock);
-       kimn->irq = irq;
-       hlist_add_head_rcu(&kimn->link, &kvm->arch.mask_notifier_list);
-       mutex_unlock(&kvm->irq_lock);
-}
-
-void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
-                                     struct kvm_irq_mask_notifier *kimn)
-{
-       mutex_lock(&kvm->irq_lock);
-       hlist_del_rcu(&kimn->link);
-       mutex_unlock(&kvm->irq_lock);
-       synchronize_srcu(&kvm->irq_srcu);
-}
-
-void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
-                            bool mask)
-{
-       struct kvm_irq_mask_notifier *kimn;
-       int idx, gsi;
-
-       idx = srcu_read_lock(&kvm->irq_srcu);
-       gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
-       if (gsi != -1)
-               hlist_for_each_entry_rcu(kimn, &kvm->arch.mask_notifier_list, link)
-                       if (kimn->irq == gsi)
-                               kimn->func(kimn, mask);
-       srcu_read_unlock(&kvm->irq_srcu, idx);
-}
-
 bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
 {
        return irqchip_in_kernel(kvm);
index 78dfa6c1cb01254fa6a2a22a53be646833889c81..02237dbb7f322e8d0be8f6396504e7ff2981f34d 100644 (file)
@@ -12676,7 +12676,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        if (ret)
                goto out_uninit_mmu;
 
-       INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list);
        atomic_set(&kvm->arch.noncoherent_dma_count, 0);
 
        raw_spin_lock_init(&kvm->arch.tsc_write_lock);