* [RFC PATCH] KVM: arm64: Set irqfd->producer to enable vLPI routing updates
[not found] <20260622075103.35164-1-leixiang@kylinos.cn>
@ 2026-06-23 8:14 ` leixiang
2026-06-23 9:52 ` Marc Zyngier
0 siblings, 1 reply; 2+ messages in thread
From: leixiang @ 2026-06-23 8:14 UTC (permalink / raw)
To: maz
Cc: oupton, seanjc, pbonzini, kvmarm, kvm, linux-arm-kernel,
linux-kernel, leixiang
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@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
^ permalink raw reply related [flat|nested] 2+ messages in thread