[PATCH v2 3/6] arm64/ptrace: Zero FPMR on streaming mode entry/exit
Mark Brown
broonie at kernel.org
Wed Dec 4 07:20:51 PST 2024
When FPMR and SME are both present then entering and exiting streaming mode
clears FPMR in the same manner as it clears the V/Z and P registers.
Since entering and exiting streaming mode via ptrace is expected to have
the same effect as doing so via SMSTART/SMSTOP it should clear FPMR too
but this was missed when FPMR support was added. Add the required reset
of FPMR.
Since changing the vector length resets SVCR a SME vector length change
implemented via a write to ZA can trigger an exit of streaming mode and
we need to check when writing to ZA as well.
Fixes: 4035c22ef7d4 ("arm64/ptrace: Expose FPMR via ptrace")
Signed-off-by: Mark Brown <broonie at kernel.org>
Cc: stable at vger.kernel.org
---
arch/arm64/kernel/ptrace.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index e4437f62a2cda93734052c44b48886db83d75b3e..43a9397d5903ff87b608befdcaed3f9a7e48f976 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -877,6 +877,7 @@ static int sve_set_common(struct task_struct *target,
const void *kbuf, const void __user *ubuf,
enum vec_type type)
{
+ u64 old_svcr = target->thread.svcr;
int ret;
struct user_sve_header header;
unsigned int vq;
@@ -908,8 +909,6 @@ static int sve_set_common(struct task_struct *target,
/* Enter/exit streaming mode */
if (system_supports_sme()) {
- u64 old_svcr = target->thread.svcr;
-
switch (type) {
case ARM64_VEC_SVE:
target->thread.svcr &= ~SVCR_SM_MASK;
@@ -1008,6 +1007,10 @@ static int sve_set_common(struct task_struct *target,
start, end);
out:
+ /* If we entered or exited streaming mode then reset FPMR */
+ if ((target->thread.svcr & SVCR_SM) != (old_svcr & SVCR_SM))
+ target->thread.uw.fpmr = 0;
+
fpsimd_flush_task_state(target);
return ret;
}
@@ -1104,6 +1107,7 @@ static int za_set(struct task_struct *target,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
+ u64 old_svcr = target->thread.svcr;
int ret;
struct user_za_header header;
unsigned int vq;
@@ -1184,6 +1188,10 @@ static int za_set(struct task_struct *target,
target->thread.svcr |= SVCR_ZA_MASK;
out:
+ /* If we entered or exited streaming mode then reset FPMR */
+ if ((target->thread.svcr & SVCR_SM) != (old_svcr & SVCR_SM))
+ target->thread.uw.fpmr = 0;
+
fpsimd_flush_task_state(target);
return ret;
}
--
2.39.5
More information about the linux-arm-kernel
mailing list