Skip to content

Commit e27f2d5

Browse files
committed
KVM: arm64: vgic: Don't acquire the lpi_list_lock in vgic_put_irq()
The LPI xarray's xa_lock is sufficient for synchronizing writers when freeing a given LPI. Furthermore, readers can only take a new reference on an IRQ if it was already nonzero. Stop taking the lpi_list_lock unnecessarily and get rid of __vgic_put_lpi_locked(). Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20240221054253.3848076-11-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 50ac89b commit e27f2d5

File tree

3 files changed

+11
-22
lines changed

3 files changed

+11
-22
lines changed

arch/arm64/kvm/vgic/vgic-its.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
649649
* was in the cache, and increment it on the new interrupt.
650650
*/
651651
if (cte->irq)
652-
__vgic_put_lpi_locked(kvm, cte->irq);
652+
vgic_put_irq(kvm, cte->irq);
653653

654654
/*
655655
* The irq refcount is guaranteed to be nonzero while holding the
@@ -686,7 +686,7 @@ void vgic_its_invalidate_cache(struct kvm *kvm)
686686
if (!cte->irq)
687687
break;
688688

689-
__vgic_put_lpi_locked(kvm, cte->irq);
689+
vgic_put_irq(kvm, cte->irq);
690690
cte->irq = NULL;
691691
}
692692

arch/arm64/kvm/vgic/vgic.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -111,22 +111,6 @@ static void vgic_irq_release(struct kref *ref)
111111
{
112112
}
113113

114-
/*
115-
* Drop the refcount on the LPI. Must be called with lpi_list_lock held.
116-
*/
117-
void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq)
118-
{
119-
struct vgic_dist *dist = &kvm->arch.vgic;
120-
121-
if (!kref_put(&irq->refcount, vgic_irq_release))
122-
return;
123-
124-
xa_erase(&dist->lpi_xa, irq->intid);
125-
atomic_dec(&dist->lpi_count);
126-
127-
kfree_rcu(irq, rcu);
128-
}
129-
130114
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
131115
{
132116
struct vgic_dist *dist = &kvm->arch.vgic;
@@ -135,9 +119,15 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
135119
if (irq->intid < VGIC_MIN_LPI)
136120
return;
137121

138-
raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
139-
__vgic_put_lpi_locked(kvm, irq);
140-
raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
122+
if (!kref_put(&irq->refcount, vgic_irq_release))
123+
return;
124+
125+
xa_lock_irqsave(&dist->lpi_xa, flags);
126+
__xa_erase(&dist->lpi_xa, irq->intid);
127+
xa_unlock_irqrestore(&dist->lpi_xa, flags);
128+
129+
atomic_dec(&dist->lpi_count);
130+
kfree_rcu(irq, rcu);
141131
}
142132

143133
void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)

arch/arm64/kvm/vgic/vgic.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev,
180180
gpa_t addr, int len);
181181
struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
182182
u32 intid);
183-
void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq);
184183
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq);
185184
bool vgic_get_phys_line_level(struct vgic_irq *irq);
186185
void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending);

0 commit comments

Comments
 (0)