[PATCH 2/3] arm64: ptrace: Simplify sve_set_common() SME-only logic

Mark Rutland mark.rutland at arm.com
Tue Nov 3 04:13:45 PST 2026


When SME is supported but SVE is not supported, sve_set_common() permits
some writes to NT_ARM_SVE so that a tracer can take a tracee out of
streaming mode. Such writes are only permitted when the data is in
FPSIMD format, and header.flags is 0, and header.vl is 0. Logic was
added to permit this (with no other intentional changes) in commit:

  472800cd5e38 ("arm64/sme: Support disabling streaming mode via ptrace on SME only system")

While this logic is correct, it is convoluted, and can be simplified.
Importantly, regardless of the changes from that commit:

(1) vec_set_vector_length() always rejects VL==0, and returns -EINVAL.
    It has always done so, as sve_vl_valid(0) is always false.

(2) sve_set_common() always rejects writes to NT_ARM_SME in FPSIMD
    format, and returns -EINVAL. This has been the case since commit:

    f916dd32a943 ("arm64/fpsimd: ptrace: Mandate SVE payload for streaming-mode state")

    That commit has been backported to all upstream stable kernels which
    support SME.

Given this, it is significantly simpler to have an explicit special case
for writes to NT_ARM_SVE when SVE is not supported. The is the only case
where VL is permitted (and required) to be zero. In all other cases, the
existing logic from before commit 472800cd5e38 is sufficient.

Treat SME-only configurations as an explicit special case, and clarify
the comments.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Mark Brown <broonie at kernel.org>
Cc: Will Deacon <will at kernel.org>
---
 arch/arm64/kernel/ptrace.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 7405c76724bfe..7052d7f751446 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -962,18 +962,17 @@ static int sve_set_common(struct task_struct *target,
 		return -EINVAL;
 
 	/*
-	 * On systems without SVE we accept FPSIMD format writes with
-	 * a VL of 0 to allow exiting streaming mode, otherwise a VL
-	 * is required.
+	 * On systems with SME but not SVE, accept writes to NT_ARM_SVE if and
+	 * only if VL==0 and data is in FPSIMD format and no flags are set.
+	 * This permits exiting streaming mode, and avoids the possibility of
+	 * creating non-streaming SVE state.
 	 */
-	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)
+	if (!system_supports_sve() && type == ARM64_VEC_SVE) {
+		if (header.vl)
 			return -EINVAL;
-
+		if (header.flags != SVE_PT_REGS_FPSIMD)
+			return -EINVAL;
+	} else {
 		/*
 		 * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are
 		 * consumed by vec_set_vector_length(), which will
@@ -983,17 +982,6 @@ static int sve_set_common(struct task_struct *target,
 					    ((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 */
-- 
2.30.2




More information about the linux-arm-kernel mailing list