Skip to content

Commit 50ac89b

Browse files
committed
KVM: arm64: vgic: Ensure the irq refcount is nonzero when taking a ref
It will soon be possible for get() and put() calls to happen in parallel, which means in most cases we must ensure the refcount is nonzero when taking a new reference. Switch to using vgic_try_get_irq_kref() where necessary, and document the few conditions where an IRQ's refcount is guaranteed to be nonzero. Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 864d430 commit 50ac89b

File tree

2 files changed

+10
-11
lines changed

2 files changed

+10
-11
lines changed

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,11 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
7474
* check that we don't add a second list entry with the same LPI.
7575
*/
7676
oldirq = xa_load(&dist->lpi_xa, intid);
77-
if (oldirq) {
77+
if (vgic_try_get_irq_kref(oldirq)) {
7878
/* Someone was faster with adding this LPI, lets use that. */
7979
kfree(irq);
8080
irq = oldirq;
8181

82-
/*
83-
* This increases the refcount, the caller is expected to
84-
* call vgic_put_irq() on the returned pointer once it's
85-
* finished with the IRQ.
86-
*/
87-
vgic_get_irq_kref(irq);
88-
8982
goto out_unlock;
9083
}
9184

@@ -611,8 +604,8 @@ static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
611604
raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
612605

613606
irq = __vgic_its_check_cache(dist, db, devid, eventid);
614-
if (irq)
615-
vgic_get_irq_kref(irq);
607+
if (!vgic_try_get_irq_kref(irq))
608+
irq = NULL;
616609

617610
raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
618611

@@ -658,6 +651,11 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
658651
if (cte->irq)
659652
__vgic_put_lpi_locked(kvm, cte->irq);
660653

654+
/*
655+
* The irq refcount is guaranteed to be nonzero while holding the
656+
* its_lock, as the ITE (and the reference it holds) cannot be freed.
657+
*/
658+
lockdep_assert_held(&its->its_lock);
661659
vgic_get_irq_kref(irq);
662660

663661
cte->db = db;

arch/arm64/kvm/vgic/vgic.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,8 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
395395

396396
/*
397397
* Grab a reference to the irq to reflect the fact that it is
398-
* now in the ap_list.
398+
* now in the ap_list. This is safe as the caller must already hold a
399+
* reference on the irq.
399400
*/
400401
vgic_get_irq_kref(irq);
401402
list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);

0 commit comments

Comments
 (0)