From: Mark Brown <broonie@kernel.org>
To: Marc Zyngier <maz@kernel.org>, Joey Gouly <joey.gouly@arm.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Will Deacon <will@kernel.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>,
Oliver Upton <oupton@kernel.org>
Cc: Dave Martin <Dave.Martin@arm.com>, Fuad Tabba <tabba@google.com>,
Mark Rutland <mark.rutland@arm.com>,
Ben Horgan <ben.horgan@arm.com>,
Jean-Philippe Brucker <jpb@kernel.org>,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
Peter Maydell <peter.maydell@linaro.org>,
Eric Auger <eric.auger@redhat.com>,
Mark Brown <broonie@kernel.org>
Subject: [PATCH v12 13/29] KVM: arm64: Document the KVM ABI for SME
Date: Thu, 09 Jul 2026 19:27:34 +0100 [thread overview]
Message-ID: <20260709-kvm-arm64-sme-v12-13-d0301d79ef58@kernel.org> (raw)
In-Reply-To: <20260709-kvm-arm64-sme-v12-0-d0301d79ef58@kernel.org>
SME, the Scalable Matrix Extension, is an arm64 extension which adds
support for matrix operations, with core concepts patterned after SVE.
SVE introduced some complication in the ABI since it adds new vector
floating point registers with runtime configurable size, the size being
controlled by a parameter called the vector length (VL). To provide control
of this to VMMs we offer two phase configuration of SVE, SVE must first be
enabled for the vCPU with KVM_ARM_VCPU_INIT(KVM_ARM_VCPU_SVE), after which
vector length may then be configured but the configurably sized floating
point registers are inaccessible until finalized with a call to
KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE) after which the configurably sized
registers can be accessed.
SME introduces an additional independent configurable vector length
which as well as controlling the size of the new ZA register also
provides an alternative view of the configurably sized SVE registers
(known as streaming mode) with the guest able to switch between the two
modes as it pleases. There is also a fixed sized register ZT0
introduced in SME2. As well as streaming mode the guest may enable and
disable ZA and (where SME2 is available) ZT0 dynamically independently
of streaming mode. These modes are controlled via the system register
SVCR.
We handle the configuration of the vector length for SME in a similar
manner to SVE, requiring initialization and finalization of the feature
with a pseudo register controlling the available SME vector lengths as for
SVE. Further, if the guest has both SVE and SME then finalizing one
prevents further configuration of the vector length for the other.
Where both SVE and SME are configured for the guest we present the SVE
registers to userspace as having the maximum vector length of the
currently active vector type as configured via SVCR.SM, imposing an
ordering requirement on userspace.
Userspace access to ZA and (if configured) ZT0 is only available when
SVCR.ZA is 1.
Reviewed-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Documentation/virt/kvm/api.rst | 124 +++++++++++++++++++++++++++++------------
1 file changed, 88 insertions(+), 36 deletions(-)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index a5f9ee92f43e..64f482c9f6a9 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -406,7 +406,7 @@ Errors:
instructions from device memory (arm64)
ENOSYS data abort outside memslots with no syndrome info and
KVM_CAP_ARM_NISV_TO_USER not enabled (arm64)
- EPERM SVE feature set but not finalized (arm64)
+ EPERM SVE or SME feature set but not finalized (arm64)
======= ==============================================================
This ioctl is used to run a guest virtual cpu. While there are no
@@ -2607,11 +2607,11 @@ Specifically:
======================= ========= ===== =======================================
.. [1] These encodings are not accepted for SVE-enabled vcpus. See
- :ref:`KVM_ARM_VCPU_INIT`.
+ :ref:`KVM_ARM_VCPU_INIT`. They are also not accepted when SME is
+ enabled without SVE and the vcpu is in streaming mode.
The equivalent register content can be accessed via bits [127:0] of
- the corresponding SVE Zn registers instead for vcpus that have SVE
- enabled (see below).
+ the corresponding SVE Zn registers in these cases (see below).
arm64 CCSIDR registers are demultiplexed by CSSELR value::
@@ -2642,24 +2642,38 @@ arm64 SVE registers have the following bit patterns::
0x6050 0000 0015 060 <slice:5> FFR bits[256*slice + 255 : 256*slice]
0x6060 0000 0015 ffff KVM_REG_ARM64_SVE_VLS pseudo-register
-Access to register IDs where 2048 * slice >= 128 * max_vq will fail with
-ENOENT. max_vq is the vcpu's maximum supported vector length in 128-bit
-quadwords: see [2]_ below.
+arm64 SME registers have the following bit patterns::
-These registers are only accessible on vcpus for which SVE is enabled.
-See KVM_ARM_VCPU_INIT for details.
+ 0x6080 0000 0017 <n:8> <slice:5> ZA[n] bits[2048*slice + 2047 : 2048*slice]
+ 0x6060 0000 0017 0600 ZT0
+ 0x6060 0000 0017 fffe KVM_REG_ARM64_SME_VLS pseudo-register
-In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not
-accessible until the vcpu's SVE configuration has been finalized
-using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE). See KVM_ARM_VCPU_INIT
-and KVM_ARM_VCPU_FINALIZE for more information about this procedure.
+Access to Z, P, FFR or ZA register IDs where 2048 * slice >= 128 *
+max_vq will fail with ENOENT. max_vq is the vcpu's current maximum
+supported vector length in 128-bit quadwords: see [2]_ below.
-KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
-lengths supported by the vcpu to be discovered and configured by
-userspace. When transferred to or from user memory via KVM_GET_ONE_REG
-or KVM_SET_ONE_REG, the value of this register is of type
-__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as
-follows::
+Changing the value of SVCR.SM will result in the contents of registers
+that are architecturally reset by entering or exiting streaming mode
+being reset. When restoring the values of these registers for a VM
+with SME support it is important that SVCR.SM be configured first.
+
+Access to the ZA and ZT0 registers is only available if SVCR.ZA is set
+to 1. These registers are only accessible on vcpus for which SME is
+enabled. See KVM_ARM_VCPU_INIT for details.
+
+In addition, except for KVM_REG_ARM64_SVE_VLS and
+KVM_REG_ARM64_SME_VLS, these registers are not accessible until the
+vcpu's SVE and SME configuration has been finalized using
+KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC). See KVM_ARM_VCPU_INIT and
+KVM_ARM_VCPU_FINALIZE for more information about this procedure.
+
+KVM_REG_ARM64_SVE_VLS and KVM_REG_ARM64_SME_VLS are
+pseudo-registers that allows the set of vector lengths supported by
+the vcpu to be discovered and configured by userspace. When
+transferred to or from user memory via KVM_GET_ONE_REG or
+KVM_SET_ONE_REG, the value of this register is of type
+__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths
+as follows::
__u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS];
@@ -2671,19 +2685,25 @@ follows::
/* Vector length vq * 16 bytes not supported */
.. [2] The maximum value vq for which the above condition is true is
- max_vq. This is the maximum vector length available to the guest on
- this vcpu, and determines which register slices are visible through
- this ioctl interface.
+ max_vq. This is the maximum vector length currently available to
+ the guest on this vcpu, and determines which register slices are
+ visible through this ioctl interface. Note that these slices
+ should not be confused with the architectural "ZA tile slice".
+
+ If SME is supported and SVCR.SM is 1, then the max_vq used for the
+ Z and P registers is the maximum SME vector length. Otherwise
+ it is the maximum SVE vector length.
(See Documentation/arch/arm64/sve.rst for an explanation of the "vq"
nomenclature.)
-KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
-KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
-the host supports.
+KVM_REG_ARM64_SVE_VLS and KVM_REG_ARM64_SME_VLS are only accessible
+after KVM_ARM_VCPU_INIT. KVM_ARM_VCPU_INIT initialises them to the
+best set of vector lengths that the host supports.
-Userspace may subsequently modify it if desired until the vcpu's SVE
-configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).
+Userspace may subsequently modify these registers if desired until the
+vcpu's SVE and SME configuration is finalized using
+KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC).
Apart from simply removing all vector lengths from the host set that
exceed some value, support for arbitrarily chosen sets of vector lengths
@@ -2691,8 +2711,8 @@ is hardware-dependent and may not be available. Attempting to configure
an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
EINVAL.
-After the vcpu's SVE configuration is finalized, further attempts to
-write this register will fail with EPERM.
+After the vcpu's SVE or SME configuration is finalized, further
+attempts to write these registers will fail with EPERM.
arm64 bitmap feature firmware pseudo-registers have the following bit pattern::
@@ -3491,6 +3511,7 @@ The initial values are defined as:
- General Purpose registers, including PC and SP: set to 0
- FPSIMD/NEON registers: set to 0
- SVE registers: set to 0
+ - SME registers: set to 0
- System registers: Reset to their architecturally defined
values as for a warm reset to EL1 (resp. SVC) or EL2 (in the
case of EL2 being enabled).
@@ -3534,7 +3555,7 @@ Possible features:
- KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
Depends on KVM_CAP_ARM_SVE.
- Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+ Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC):
* After KVM_ARM_VCPU_INIT:
@@ -3542,7 +3563,7 @@ Possible features:
initial value of this pseudo-register indicates the best set of
vector lengths possible for a vcpu on this host.
- * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+ * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC):
- KVM_RUN and KVM_GET_REG_LIST are not available;
@@ -3555,11 +3576,41 @@ Possible features:
KVM_SET_ONE_REG, to modify the set of vector lengths available
for the vcpu.
- * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+ * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC):
- the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
no longer be written using KVM_SET_ONE_REG.
+ - KVM_ARM_VCPU_SME: Enables SME for the CPU (arm64 only).
+ Depends on KVM_CAP_ARM_SME.
+ Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC):
+
+ * After KVM_ARM_VCPU_INIT:
+
+ - KVM_REG_ARM64_SME_VLS may be read using KVM_GET_ONE_REG: the
+ initial value of this pseudo-register indicates the best set of
+ vector lengths possible for a vcpu on this host.
+
+ * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC):
+
+ - KVM_RUN and KVM_GET_REG_LIST are not available;
+
+ - KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access
+ the scalable architectural SVE registers
+ KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or
+ KVM_REG_ARM64_SVE_FFR, the matrix register
+ KVM_REG_ARM64_SME_ZAHREG() or the LUT register
+ KVM_REG_ARM64_SME_ZTREG();
+
+ - KVM_REG_ARM64_SME_VLS may optionally be written using
+ KVM_SET_ONE_REG, to modify the set of vector lengths available
+ for the vcpu.
+
+ * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC):
+
+ - the KVM_REG_ARM64_SME_VLS pseudo-register is immutable, and can
+ no longer be written using KVM_SET_ONE_REG.
+
- KVM_ARM_VCPU_HAS_EL2: Enable Nested Virtualisation support,
booting the guest from EL2 instead of EL1.
Depends on KVM_CAP_ARM_EL2.
@@ -5156,11 +5207,12 @@ Errors:
Recognised values for feature:
- ===== ===========================================
- arm64 KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE)
- ===== ===========================================
+ ===== ==============================================================
+ arm64 KVM_ARM_VCPU_VEC (requires KVM_CAP_ARM_SVE or KVM_CAP_ARM_SME)
+ arm64 KVM_ARM_VCPU_SVE (alias for KVM_ARM_VCPU_VEC)
+ ===== ==============================================================
-Finalizes the configuration of the specified vcpu feature.
+Finalizes the configuration of the specified vcpu features.
The vcpu must already have been initialised, enabling the affected feature, by
means of a successful :ref:`KVM_ARM_VCPU_INIT <KVM_ARM_VCPU_INIT>` call with the
--
2.47.3
next prev parent reply other threads:[~2026-07-09 18:41 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 18:27 [PATCH v12 00/29] KVM: arm64: Implement support for SME Mark Brown
2026-07-09 18:27 ` [PATCH v12 01/29] arm64/sysreg: Define full value read/modify/write helpers Mark Brown
2026-07-09 18:27 ` [PATCH v12 02/29] arm64/fpsimd: Update FA64 and ZT0 enables when loading SME state Mark Brown
2026-07-09 18:27 ` [PATCH v12 03/29] arm64/fpsimd: Decide to save ZT0 and streaming mode FFR at bind time Mark Brown
2026-07-09 18:27 ` [PATCH v12 04/29] arm64/sve: Factor virtualizable VL discovery out of SVE specific code Mark Brown
2026-07-09 18:27 ` [PATCH v12 05/29] arm64/fpsimd: Determine maximum virtualisable SME vector length Mark Brown
2026-07-09 18:27 ` [PATCH v12 06/29] KVM: arm64: Handle FEAT_IDST for guest accesses to hidden registers Mark Brown
2026-07-09 18:27 ` [PATCH v12 07/29] KVM: arm64: Pull ctxt_has_ helpers to start of sysreg-sr.h Mark Brown
2026-07-09 18:27 ` [PATCH v12 08/29] KVM: arm64: Rename SVE finalization constants to be more general Mark Brown
2026-07-09 18:27 ` [PATCH v12 09/29] KVM: arm64: Define internal features for SME Mark Brown
2026-07-09 18:27 ` [PATCH v12 10/29] KVM: arm64: Rename sve_state_reg_region Mark Brown
2026-07-09 18:27 ` [PATCH v12 11/29] KVM: arm64: Store vector lengths in an array Mark Brown
2026-07-09 18:27 ` [PATCH v12 12/29] KVM: arm64: Factor SVE code out of fpsimd_lazy_switch_to_host() Mark Brown
2026-07-09 18:27 ` Mark Brown [this message]
2026-07-09 18:27 ` [PATCH v12 14/29] KVM: arm64: Implement SME vector length configuration Mark Brown
2026-07-09 18:27 ` [PATCH v12 15/29] KVM: arm64: Support SME control registers Mark Brown
2026-07-09 18:27 ` [PATCH v12 16/29] KVM: arm64: Support TPIDR2_EL0 Mark Brown
2026-07-09 18:27 ` [PATCH v12 17/29] KVM: arm64: Support SME identification registers for guests Mark Brown
2026-07-09 18:27 ` [PATCH v12 18/29] KVM: arm64: Support SME priority registers Mark Brown
2026-07-09 18:27 ` [PATCH v12 19/29] KVM: arm64: Support userspace access to streaming mode Z and P registers Mark Brown
2026-07-09 18:27 ` [PATCH v12 20/29] KVM: arm64: Flush register state on writes to SVCR.SM and SVCR.ZA Mark Brown
2026-07-09 18:27 ` [PATCH v12 21/29] KVM: arm64: Expose SME specific state to userspace Mark Brown
2026-07-09 18:27 ` [PATCH v12 22/29] KVM: arm64: Context switch SME state for guests Mark Brown
2026-07-09 18:27 ` [PATCH v12 23/29] KVM: arm64: Handle SME exceptions Mark Brown
2026-07-09 18:27 ` [PATCH v12 24/29] KVM: arm64: Expose SME to nested guests Mark Brown
2026-07-09 18:27 ` [PATCH v12 25/29] KVM: arm64: Provide interface for configuring and enabling SME for guests Mark Brown
2026-07-09 18:27 ` [PATCH v12 26/29] KVM: arm64: selftests: Remove spurious check for single bit safe values Mark Brown
2026-07-09 18:27 ` [PATCH v12 27/29] KVM: arm64: selftests: Skip impossible invalid value tests Mark Brown
2026-07-09 18:27 ` [PATCH v12 28/29] KVM: arm64: selftests: Add SME system registers to get-reg-list Mark Brown
2026-07-09 18:27 ` [PATCH v12 29/29] KVM: arm64: selftests: Add SME to set_id_regs test Mark Brown
2026-07-10 8:43 ` [PATCH v12 00/29] KVM: arm64: Implement support for SME Fuad Tabba
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=20260709-kvm-arm64-sme-v12-13-d0301d79ef58@kernel.org \
--to=broonie@kernel.org \
--cc=Dave.Martin@arm.com \
--cc=ben.horgan@arm.com \
--cc=catalin.marinas@arm.com \
--cc=corbet@lwn.net \
--cc=eric.auger@redhat.com \
--cc=joey.gouly@arm.com \
--cc=jpb@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=linux-kselftest@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=shuah@kernel.org \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.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