Skip to content

Commit 3a08a6c

Browse files
committed
KVM: arm64: vgic-v3: Use bare refcount for VGIC LPIs
KVM's use of krefs to manage LPIs isn't adding much, especially considering vgic_irq_release() is a noop due to the lack of sufficient context. Switch to using a regular refcount in anticipation of adding a meaningful release concept for LPIs. Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 7d6ca84 commit 3a08a6c

File tree

7 files changed

+18
-27
lines changed

7 files changed

+18
-27
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int iter_mark_lpis(struct kvm *kvm)
6969
int nr_lpis = 0;
7070

7171
xa_for_each(&dist->lpi_xa, intid, irq) {
72-
if (!vgic_try_get_irq_kref(irq))
72+
if (!vgic_try_get_irq_ref(irq))
7373
continue;
7474

7575
xa_set_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
208208
raw_spin_lock_init(&irq->irq_lock);
209209
irq->vcpu = NULL;
210210
irq->target_vcpu = vcpu0;
211-
kref_init(&irq->refcount);
211+
refcount_set(&irq->refcount, 0);
212212
switch (dist->vgic_model) {
213213
case KVM_DEV_TYPE_ARM_VGIC_V2:
214214
irq->targets = 0;
@@ -277,7 +277,7 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
277277
irq->intid = i;
278278
irq->vcpu = NULL;
279279
irq->target_vcpu = vcpu;
280-
kref_init(&irq->refcount);
280+
refcount_set(&irq->refcount, 0);
281281
if (vgic_irq_is_sgi(i)) {
282282
/* SGIs */
283283
irq->enabled = 1;

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
9999
raw_spin_lock_init(&irq->irq_lock);
100100

101101
irq->config = VGIC_CONFIG_EDGE;
102-
kref_init(&irq->refcount);
102+
refcount_set(&irq->refcount, 1);
103103
irq->intid = intid;
104104
irq->target_vcpu = vcpu;
105105
irq->group = 1;
@@ -111,7 +111,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
111111
* check that we don't add a second list entry with the same LPI.
112112
*/
113113
oldirq = xa_load(&dist->lpi_xa, intid);
114-
if (vgic_try_get_irq_kref(oldirq)) {
114+
if (vgic_try_get_irq_ref(oldirq)) {
115115
/* Someone was faster with adding this LPI, lets use that. */
116116
kfree(irq);
117117
irq = oldirq;
@@ -547,7 +547,7 @@ static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
547547
rcu_read_lock();
548548

549549
irq = xa_load(&its->translation_cache, cache_key);
550-
if (!vgic_try_get_irq_kref(irq))
550+
if (!vgic_try_get_irq_ref(irq))
551551
irq = NULL;
552552

553553
rcu_read_unlock();
@@ -571,7 +571,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
571571
* its_lock, as the ITE (and the reference it holds) cannot be freed.
572572
*/
573573
lockdep_assert_held(&its->its_lock);
574-
vgic_get_irq_kref(irq);
574+
vgic_get_irq_ref(irq);
575575

576576
old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
577577

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ static struct vgic_irq *__vgic_host_irq_get_vlpi(struct kvm *kvm, int host_irq)
518518
if (!irq->hw || irq->host_irq != host_irq)
519519
continue;
520520

521-
if (!vgic_try_get_irq_kref(irq))
521+
if (!vgic_try_get_irq_ref(irq))
522522
return NULL;
523523

524524
return irq;

arch/arm64/kvm/vgic/vgic.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
7171
rcu_read_lock();
7272

7373
irq = xa_load(&dist->lpi_xa, intid);
74-
if (!vgic_try_get_irq_kref(irq))
74+
if (!vgic_try_get_irq_ref(irq))
7575
irq = NULL;
7676

7777
rcu_read_unlock();
@@ -114,15 +114,6 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
114114
return vgic_get_irq(vcpu->kvm, intid);
115115
}
116116

117-
/*
118-
* We can't do anything in here, because we lack the kvm pointer to
119-
* lock and remove the item from the lpi_list. So we keep this function
120-
* empty and use the return value of kref_put() to trigger the freeing.
121-
*/
122-
static void vgic_irq_release(struct kref *ref)
123-
{
124-
}
125-
126117
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
127118
{
128119
struct vgic_dist *dist = &kvm->arch.vgic;
@@ -131,7 +122,7 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
131122
if (irq->intid < VGIC_MIN_LPI)
132123
return;
133124

134-
if (!kref_put(&irq->refcount, vgic_irq_release))
125+
if (!refcount_dec_and_test(&irq->refcount))
135126
return;
136127

137128
xa_lock_irqsave(&dist->lpi_xa, flags);
@@ -399,7 +390,7 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
399390
* now in the ap_list. This is safe as the caller must already hold a
400391
* reference on the irq.
401392
*/
402-
vgic_get_irq_kref(irq);
393+
vgic_get_irq_ref(irq);
403394
list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
404395
irq->vcpu = vcpu;
405396

@@ -657,7 +648,7 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
657648

658649
/*
659650
* This vgic_put_irq call matches the
660-
* vgic_get_irq_kref in vgic_queue_irq_unlock,
651+
* vgic_get_irq_ref in vgic_queue_irq_unlock,
661652
* where we added the LPI to the ap_list. As
662653
* we remove the irq from the list, we drop
663654
* also drop the refcount.

arch/arm64/kvm/vgic/vgic.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,20 @@ void vgic_v2_put(struct kvm_vcpu *vcpu);
267267
void vgic_v2_save_state(struct kvm_vcpu *vcpu);
268268
void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
269269

270-
static inline bool vgic_try_get_irq_kref(struct vgic_irq *irq)
270+
static inline bool vgic_try_get_irq_ref(struct vgic_irq *irq)
271271
{
272272
if (!irq)
273273
return false;
274274

275275
if (irq->intid < VGIC_MIN_LPI)
276276
return true;
277277

278-
return kref_get_unless_zero(&irq->refcount);
278+
return refcount_inc_not_zero(&irq->refcount);
279279
}
280280

281-
static inline void vgic_get_irq_kref(struct vgic_irq *irq)
281+
static inline void vgic_get_irq_ref(struct vgic_irq *irq)
282282
{
283-
WARN_ON_ONCE(!vgic_try_get_irq_kref(irq));
283+
WARN_ON_ONCE(!vgic_try_get_irq_ref(irq));
284284
}
285285

286286
void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);

include/kvm/arm_vgic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include <linux/bits.h>
99
#include <linux/kvm.h>
1010
#include <linux/irqreturn.h>
11-
#include <linux/kref.h>
1211
#include <linux/mutex.h>
12+
#include <linux/refcount.h>
1313
#include <linux/spinlock.h>
1414
#include <linux/static_key.h>
1515
#include <linux/types.h>
@@ -142,7 +142,7 @@ struct vgic_irq {
142142
bool active;
143143
bool enabled;
144144
bool hw; /* Tied to HW IRQ */
145-
struct kref refcount; /* Used for LPIs */
145+
refcount_t refcount; /* Used for LPIs */
146146
u32 hwintid; /* HW INTID number */
147147
unsigned int host_irq; /* linux irq corresponding to hwintid */
148148
union {

0 commit comments

Comments
 (0)