[RFC PATCH] KVM: arm64: Set irqfd->producer to enable vLPI routing updates

leixiang leixiang at kylinos.cn
Tue Jun 23 01:14:33 PDT 2026


ARM64's kvm_arch_irq_bypass_add_producer() never sets irqfd->producer,
so kvm_irq_routing_update() never calls the ARM64 routing hook.  That
hook unmaps the vLPI and falls back to software injection when an
irqfd's MSI routing changes; with it dead, the vLPI stays bound to the
old translation.

Set irqfd->producer once kvm_vgic_v4_set_forwarding() succeeds and
clear it in del_producer(), under irqfds.lock; the only reader,
kvm_irq_routing_update(), takes that lock.  set_forwarding() may sleep,
so it runs outside the lock and the pointer is published only on
success, needing no error cleanup.

Sent as RFC: the unmap-on-reroute path has been dormant.

Fixes: 2412405b3141 ("KVM: arm/arm64: register irq bypass consumer on ARM/ARM64")
Signed-off-by: leixiang <leixiang at kylinos.cn>
---
A review of the x86/powerpc producer-nullify patch pointed out that
ARM64 never sets irqfd->producer, so kvm_arch_update_irqfd_routing()
is dead.  This RFC fills that gap; set_forwarding() may sleep and so
can't run under irqfds.lock like the x86 path, hence the locking is
what I'd most like reviewed.

 arch/arm64/kvm/arm.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 50adfff75be8..6f1e4f526719 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -2935,6 +2935,7 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 	struct kvm_kernel_irq_routing_entry *irq_entry = &irqfd->irq_entry;
+	int ret;

 	/*
 	 * The only thing we have a chance of directly-injecting is LPIs. Maybe
@@ -2943,8 +2944,16 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
 	if (irq_entry->type != KVM_IRQ_ROUTING_MSI)
 		return 0;

-	return kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
-					  &irqfd->irq_entry);
+	ret = kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
+					 &irqfd->irq_entry);
+	if (ret)
+		return ret;
+
+	spin_lock_irq(&irqfd->kvm->irqfds.lock);
+	irqfd->producer = prod;
+	spin_unlock_irq(&irqfd->kvm->irqfds.lock);
+
+	return 0;
 }

 void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
@@ -2957,6 +2966,10 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
 	if (irq_entry->type != KVM_IRQ_ROUTING_MSI)
 		return;

+	spin_lock_irq(&irqfd->kvm->irqfds.lock);
+	irqfd->producer = NULL;
+	spin_unlock_irq(&irqfd->kvm->irqfds.lock);
+
 	kvm_vgic_v4_unset_forwarding(irqfd->kvm, prod->irq);
 }

--
2.45.0



More information about the linux-arm-kernel mailing list