]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: x86: Move IRQ routing/delivery APIs from x86.c => irq.c
authorSean Christopherson <seanjc@google.com>
Wed, 11 Jun 2025 22:45:29 +0000 (15:45 -0700)
committerSean Christopherson <seanjc@google.com>
Mon, 23 Jun 2025 16:50:28 +0000 (09:50 -0700)
Move a bunch of IRQ routing and delivery APIs from x86.c to irq.c.  x86.c
has grown quite fat, and irq.c is the perfect landing spot.

Opportunistically rewrite kvm_arch_irq_bypass_del_producer()'s comment, as
the existing comment has several typos and is rather confusing.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20250611224604.313496-28-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/irq.c
arch/x86/kvm/x86.c

index a0b1499baf6e503de1a238e68ace1ba9d4367138..f34c2deedf78202955926a848ee258536076017f 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/export.h>
 #include <linux/kvm_host.h>
+#include <linux/kvm_irqfd.h>
 
 #include "hyperv.h"
 #include "ioapic.h"
@@ -332,6 +333,18 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
        return -EWOULDBLOCK;
 }
 
+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event,
+                       bool line_status)
+{
+       if (!irqchip_in_kernel(kvm))
+               return -ENXIO;
+
+       irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
+                                       irq_event->irq, irq_event->level,
+                                       line_status);
+       return 0;
+}
+
 bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
 {
        return irqchip_in_kernel(kvm);
@@ -495,6 +508,81 @@ void kvm_arch_irq_routing_update(struct kvm *kvm)
                kvm_make_scan_ioapic_request(kvm);
 }
 
+int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
+                                     struct irq_bypass_producer *prod)
+{
+       struct kvm_kernel_irqfd *irqfd =
+               container_of(cons, struct kvm_kernel_irqfd, consumer);
+       struct kvm *kvm = irqfd->kvm;
+       int ret = 0;
+
+       kvm_arch_start_assignment(irqfd->kvm);
+
+       spin_lock_irq(&kvm->irqfds.lock);
+       irqfd->producer = prod;
+
+       if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
+               ret = kvm_x86_call(pi_update_irte)(irqfd, irqfd->kvm, prod->irq,
+                                                  irqfd->gsi, &irqfd->irq_entry);
+               if (ret)
+                       kvm_arch_end_assignment(irqfd->kvm);
+       }
+       spin_unlock_irq(&kvm->irqfds.lock);
+
+       return ret;
+}
+
+void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
+                                     struct irq_bypass_producer *prod)
+{
+       struct kvm_kernel_irqfd *irqfd =
+               container_of(cons, struct kvm_kernel_irqfd, consumer);
+       struct kvm *kvm = irqfd->kvm;
+       int ret;
+
+       WARN_ON(irqfd->producer != prod);
+
+       /*
+        * If the producer of an IRQ that is currently being posted to a vCPU
+        * is unregistered, change the associated IRTE back to remapped mode as
+        * the IRQ has been released (or repurposed) by the device driver, i.e.
+        * KVM must relinquish control of the IRTE.
+        */
+       spin_lock_irq(&kvm->irqfds.lock);
+       irqfd->producer = NULL;
+
+       if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
+               ret = kvm_x86_call(pi_update_irte)(irqfd, irqfd->kvm, prod->irq,
+                                                  irqfd->gsi, NULL);
+               if (ret)
+                       pr_info("irq bypass consumer (eventfd %p) unregistration fails: %d\n",
+                               irqfd->consumer.eventfd, ret);
+       }
+
+       spin_unlock_irq(&kvm->irqfds.lock);
+
+
+       kvm_arch_end_assignment(irqfd->kvm);
+}
+
+int kvm_arch_update_irqfd_routing(struct kvm_kernel_irqfd *irqfd,
+                                 struct kvm_kernel_irq_routing_entry *old,
+                                 struct kvm_kernel_irq_routing_entry *new)
+{
+       return kvm_x86_call(pi_update_irte)(irqfd, irqfd->kvm, irqfd->producer->irq,
+                                           irqfd->gsi, new);
+}
+
+bool kvm_arch_irqfd_route_changed(struct kvm_kernel_irq_routing_entry *old,
+                                 struct kvm_kernel_irq_routing_entry *new)
+{
+       if (old->type != KVM_IRQ_ROUTING_MSI ||
+           new->type != KVM_IRQ_ROUTING_MSI)
+               return true;
+
+       return !!memcmp(&old->msi, &new->msi, sizeof(new->msi));
+}
+
 #ifdef CONFIG_KVM_IOAPIC
 #define IOAPIC_ROUTING_ENTRY(irq) \
        { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP,  \
index c176ff44bb9a0d4205c60840688d66b1229e11de..7091d7d7eebdcb16b839b9765a7aff5093eb3316 100644 (file)
@@ -6420,18 +6420,6 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
                kvm_vcpu_kick(vcpu);
 }
 
