[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v6 03/19] xen/riscv: introduce VMID allocation and manegement
- To: Jan Beulich <jbeulich@xxxxxxxx>
- From: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
- Date: Tue, 9 Dec 2025 11:35:11 +0100
- Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Alistair Francis <alistair.francis@xxxxxxx>, Bob Eshleman <bobbyeshleman@xxxxxxxxx>, Connor Davis <connojdavis@xxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
- Delivery-date: Tue, 09 Dec 2025 10:35:24 +0000
- List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
On 12/8/25 5:31 PM, Jan Beulich wrote:
On 24.11.2025 13:33, Oleksii Kurochko wrote:
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -3096,3 +3096,12 @@ the hypervisor was compiled with `CONFIG_XSM` enabled.
* `silo`: this will deny any unmediated communication channels between
unprivileged VMs. To choose this, the separated option in kconfig must also
be enabled.
+
+### vmid (RISC-V)
+> `= <boolean>`
+
+> Default: `true`
+
+Permit Xen to use Virtual Machine Identifiers. This is an optimisation which
+tags the TLB entries with an ID per vcpu. This allows for guest TLB flushes
+to be performed without the overhead of a complete TLB flush.
Please obey to the alphabetic sorting within this file.
Do we have a definition of alphabetical order? In xen-command-line.pandoc there
is
`### vm-notify-window (Intel)`, and I would expect `### vmid` to appear before
it.
Am I right? So the ordering should be: letters first, then numbers, then special
characters?
--- /dev/null
+++ b/xen/arch/riscv/vmid.c
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/domain.h>
+#include <xen/init.h>
+#include <xen/sections.h>
+#include <xen/lib.h>
+#include <xen/param.h>
+#include <xen/percpu.h>
+
+#include <asm/atomic.h>
+#include <asm/csr.h>
+#include <asm/flushtlb.h>
+#include <asm/p2m.h>
+
+/* Xen command-line option to enable VMIDs */
+static bool __ro_after_init opt_vmid = true;
+boolean_param("vmid", opt_vmid);
+
+/*
+ * VMIDs partition the physical TLB. In the current implementation VMIDs are
+ * introduced to reduce the number of TLB flushes. Each time a guest-physical
+ * address space changes, instead of flushing the TLB, a new VMID is
+ * assigned. This reduces the number of TLB flushes to at most 1/#VMIDs.
+ * The biggest advantage is that hot parts of the hypervisor's code and data
+ * retain in the TLB.
+ *
+ * Sketch of the Implementation:
+ *
+ * VMIDs are a hart-local resource. As preemption of VMIDs is not possible,
+ * VMIDs are assigned in a round-robin scheme. To minimize the overhead of
+ * VMID invalidation, at the time of a TLB flush, VMIDs are tagged with a
+ * 64-bit generation. Only on a generation overflow the code needs to
+ * invalidate all VMID information stored at the VCPUs with are run on the
+ * specific physical processor. When this overflow appears VMID usage is
+ * disabled to retain correctness.
+ */
+
+/* Per-Hart VMID management. */
+struct vmid_data {
+ uint64_t generation;
+ uint16_t next_vmid;
+ uint16_t max_vmid;
+ bool used;
+};
+
+static DEFINE_PER_CPU(struct vmid_data, vmid_data);
+
+static unsigned int vmidlen_detect(void)
+{
+ unsigned int vmid_bits;
+ unsigned char gstage_mode = get_max_supported_mode();
+
+ /*
+ * According to the RISC-V Privileged Architecture Spec:
+ * When MODE=Bare, guest physical addresses are equal to supervisor
+ * physical addresses, and there is no further memory protection
+ * for a guest virtual machine beyond the physical memory protection
+ * scheme described in Section "Physical Memory Protection".
+ * In this case, the remaining fields in hgatp must be set to zeros.
+ * Thereby it is necessary to set gstage_mode not equal to Bare.
+ */
+ ASSERT(gstage_mode != HGATP_MODE_OFF);
+ csr_write(CSR_HGATP,
+ MASK_INSR(gstage_mode, HGATP_MODE_MASK) | HGATP_VMID_MASK);
+ vmid_bits = MASK_EXTR(csr_read(CSR_HGATP), HGATP_VMID_MASK);
+ vmid_bits = flsl(vmid_bits);
+ csr_write(CSR_HGATP, _AC(0, UL));
+
+ /* local_hfence_gvma_all() will be called at the end of pre_gstage_init. */
+
+ return vmid_bits;
+}
+
+void vmid_init(void)
With the presently sole caller being __init, this (and likely the helper above)
could be __init. Iirc you intend to also call this as secondary harts come up,
so this may be okay. But then it wants justifing in the description.
I will add the comment aobve vmidlen_detect():
/*
* vmidlen_detect() is expected to be called during secondary hart bring-up,
* so it should not be marked as __init.
*/
And the similar comment for vmid_init().
Thanks.
~ Oleksii
|