Skip to content

Commit e64f291

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: arm64: vgic-its: Use the per-ITS translation cache for injection
Everything is in place to switch to per-ITS translation caches. Start using the per-ITS cache to avoid the lock serialization related to the global translation cache. Explicitly check for out-of-range device and event IDs as the cache index is packed based on the range the ITS actually supports. Take the RCU read lock to protect against the returned descriptor being freed while trying to take a reference on it, as it is no longer necessary to acquire the lpi_list_lock. Signed-off-by: Oliver Upton <oliver.upton@linux.dev> Link: https://lore.kernel.org/r/20240422200158.2606761-11-oliver.upton@linux.dev Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent dedfcd1 commit e64f291

File tree

1 file changed

+17
-46
lines changed

1 file changed

+17
-46
lines changed

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

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,10 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
251251

252252
#define GIC_LPI_OFFSET 8192
253253

254-
#define VITS_TYPER_IDBITS 16
255-
#define VITS_TYPER_DEVBITS 16
254+
#define VITS_TYPER_IDBITS 16
255+
#define VITS_MAX_EVENTID (BIT(VITS_TYPER_IDBITS) - 1)
256+
#define VITS_TYPER_DEVBITS 16
257+
#define VITS_MAX_DEVID (BIT(VITS_TYPER_DEVBITS) - 1)
256258
#define VITS_DTE_MAX_DEVID_OFFSET (BIT(14) - 1)
257259
#define VITS_ITE_MAX_EVENTID_OFFSET (BIT(16) - 1)
258260

@@ -536,51 +538,27 @@ static unsigned long vgic_its_cache_key(u32 devid, u32 eventid)
536538

537539
}
538540

539-
static struct vgic_irq *__vgic_its_check_cache(struct vgic_dist *dist,
540-
phys_addr_t db,
541-
u32 devid, u32 eventid)
542-
{
543-
struct vgic_translation_cache_entry *cte;
544-
545-
list_for_each_entry(cte, &dist->lpi_translation_cache, entry) {
546-
/*
547-
* If we hit a NULL entry, there is nothing after this
548-
* point.
549-
*/
550-
if (!cte->irq)
551-
break;
552-
553-
if (cte->db != db || cte->devid != devid ||
554-
cte->eventid != eventid)
555-
continue;
556-
557-
/*
558-
* Move this entry to the head, as it is the most
559-
* recently used.
560-
*/
561-
if (!list_is_first(&cte->entry, &dist->lpi_translation_cache))
562-
list_move(&cte->entry, &dist->lpi_translation_cache);
563-
564-
return cte->irq;
565-
}
566-
567-
return NULL;
568-
}
569-
570541
static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
571542
u32 devid, u32 eventid)
572543
{
573-
struct vgic_dist *dist = &kvm->arch.vgic;
544+
unsigned long cache_key = vgic_its_cache_key(devid, eventid);
545+
struct vgic_its *its;
574546
struct vgic_irq *irq;
575-
unsigned long flags;
576547

577-
raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
548+
if (devid > VITS_MAX_DEVID || eventid > VITS_MAX_EVENTID)
549+
return NULL;
550+
551+
its = __vgic_doorbell_to_its(kvm, db);
552+
if (IS_ERR(its))
553+
return NULL;
578554

579-
irq = __vgic_its_check_cache(dist, db, devid, eventid);
555+
rcu_read_lock();
556+
557+
irq = xa_load(&its->translation_cache, cache_key);
580558
if (!vgic_try_get_irq_kref(irq))
581559
irq = NULL;
582560

583-
raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
561+
rcu_read_unlock();
584562

585563
return irq;
586564
}
@@ -605,14 +583,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
605583
if (unlikely(list_empty(&dist->lpi_translation_cache)))
606584
goto out;
607585

608-
/*
609-
* We could have raced with another CPU caching the same
610-
* translation behind our back, so let's check it is not in
611-
* already
612-
*/
613586
db = its->vgic_its_base + GITS_TRANSLATER;
614-
if (__vgic_its_check_cache(dist, db, devid, eventid))
615-
goto out;
616587

617588
/* Always reuse the last entry (LRU policy) */
618589
cte = list_last_entry(&dist->lpi_translation_cache,
@@ -958,7 +929,7 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
958929

959930
switch (type) {
960931
case GITS_BASER_TYPE_DEVICE:
961-
if (id >= BIT_ULL(VITS_TYPER_DEVBITS))
932+
if (id > VITS_MAX_DEVID)
962933
return false;
963934
break;
964935
case GITS_BASER_TYPE_COLLECTION:

0 commit comments

Comments
 (0)