public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Oliver Upton <oliver.upton@linux.dev>
To: kvmarm@lists.linux.dev
Cc: Marc Zyngier <maz@kernel.org>, James Morse <james.morse@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Eric Auger <eric.auger@redhat.com>,
	kvm@vger.kernel.org, Oliver Upton <oliver.upton@linux.dev>
Subject: [PATCH v3 10/19] KVM: arm64: vgic-its: Use the per-ITS translation cache for injection
Date: Mon, 22 Apr 2024 20:01:49 +0000	[thread overview]
Message-ID: <20240422200158.2606761-11-oliver.upton@linux.dev> (raw)
In-Reply-To: <20240422200158.2606761-1-oliver.upton@linux.dev>

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>
---
 arch/arm64/kvm/vgic/vgic-its.c | 63 +++++++++-------------------------
 1 file changed, 17 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 237e92016c1b..9a517faa43ae 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -251,8 +251,10 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 
 #define GIC_LPI_OFFSET 8192
 
-#define VITS_TYPER_IDBITS 16
-#define VITS_TYPER_DEVBITS 16
+#define VITS_TYPER_IDBITS		16
+#define VITS_MAX_EVENTID		(BIT(VITS_TYPER_IDBITS) - 1)
+#define VITS_TYPER_DEVBITS		16
+#define VITS_MAX_DEVID			(BIT(VITS_TYPER_DEVBITS) - 1)
 #define VITS_DTE_MAX_DEVID_OFFSET	(BIT(14) - 1)
 #define VITS_ITE_MAX_EVENTID_OFFSET	(BIT(16) - 1)
 
@@ -536,51 +538,27 @@ static unsigned long vgic_its_cache_key(u32 devid, u32 eventid)
 
 }
 
-static struct vgic_irq *__vgic_its_check_cache(struct vgic_dist *dist,
-					       phys_addr_t db,
-					       u32 devid, u32 eventid)
-{
-	struct vgic_translation_cache_entry *cte;
-
-	list_for_each_entry(cte, &dist->lpi_translation_cache, entry) {
-		/*
-		 * If we hit a NULL entry, there is nothing after this
-		 * point.
-		 */
-		if (!cte->irq)
-			break;
-
-		if (cte->db != db || cte->devid != devid ||
-		    cte->eventid != eventid)
-			continue;
-
-		/*
-		 * Move this entry to the head, as it is the most
-		 * recently used.
-		 */
-		if (!list_is_first(&cte->entry, &dist->lpi_translation_cache))
-			list_move(&cte->entry, &dist->lpi_translation_cache);
-
-		return cte->irq;
-	}
-
-	return NULL;
-}
-
 static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
 					     u32 devid, u32 eventid)
 {
-	struct vgic_dist *dist = &kvm->arch.vgic;
+	unsigned long cache_key = vgic_its_cache_key(devid, eventid);
+	struct vgic_its *its;
 	struct vgic_irq *irq;
-	unsigned long flags;
 
-	raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
+	if (devid > VITS_MAX_DEVID || eventid > VITS_MAX_EVENTID)
+		return NULL;
+
+	its = __vgic_doorbell_to_its(kvm, db);
+	if (IS_ERR(its))
+		return NULL;
 
-	irq = __vgic_its_check_cache(dist, db, devid, eventid);
+	rcu_read_lock();
+
+	irq = xa_load(&its->translation_cache, cache_key);
 	if (!vgic_try_get_irq_kref(irq))
 		irq = NULL;
 
-	raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+	rcu_read_unlock();
 
 	return irq;
 }
@@ -605,14 +583,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
 	if (unlikely(list_empty(&dist->lpi_translation_cache)))
 		goto out;
 
-	/*
-	 * We could have raced with another CPU caching the same
-	 * translation behind our back, so let's check it is not in
-	 * already
-	 */
 	db = its->vgic_its_base + GITS_TRANSLATER;
