From: Ryan Roberts <ryan.roberts@arm.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Arnd Bergmann <arnd@arndb.de>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Marc Zyngier <maz@kernel.org>, Oliver Upton <oupton@kernel.org>,
Alex Williamson <alex@shazbot.org>,
Jason Gunthorpe <jgg@nvidia.com>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Jean-Philippe Brucker <jpb@kernel.org>,
Oded Gabbay <ogabbay@kernel.org>,
Jonathan Corbet <corbet@lwn.net>
Cc: Ryan Roberts <ryan.roberts@arm.com>,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org, devicetree@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org,
Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Subject: [RFC PATCH v2 10/15] KVM: arm64: Introduce support to pin VMIDs
Date: Thu, 15 Oct 2026 15:25:44 +0100 [thread overview]
Message-ID: <20261015142552.4128028-11-ryan.roberts@arm.com> (raw)
In-Reply-To: <20261015142552.4128028-1-ryan.roberts@arm.com>
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Introduce kvm_arm_pinned_vmid_get() and kvm_arm_pinned_vmid_put(), to pin
a VMID associated with a KVM instance. This will guarantee that VMID
remains the same after a rollover.
This will allow some devices, such as ones behind an SMMUv3, to have
their TLB entries tagged with the KVM VMID. In some systems, TLB
maintenance instructions from the CPU to the Inner Shareable domain can
invalidate those entries.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Signed-off-by: Jean-Philippe Brucker <jpb@kernel.org>
---
arch/arm64/include/asm/kvm_host.h | 3 ++
arch/arm64/kvm/vmid.c | 77 ++++++++++++++++++++++++++++---
2 files changed, 73 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index cd9b9d2462f9..30d0082b15ec 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -148,6 +148,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages);
struct kvm_vmid {
atomic64_t id;
+ refcount_t pinned;
};
struct kvm_s2_mmu {
@@ -1359,6 +1360,8 @@ int __init kvm_arm_vmid_alloc_init(void);
void __init kvm_arm_vmid_alloc_free(void);
void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
void kvm_arm_vmid_clear_active(void);
+int kvm_arm_pinned_vmid_get(struct kvm *kvm);
+void kvm_arm_pinned_vmid_put(struct kvm *kvm);
static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
{
diff --git a/arch/arm64/kvm/vmid.c b/arch/arm64/kvm/vmid.c
index 7fe8ba1a2851..322279f59e88 100644
--- a/arch/arm64/kvm/vmid.c
+++ b/arch/arm64/kvm/vmid.c
@@ -25,6 +25,10 @@ static unsigned long *vmid_map;
static DEFINE_PER_CPU(atomic64_t, active_vmids);
static DEFINE_PER_CPU(u64, reserved_vmids);
+static unsigned long max_pinned_vmids;
+static unsigned long nr_pinned_vmids;
+static unsigned long *pinned_vmid_map;
+
#define VMID_MASK (~GENMASK(kvm_arm_vmid_bits - 1, 0))
#define VMID_FIRST_VERSION (1UL << kvm_arm_vmid_bits)
@@ -47,7 +51,7 @@ static void flush_context(void)
int cpu;
u64 vmid;
- bitmap_zero(vmid_map, NUM_USER_VMIDS);
+ bitmap_copy(vmid_map, pinned_vmid_map, NUM_USER_VMIDS);
for_each_possible_cpu(cpu) {
vmid = atomic64_xchg_relaxed(&per_cpu(active_vmids, cpu), 0);
@@ -98,12 +102,14 @@ static u64 new_vmid(struct kvm_vmid *kvm_vmid)
if (vmid != 0) {
u64 newvmid = generation | (vmid & ~VMID_MASK);
- if (check_update_reserved_vmid(vmid, newvmid)) {
- atomic64_set(&kvm_vmid->id, newvmid);
- return newvmid;
- }
-
- if (!__test_and_set_bit(vmid2idx(vmid), vmid_map)) {
+ /*
+ * If it is pinned, we can keep using it. Note that reserved
+ * takes priority, because even if it is also pinned, we need to
+ * update the generation into the reserved_vmids.
+ */
+ if (check_update_reserved_vmid(vmid, newvmid) ||
+ refcount_read(&kvm_vmid->pinned) ||
+ !__test_and_set_bit(vmid2idx(vmid), vmid_map)) {
atomic64_set(&kvm_vmid->id, newvmid);
return newvmid;
}
@@ -169,6 +175,49 @@ void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags);
}
+int kvm_arm_pinned_vmid_get(struct kvm *kvm)
+{
+ struct kvm_vmid *kvm_vmid;
+ u64 vmid;
+
+ kvm_vmid = &kvm->arch.mmu.vmid;
+
+ guard(raw_spinlock_irqsave)(&cpu_vmid_lock);
+ vmid = atomic64_read(&kvm_vmid->id);
+
+ if (refcount_inc_not_zero(&kvm_vmid->pinned))
+ return (vmid & ~VMID_MASK);
+
+ if (nr_pinned_vmids >= max_pinned_vmids)
+ return -EINVAL;
+
+ /*
+ * If we went through one or more rollover since that VMID was
+ * used, make sure it is still valid, or generate a new one.
+ */
+ if (!vmid_gen_match(vmid))
+ vmid = new_vmid(kvm_vmid);
+
+ nr_pinned_vmids++;
+ __set_bit(vmid2idx(vmid), pinned_vmid_map);
+ refcount_set(&kvm_vmid->pinned, 1);
+ return (vmid & ~VMID_MASK);
+}
+
+void kvm_arm_pinned_vmid_put(struct kvm *kvm)
+{
+ struct kvm_vmid *kvm_vmid;
+ u64 vmid;
+
+ kvm_vmid = &kvm->arch.mmu.vmid;
+ vmid = atomic64_read(&kvm_vmid->id);
+ guard(raw_spinlock_irqsave)(&cpu_vmid_lock);
+ if (refcount_dec_and_test(&kvm_vmid->pinned)) {
+ __clear_bit(vmid2idx(vmid), pinned_vmid_map);
+ nr_pinned_vmids--;
+ }
+}
+
/*
* Initialize the VMID allocator
*/
@@ -186,10 +235,24 @@ int __init kvm_arm_vmid_alloc_init(void)
if (!vmid_map)
return -ENOMEM;
+ pinned_vmid_map = bitmap_zalloc(NUM_USER_VMIDS, GFP_KERNEL);
+ if (!pinned_vmid_map) {
+ bitmap_free(vmid_map);
+ return -ENOMEM;
+ }
+ nr_pinned_vmids = 0;
+
+ /*
+ * Ensure we have at least one empty slot available after rollover when
+ * the maximum number of VMIDs are pinned. VMID#0 is reserved.
+ */
+ max_pinned_vmids = NUM_USER_VMIDS - num_possible_cpus() - 2;
+
return 0;
}
void __init kvm_arm_vmid_alloc_free(void)
{
+ bitmap_free(pinned_vmid_map);
bitmap_free(vmid_map);
}
--
2.43.0
next prev parent reply other threads:[~2026-10-15 14:26 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 14:25 [RFC PATCH v2 00/15] Arm Core Local Accelerator Driver Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 01/15] misc/arm-cla: Add driver skeleton and documentation Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 02/15] misc/arm-cla: Add launch operation helpers Ryan Roberts
2026-10-15 16:17 ` Greg Kroah-Hartman
2026-10-15 16:32 ` Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 03/15] dt-bindings: misc: Add Arm Core Local Accelerator Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 04/15] misc/arm-cla: Probe firmware-described devices Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 05/15] misc/arm-cla: Initialize devices on CPU bringup Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 06/15] misc/arm-cla: Accelerator context save and restore Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 07/15] misc/arm-cla: Set up memory translation context Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 08/15] misc/arm-cla: Manage domain contexts Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 09/15] misc/arm-cla: Add userspace interface Ryan Roberts
2026-10-15 14:25 ` Ryan Roberts [this message]
2026-10-15 14:25 ` [RFC PATCH v2 11/15] KVM: arm64: Export stage-2 MMU config Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 12/15] vfio: Support VFIO devices that access the CPU MMU Ryan Roberts
2026-10-15 16:44 ` Jason Gunthorpe
2026-10-15 14:25 ` [RFC PATCH v2 13/15] misc/arm-cla: Add stage-2 MTC and VM context switch Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 14/15] misc/arm-cla: Support exclusive context assignment Ryan Roberts
2026-10-15 14:25 ` [RFC PATCH v2 15/15] misc/arm-cla: Add vfio-mdev user interface Ryan Roberts
2026-10-15 16:41 ` Jason Gunthorpe
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=20261015142552.4128028-11-ryan.roberts@arm.com \
--to=ryan.roberts@arm.com \
--cc=alex@shazbot.org \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=jgg@nvidia.com \
--cc=jpb@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=ogabbay@kernel.org \
--cc=oupton@kernel.org \
--cc=robh@kernel.org \
--cc=shameerali.kolothum.thodi@huawei.com \
--cc=will@kernel.org \
/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
all inboxes | Powered by JetHome®