Skip to content

Commit 0a4aedf

Browse files
committed
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 3a08a6c commit 0a4aedf

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

arch/arm64/kvm/vgic/vgic.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,32 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
114114
return vgic_get_irq(vcpu->kvm, intid);
115115
}
116116

117+
static void vgic_release_lpi_locked(struct vgic_dist *dist, struct vgic_irq *irq)
118+
{
119+
lockdep_assert_held(&dist->lpi_xa.xa_lock);
120+
__xa_erase(&dist->lpi_xa, irq->intid);
121+
kfree_rcu(irq, rcu);
122+
}
123+
124+
static __must_check bool __vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
125+
{
126+
if (irq->intid < VGIC_MIN_LPI)
127+
return false;
128+
129+
return refcount_dec_and_test(&irq->refcount);
130+
}
131+
117132
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
118133
{
119134
struct vgic_dist *dist = &kvm->arch.vgic;
120135
unsigned long flags;
121136

122-
if (irq->intid < VGIC_MIN_LPI)
123-
return;
124-
125-
if (!refcount_dec_and_test(&irq->refcount))
137+
if (!__vgic_put_irq(kvm, irq))
126138
return;
127139

128140
xa_lock_irqsave(&dist->lpi_xa, flags);
129-
__xa_erase(&dist->lpi_xa, irq->intid);
141+
vgic_release_lpi_locked(dist, irq);
130142
xa_unlock_irqrestore(&dist->lpi_xa, flags);
131-
132-
kfree_rcu(irq, rcu);
133143
}
134144

135145
void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)

0 commit comments

Comments
 (0)