]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: vgic-v2: Force vgic init on injection outside the run loop
authorMarc Zyngier <maz@kernel.org>
Wed, 20 May 2026 10:01:59 +0000 (11:01 +0100)
committerMarc Zyngier <maz@kernel.org>
Thu, 21 May 2026 07:08:49 +0000 (08:08 +0100)
Make sure that any attempt to inject an interrupt from userspace
or an irqfd results in the GICv2 lazy init to take place.

This is not currently necessary as the init is also performed on
*any* interrupt injection. But as we're about to remove that,
let's introduce it here.

Reviewed-by: Oliver Upton <oupton@kernel.org>
Link: https://patch.msgid.link/20260520100200.543845-6-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/arm.c
arch/arm64/kvm/vgic/vgic-irqfd.c

index 6e6dc17f8b606af22086c11ee8d16c86b097f245..cfb7921fc7d75f5bdfa4b0c39ccce7349f2d5ccb 100644 (file)
@@ -51,6 +51,7 @@
 
 #include <linux/irqchip/arm-gic-v5.h>
 
+#include "vgic/vgic.h"
 #include "sys_regs.h"
 
 static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
@@ -1497,8 +1498,13 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
 
                return vcpu_interrupt_line(vcpu, irq_num, level);
        case KVM_ARM_IRQ_TYPE_PPI:
-               if (!irqchip_in_kernel(kvm))
+               if (irqchip_in_kernel(kvm)) {
+                       int ret = vgic_lazy_init(kvm);
+                       if (ret)
+                               return ret;
+               } else {
                        return -ENXIO;
+               }
 
                vcpu = kvm_get_vcpu_by_id(kvm, vcpu_id);
                if (!vcpu)
@@ -1525,8 +1531,13 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
 
                return kvm_vgic_inject_irq(kvm, vcpu, irq_num, level, NULL);
        case KVM_ARM_IRQ_TYPE_SPI:
-               if (!irqchip_in_kernel(kvm))
+               if (irqchip_in_kernel(kvm)) {
+                       int ret = vgic_lazy_init(kvm);
+                       if (ret)
+                               return ret;
+               } else {
                        return -ENXIO;
+               }
 
                if (vgic_is_v5(kvm)) {
                        /* Build a GICv5-style IntID here */
index b9b86e3a6c8625b2b55a70834f293d8d679ee2cd..19a1094536e6a8d709ebb095295774f3a43fc554 100644 (file)
@@ -20,9 +20,15 @@ static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
                        int level, bool line_status)
 {
        unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
+       int ret;
 
        if (!vgic_valid_spi(kvm, spi_id))
                return -EINVAL;
+
+       ret = vgic_lazy_init(kvm);
+       if (ret)
+               return ret;
+
        return kvm_vgic_inject_irq(kvm, NULL, spi_id, level, NULL);
 }