-int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event,
-                       bool line_status)
-{
-       if (!irqchip_in_kernel(kvm))
-               return -ENXIO;
-
-       irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
-                                       irq_event->irq, irq_event->level,
-                                       line_status);
-       return 0;
-}
-
 int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
                            struct kvm_enable_cap *cap)
 {
@@ -13504,81 +13492,6 @@ bool kvm_arch_has_noncoherent_dma(struct kvm *kvm)
 }
 EXPORT_SYMBOL_GPL(kvm_arch_has_noncoherent_dma);
 
-int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
-                                     struct irq_bypass_producer *prod)
-{
-       struct kvm_kernel_irqfd *irqfd =
-               container_of(cons, struct kvm_kernel_irqfd, consumer);
-       struct kvm *kvm = irqfd->kvm;
-       int ret = 0;
-
-       kvm_arch_start_assignment(irqfd->kvm);
-
-       spin_lock_irq(&kvm->irqfds.lock);
-       irqfd->producer = prod;
-
-       if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
-               ret = kvm_x86_call(pi_update_irte)(irqfd, irqfd->kvm, prod->irq,
-                                                  irqfd->gsi, &irqfd->irq_entry);
-               if (ret)
-                       kvm_arch_end_assignment(irqfd->kvm);
-       }
-       spin_unlock_irq(&kvm->irqfds.lock);
-
-       return ret;
-}
-
-void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
-                                     struct irq_bypass_producer *prod)
-{
-       struct kvm_kernel_irqfd *irqfd =
-               container_of(cons, struct kvm_kernel_irqfd, consumer);
-       struct kvm *kvm = irqfd->kvm;
-       int ret;
-
-       WARN_ON(irqfd->producer != prod);
-
-       /*
-        * When producer of consumer is unregistered, we change back to
-        * remapped mode, so we can re-use the current implementation
-        * when the irq is masked/disabled or the consumer side (KVM
-        * int this case doesn't want to receive the interrupts.
-       */
-       spin_lock_irq(&kvm->irqfds.lock);
-       irqfd->producer = NULL;
-
-       if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
-               ret = kvm_x86_call(pi_update_irte)(irqfd, irqfd->kvm, prod->irq,
-                                                  irqfd->gsi, NULL);
-               if (ret)
-                       pr_info("irq bypass consumer (eventfd %p) unregistration fails: %d\n",
-                               irqfd->consumer.eventfd, ret);
-       }
-
-       spin_unlock_irq(&kvm->irqfds.lock);
-
-
-       kvm_arch_end_assignment(irqfd->kvm);
-}
-
-int kvm_arch_update_irqfd_routing(struct kvm_kernel_irqfd *irqfd,
-                                 struct kvm_kernel_irq_routing_entry *old,
-                                 struct kvm_kernel_irq_routing_entry *new)
-{
-       return kvm_x86_call(pi_update_irte)(irqfd, irqfd->kvm, irqfd->producer->irq,
-                                           irqfd->gsi, new);
-}
-
-bool kvm_arch_irqfd_route_changed(struct kvm_kernel_irq_routing_entry *old,
-                                 struct kvm_kernel_irq_routing_entry *new)
-{
-       if (old->type != KVM_IRQ_ROUTING_MSI ||
-           new->type != KVM_IRQ_ROUTING_MSI)
-               return true;
-
-       return !!memcmp(&old->msi, &new->msi, sizeof(new->msi));
-}
-
 bool kvm_vector_hashing_enabled(void)
 {
        return vector_hashing;