* [PATCH v2 1/3] arm64/sme: Support disabling streaming mode via ptrace on SME only systems
2025-10-15 17:56 [PATCH v2 0/3] arm64/sme: Support disabling streaming mode via ptrace on SME only systems Mark Brown
@ 2025-10-15 17:56 ` Mark Brown
2025-10-29 15:23 ` David Spickett
2025-10-15 17:56 ` [PATCH v2 2/3] kselftst/arm64: Test NT_ARM_SVE FPSIMD format writes on non-SVE systems Mark Brown
2025-10-15 17:56 ` [PATCH v2 3/3] kselftest/arm64: Cover disabling streaming mode without SVE in fp-ptrace Mark Brown
2 siblings, 1 reply; 5+ messages in thread
From: Mark Brown @ 2025-10-15 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan, Jonathan Corbet,
Oleg Nesterov
Cc: Mark Rutland, David Spickett, Thiago Jung Bauermann, Luis Machado,
linux-arm-kernel, linux-kselftest, linux-kernel, linux-doc,
Mark Brown
Currently it is not possible to disable streaming mode via ptrace on SME
only systems, the interface for doing this is to write via NT_ARM_SVE but
such writes will be rejected on a system without SVE support. Enable this
functionality by allowing userspace to write SVE_PT_REGS_FPSIMD format data
via NT_ARM_SVE with the vector length set to 0 on SME only systems. Such
writes currently error since we require that a vector length is specified
which should minimise the risk that existing software is relying on current
behaviour.
Reads are not supported since I am not aware of any use case for this and
there is some risk that an existing userspace application may be confused if
it reads NT_ARM_SVE on a system without SVE. Existing kernels will return
FPSIMD formatted register state from NT_ARM_SVE if full SVE state is not
stored, for example if the task has not used SVE. Returning a vector length
of 0 would create a risk that software would try to do things like allocate
space for register state with zero sizes, while returning a vector length of
128 bits would look like SVE is supported. It seems safer to just not make
the changes to add read support.
It remains possible for userspace to detect a SME only system via the ptrace
interface only since reads of NT_ARM_SSVE and NT_ARM_ZA will succeed while
reads of NT_ARM_SVE will fail. Read/write access to the FPSIMD registers in
non-streaming mode is available via REGSET_FPR.
sve_set_common() already avoids allocating SVE storage when doing a FPSIMD
formatted write and allocating SME storage when doing a NT_ARM_SVE write so
we change the function to validate the new case and skip setting a vector
length for it.
The aim is to make a minimally invasive change, no operation that would
previously have succeeded will be affected, and we use a previously
defined interface in new circumstances rather than define completely new
ABI.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Documentation/arch/arm64/sve.rst | 5 +++++
arch/arm64/kernel/ptrace.c | 40 +++++++++++++++++++++++++++++++++-------
2 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/Documentation/arch/arm64/sve.rst b/Documentation/arch/arm64/sve.rst
index 28152492c29c..a61c9d0efe4d 100644
--- a/Documentation/arch/arm64/sve.rst
+++ b/Documentation/arch/arm64/sve.rst
@@ -402,6 +402,11 @@ The regset data starts with struct user_sve_header, containing:
streaming mode and any SETREGSET of NT_ARM_SSVE will enter streaming mode
if the target was not in streaming mode.
+* On systems that do not support SVE it is permitted to use SETREGSET to
+ write SVE_PT_REGS_FPSIMD formatted data via NT_ARM_SVE, in this case the
+ vector length should be specified as 0. This allows streaming mode to be
+ disabled on systems with SME but not SVE.
+
* If any register data is provided along with SVE_PT_VL_ONEXEC then the
registers data will be interpreted with the current vector length, not
the vector length configured for use on exec.
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 4b001121c72d..b9bdd83fbbca 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -912,13 +912,39 @@ static int sve_set_common(struct task_struct *target,
return -EINVAL;
/*
- * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by
- * vec_set_vector_length(), which will also validate them for us:
+ * On systems without SVE we accept FPSIMD format writes with
+ * a VL of 0 to allow exiting streaming mode, otherwise a VL
+ * is required.
*/
- ret = vec_set_vector_length(target, type, header.vl,
- ((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16);
- if (ret)
- return ret;
+ if (header.vl) {
+ /*
+ * If the system does not support SVE we can't
+ * configure a SVE VL.
+ */
+ if (!system_supports_sve() && type == ARM64_VEC_SVE)
+ return -EINVAL;
+
+ /*
+ * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are
+ * consumed by vec_set_vector_length(), which will
+ * also validate them for us:
+ */
+ ret = vec_set_vector_length(target, type, header.vl,
+ ((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16);
+ if (ret)
+ return ret;
+ } else {
+ /* If the system supports SVE we require a VL. */
+ if (system_supports_sve())
+ return -EINVAL;
+
+ /*
+ * Only FPSIMD formatted data with no flags set is
+ * supported.
+ */
+ if (header.flags != SVE_PT_REGS_FPSIMD)
+ return -EINVAL;
+ }
/* Allocate SME storage if necessary, preserving any existing ZA/ZT state */
if (type == ARM64_VEC_SME) {
@@ -1016,7 +1042,7 @@ static int sve_set(struct task_struct *target,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
- if (!system_supports_sve())
+ if (!system_supports_sve() && !system_supports_sme())
return -EINVAL;
return sve_set_common(target, regset, pos, count, kbuf, ubuf,
--
2.47.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH v2 1/3] arm64/sme: Support disabling streaming mode via ptrace on SME only systems
2025-10-15 17:56 ` [PATCH v2 1/3] " Mark Brown
@ 2025-10-29 15:23 ` David Spickett
0 siblings, 0 replies; 5+ messages in thread
From: David Spickett @ 2025-10-29 15:23 UTC (permalink / raw)
To: broonie
Cc: catalin.marinas, corbet, david.spickett, linux-arm-kernel,
linux-doc, linux-kernel, linux-kselftest, luis.machado.foss,
mark.rutland, oleg, shuah, thiago.bauermann, will, David Spickett
I have put the LLDB changes for this into review.
We are tracking SME only support in this issue:
https://github.com/llvm/llvm-project/issues/138717
The PRs that relate to these kernel changes are
listed in this comment:
https://github.com/llvm/llvm-project/issues/138717#issuecomment-3456979166
LLDB's use case for this new ptrace feature is to restore
process state after expression evaluation takes a process
from non-streaming to streaming mode. We have a specific
code path to handle that restoration, and it was not a
problem to integrate this new ptrace feature.
I have proven with testcases that LLDB can restore
any streaming mode/ZA/streaming vector length
combination, starting from any other combination.
The LLDB changes will remain in review until if/when
these kernel changes are accepted. I expect LLDB
reviewers will be ok approving changes on the condition
that I wait for the kernel side before merging.
I expect LLDB review to take some time, likely a month,
due to the availability of reviewers at this time.
Reviewed-by: David Spickett <david.spickett@linaro.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] kselftst/arm64: Test NT_ARM_SVE FPSIMD format writes on non-SVE systems
2025-10-15 17:56 [PATCH v2 0/3] arm64/sme: Support disabling streaming mode via ptrace on SME only systems Mark Brown
2025-10-15 17:56 ` [PATCH v2 1/3] " Mark Brown
@ 2025-10-15 17:56 ` Mark Brown
2025-10-15 17:56 ` [PATCH v2 3/3] kselftest/arm64: Cover disabling streaming mode without SVE in fp-ptrace Mark Brown
2 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2025-10-15 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan, Jonathan Corbet,
Oleg Nesterov
Cc: Mark Rutland, David Spickett, Thiago Jung Bauermann, Luis Machado,
linux-arm-kernel, linux-kselftest, linux-kernel, linux-doc,
Mark Brown
In order to allow exiting streaming mode on systems with SME but not SVE
we allow writes of FPSIMD format data via NT_ARM_SVE even when SVE is not
supported, add a test case that covers this to sve-ptrace.
We do not support reads.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
tools/testing/selftests/arm64/fp/sve-ptrace.c | 61 +++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/tools/testing/selftests/arm64/fp/sve-ptrace.c b/tools/testing/selftests/arm64/fp/sve-ptrace.c
index e0fc3a001e28..f44d44618575 100644
--- a/tools/testing/selftests/arm64/fp/sve-ptrace.c
+++ b/tools/testing/selftests/arm64/fp/sve-ptrace.c
@@ -394,6 +394,58 @@ static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
free(svebuf);
}
+/* Write the FPSIMD registers via the SVE regset when SVE is not supported */
+static void ptrace_sve_fpsimd_no_sve(pid_t child)
+{
+ void *svebuf;
+ struct user_sve_header *sve;
+ struct user_fpsimd_state *fpsimd, new_fpsimd;
+ unsigned int i, j;
+ unsigned char *p;
+ int ret;
+
+ svebuf = malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
+ if (!svebuf) {
+ ksft_test_result_fail("Failed to allocate FPSIMD buffer\n");
+ return;
+ }
+
+ /* On a system without SVE the VL should be set to 0 */
+ memset(svebuf, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
+ sve = svebuf;
+ sve->flags = SVE_PT_REGS_FPSIMD;
+ sve->size = SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD);
+ sve->vl = 0;
+
+ /* Try to set a known FPSIMD state via PT_REGS_SVE */
+ fpsimd = (struct user_fpsimd_state *)((char *)sve +
+ SVE_PT_FPSIMD_OFFSET);
+ for (i = 0; i < 32; ++i) {
+ p = (unsigned char *)&fpsimd->vregs[i];
+
+ for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
+ p[j] = j;
+ }
+
+ ret = set_sve(child, &vec_types[0], sve);
+ ksft_test_result(ret == 0, "FPSIMD write via SVE\n");
+ if (ret) {
+ ksft_test_result_skip("Verify FPSIMD write via SVE\n");
+ goto out;
+ }
+
+ /* Verify via the FPSIMD regset */
+ if (get_fpsimd(child, &new_fpsimd)) {
+ ksft_test_result_skip("Verify FPSIMD write via SVE\n");
+ goto out;
+ }
+ ksft_test_result(memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0,
+ "Verify FPSIMD write via SVE\n");
+
+out:
+ free(svebuf);
+}
+
/* Validate attempting to set SVE data and read SVE data */
static void ptrace_set_sve_get_sve_data(pid_t child,
const struct vec_type *type,
@@ -826,6 +878,15 @@ static int do_parent(pid_t child)
}
}
+ /* We support SVE writes of FPSMID format on SME only systems */
+ if (!(getauxval(AT_HWCAP) & HWCAP_SVE) &&
+ (getauxval(AT_HWCAP2) & HWCAP2_SME)) {
+ ptrace_sve_fpsimd_no_sve(child);
+ } else {
+ ksft_test_result_skip("FPSIMD write via SVE\n");
+ ksft_test_result_skip("Verify FPSIMD write via SVE\n");
+ }
+
ret = EXIT_SUCCESS;
error:
--
2.47.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v2 3/3] kselftest/arm64: Cover disabling streaming mode without SVE in fp-ptrace
2025-10-15 17:56 [PATCH v2 0/3] arm64/sme: Support disabling streaming mode via ptrace on SME only systems Mark Brown
2025-10-15 17:56 ` [PATCH v2 1/3] " Mark Brown
2025-10-15 17:56 ` [PATCH v2 2/3] kselftst/arm64: Test NT_ARM_SVE FPSIMD format writes on non-SVE systems Mark Brown
@ 2025-10-15 17:56 ` Mark Brown
2 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2025-10-15 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan, Jonathan Corbet,
Oleg Nesterov
Cc: Mark Rutland, David Spickett, Thiago Jung Bauermann, Luis Machado,
linux-arm-kernel, linux-kselftest, linux-kernel, linux-doc,
Mark Brown
On a system which support SME but not SVE we can now disable streaming mode
via ptrace by writing FPSIMD formatted data through NT_ARM_SVE with a VL of
0. Extend fp-ptrace to cover rather than skip these cases, relax the check
for SVE writes of FPSIMD format data to not skip if SME is supported and
accept 0 as the VL when performing the ptrace write.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
tools/testing/selftests/arm64/fp/fp-ptrace.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/tools/testing/selftests/arm64/fp/fp-ptrace.c b/tools/testing/selftests/arm64/fp/fp-ptrace.c
index a85c19e9524e..0114108ab25f 100644
--- a/tools/testing/selftests/arm64/fp/fp-ptrace.c
+++ b/tools/testing/selftests/arm64/fp/fp-ptrace.c
@@ -1071,7 +1071,7 @@ static bool sve_write_supported(struct test_config *config)
static bool sve_write_fpsimd_supported(struct test_config *config)
{
- if (!sve_supported())
+ if (!sve_supported() && !sme_supported())
return false;
if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA))
@@ -1231,9 +1231,6 @@ static void sve_write_fpsimd(pid_t child, struct test_config *config)
vl = vl_expected(config);
vq = __sve_vq_from_vl(vl);
- if (!vl)
- return;
-
iov.iov_len = SVE_PT_SIZE(vq, SVE_PT_REGS_FPSIMD);
iov.iov_base = malloc(iov.iov_len);
if (!iov.iov_base) {
--
2.47.2
^ permalink raw reply related [flat|nested] 5+ messages in thread