]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: vgic-v4: Fall back to software irqbypass if LPI not found
authorOliver Upton <oliver.upton@linux.dev>
Wed, 26 Feb 2025 18:31:23 +0000 (10:31 -0800)
committerOliver Upton <oliver.upton@linux.dev>
Wed, 26 Feb 2025 21:22:49 +0000 (13:22 -0800)
Continuing with the theme of broken VMMs and guests, irqbypass
registration can fail if the virtual ITS lacks a translation for the
MSI. Either the guest hasn't mapped it or userspace may have forgotten
to restore the ITS.

Exit silently and allow irqbypass configuration to succeed. As a reward
for ingenuity, LPIs are demoted to software injection.

Tested-by: Sudheer Dantuluri <dantuluris@google.com>
Fixes: 196b136498b3 ("KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass")
Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250226183124.82094-4-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/vgic/vgic-v4.c

index 3e1de40720e0a7aab5b42ab813fea63b18e5de0e..9f51d58b5f8a437bf8b9be8e1c4254da862de8a9 100644 (file)
@@ -415,7 +415,7 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
        struct vgic_irq *irq;
        struct its_vlpi_map map;
        unsigned long flags;
-       int ret;
+       int ret = 0;
 
        if (!vgic_supports_direct_msis(kvm))
                return 0;
@@ -430,10 +430,15 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
 
        mutex_lock(&its->its_lock);
 
-       /* Perform the actual DevID/EventID -> LPI translation. */
-       ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
-                                  irq_entry->msi.data, &irq);
-       if (ret)
+       /*
+        * Perform the actual DevID/EventID -> LPI translation.
+        *
+        * Silently exit if translation fails as the guest (or userspace!) has
+        * managed to do something stupid. Emulated LPI injection will still
+        * work if the guest figures itself out at a later time.
+        */
+       if (vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
+                                irq_entry->msi.data, &irq))
                goto out;
 
        /* Silently exit if the vLPI is already mapped */