-	if (__vgic_its_check_cache(dist, db, devid, eventid))
-		goto out;
 
 	/* Always reuse the last entry (LRU policy) */
 	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,
 
 	switch (type) {
 	case GITS_BASER_TYPE_DEVICE:
-		if (id >= BIT_ULL(VITS_TYPER_DEVBITS))
+		if (id > VITS_MAX_DEVID)
 			return false;
 		break;
 	case GITS_BASER_TYPE_COLLECTION:
-- 
2.44.0.769.g3c40516874-goog


  parent reply	other threads:[~2024-04-22 20:02 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-22 20:01 [PATCH v3 00/19] KVM: arm64: Transition to a per-ITS translation cache Oliver Upton
2024-04-22 20:01 ` [PATCH v3 01/19] KVM: Treat the device list as an rculist Oliver Upton
2024-04-23  0:15   ` Sean Christopherson
2024-04-22 20:01 ` [PATCH v3 02/19] KVM: arm64: vgic-its: Walk LPI xarray in its_sync_lpi_pending_table() Oliver Upton
2024-04-22 20:01 ` [PATCH v3 03/19] KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_invall() Oliver Upton
2024-04-22 20:01 ` [PATCH v3 04/19] KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_cmd_handle_movall() Oliver Upton
2024-04-22 20:01 ` [PATCH v3 05/19] KVM: arm64: vgic-debug: Use an xarray mark for debug iterator Oliver Upton
2024-08-06  9:23   ` Zenghui Yu
2024-08-06 12:39     ` Zenghui Yu
2024-08-06 14:11       ` Zenghui Yu
2024-08-06 16:00         ` Zenghui Yu
2024-08-06 16:21           ` Marc Zyngier
2024-08-07  5:23             ` Zenghui Yu
2024-04-22 20:01 ` [PATCH v3 06/19] KVM: arm64: vgic-its: Get rid of vgic_copy_lpi_list() Oliver Upton
2024-04-22 20:01 ` [PATCH v3 07/19] KVM: arm64: vgic-its: Scope translation cache invalidations to an ITS Oliver Upton
2024-04-22 20:01 ` [PATCH v3 08/19] KVM: arm64: vgic-its: Maintain a translation cache per ITS Oliver Upton
2024-04-22 20:01 ` [PATCH v3 09/19] KVM: arm64: vgic-its: Spin off helper for finding ITS by doorbell addr Oliver Upton
2024-04-22 20:01 ` Oliver Upton [this message]
2024-04-22 20:01 ` [PATCH v3 11/19] KVM: arm64: vgic-its: Rip out the global translation cache Oliver Upton
2024-04-22 20:01 ` [PATCH v3 12/19] KVM: arm64: vgic-its: Get rid of the lpi_list_lock Oliver Upton
2024-04-22 20:01 ` [PATCH v3 13/19] KVM: selftests: Align with kernel's GIC definitions Oliver Upton
2024-04-22 20:01 ` [PATCH v3 14/19] KVM: selftests: Standardise layout of GIC frames Oliver Upton
2024-04-22 20:01 ` [PATCH v3 15/19] KVM: selftests: Add quadword MMIO accessors Oliver Upton
2024-04-22 20:01 ` [PATCH v3 16/19] KVM: selftests: Add a minimal library for interacting with an ITS Oliver Upton
2024-04-22 20:01 ` [PATCH v3 17/19] KVM: selftests: Add helper for enabling LPIs on a redistributor Oliver Upton
2024-04-22 20:01 ` [PATCH v3 18/19] KVM: selftests: Use MPIDR_HWID_BITMASK from cputype.h Oliver Upton
2024-04-22 20:01 ` [PATCH v3 19/19] KVM: selftests: Add stress test for LPI injection Oliver Upton
2024-04-25 12:33 ` [PATCH v3 00/19] KVM: arm64: Transition to a per-ITS translation cache Marc Zyngier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240422200158.2606761-11-oliver.upton@linux.dev \
    --to=oliver.upton@linux.dev \
    --cc=eric.auger@redhat.com \
    --cc=james.morse@arm.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=suzuki.poulose@arm.com \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox