diff options
author | Oliver Upton <oliver.upton@linux.dev> | 2025-09-05 03:05:28 -0700 |
---|---|---|
committer | Oliver Upton <oliver.upton@linux.dev> | 2025-09-10 02:56:20 -0700 |
commit | 0a4aedf2bd3031ce83eb31f2cec8905938082b24 (patch) | |
tree | 341ebd219176a403cdd148b30f2a621f7aef9903 | |
parent | 3a08a6ca7c373198c84e2a8c025c395ee966ff8a (diff) |
KVM: arm64: Spin off release helper from vgic_put_irq()
Spin off the release implementation from vgic_put_irq() to prepare for a
more involved fix for lock ordering such that it may be unnested from
raw spinlocks. This has the minor functional change of doing call_rcu()
behind the xa_lock although it shouldn't be consequential.
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250905100531.282980-4-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
-rw-r--r-- | arch/arm64/kvm/vgic/vgic.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c index a1d6fab895c4..ec4d70936a5b 100644 --- a/arch/arm64/kvm/vgic/vgic.c +++ b/arch/arm64/kvm/vgic/vgic.c @@ -114,22 +114,32 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid) return vgic_get_irq(vcpu->kvm, intid); } +static void vgic_release_lpi_locked(struct vgic_dist *dist, struct vgic_irq *irq) +{ + lockdep_assert_held(&dist->lpi_xa.xa_lock); + __xa_erase(&dist->lpi_xa, irq->intid); + kfree_rcu(irq, rcu); +} + +static __must_check bool __vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) +{ + if (irq->intid < VGIC_MIN_LPI) + return false; + + return refcount_dec_and_test(&irq->refcount); +} + void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) { struct vgic_dist *dist = &kvm->arch.vgic; unsigned long flags; - if (irq->intid < VGIC_MIN_LPI) - return; - - if (!refcount_dec_and_test(&irq->refcount)) + if (!__vgic_put_irq(kvm, irq)) return; xa_lock_irqsave(&dist->lpi_xa, flags); - __xa_erase(&dist->lpi_xa, irq->intid); + vgic_release_lpi_locked(dist, irq); xa_unlock_irqrestore(&dist->lpi_xa, flags); - - kfree_rcu(irq, rcu); } void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu) |