Skip to content

Commit 472800c

Browse files
brooniectmarinas
authored andcommitted
arm64/sme: Support disabling streaming mode via ptrace on SME only systems
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> Reviewed-by: David Spickett <david.spickett@linaro.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 3a86608 commit 472800c

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

Documentation/arch/arm64/sve.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,11 @@ The regset data starts with struct user_sve_header, containing:
402402
streaming mode and any SETREGSET of NT_ARM_SSVE will enter streaming mode
403403
if the target was not in streaming mode.
404404

405+
* On systems that do not support SVE it is permitted to use SETREGSET to
406+
write SVE_PT_REGS_FPSIMD formatted data via NT_ARM_SVE, in this case the
407+
vector length should be specified as 0. This allows streaming mode to be
408+
disabled on systems with SME but not SVE.
409+
405410
* If any register data is provided along with SVE_PT_VL_ONEXEC then the
406411
registers data will be interpreted with the current vector length, not
407412
the vector length configured for use on exec.

arch/arm64/kernel/ptrace.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -912,13 +912,39 @@ static int sve_set_common(struct task_struct *target,
912912
return -EINVAL;
913913

914914
/*
915-
* Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by
916-
* vec_set_vector_length(), which will also validate them for us:
915+
* On systems without SVE we accept FPSIMD format writes with
916+
* a VL of 0 to allow exiting streaming mode, otherwise a VL
917+
* is required.
917918
*/
918-
ret = vec_set_vector_length(target, type, header.vl,
919-
((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16);
920-
if (ret)
921-
return ret;
919+
if (header.vl) {
920+
/*
921+
* If the system does not support SVE we can't
922+
* configure a SVE VL.
923+
*/
924+
if (!system_supports_sve() && type == ARM64_VEC_SVE)
925+
return -EINVAL;
926+
927+
/*
928+
* Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are
929+
* consumed by vec_set_vector_length(), which will
930+
* also validate them for us:
931+
*/
932+
ret = vec_set_vector_length(target, type, header.vl,
933+
((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16);
934+
if (ret)
935+
return ret;
936+
} else {
937+
/* If the system supports SVE we require a VL. */
938+
if (system_supports_sve())
939+
return -EINVAL;
940+
941+
/*
942+
* Only FPSIMD formatted data with no flags set is
943+
* supported.
944+
*/
945+
if (header.flags != SVE_PT_REGS_FPSIMD)
946+
return -EINVAL;
947+
}
922948

923949
/* Allocate SME storage if necessary, preserving any existing ZA/ZT state */
924950
if (type == ARM64_VEC_SME) {
@@ -1016,7 +1042,7 @@ static int sve_set(struct task_struct *target,
10161042
unsigned int pos, unsigned int count,
10171043
const void *kbuf, const void __user *ubuf)
10181044
{
1019-
if (!system_supports_sve())
1045+
if (!system_supports_sve() && !system_supports_sme())
10201046
return -EINVAL;
10211047

10221048
return sve_set_common(target, regset, pos, count, kbuf, ubuf,

0 commit comments

Comments
 (0)