Skip to content

Commit 826a4fd

Browse files
brooniewilldeacon
authored andcommitted
arm64/sme: Don't flush SVE register state when allocating SME storage
Currently when taking a SME access trap we allocate storage for the SVE register state in order to be able to handle storage of streaming mode SVE. Due to the original usage in a purely SVE context the SVE register state allocation this also flushes the register state for SVE if storage was already allocated but in the SME context this is not desirable. For a SME access trap to be taken the task must not be in streaming mode so either there already is SVE register state present for regular SVE mode which would be corrupted or the task does not have TIF_SVE and the flush is redundant. Fix this by adding a flag to sve_alloc() indicating if we are in a SVE context and need to flush the state. Freshly allocated storage is always zeroed either way. Fixes: 8bd7f91 ("arm64/sme: Implement traps and syscall handling for SME") Signed-off-by: Mark Brown <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent ea64baa commit 826a4fd

File tree

4 files changed

+12
-10
lines changed

4 files changed

+12
-10
lines changed

arch/arm64/include/asm/fpsimd.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ struct vl_info {
153153

154154
#ifdef CONFIG_ARM64_SVE
155155

156-
extern void sve_alloc(struct task_struct *task);
156+
extern void sve_alloc(struct task_struct *task, bool flush);
157157
extern void fpsimd_release_task(struct task_struct *task);
158158
extern void fpsimd_sync_to_sve(struct task_struct *task);
159159
extern void fpsimd_force_sync_to_sve(struct task_struct *task);
@@ -256,7 +256,7 @@ size_t sve_state_size(struct task_struct const *task);
256256

257257
#else /* ! CONFIG_ARM64_SVE */
258258

259-
static inline void sve_alloc(struct task_struct *task) { }
259+
static inline void sve_alloc(struct task_struct *task, bool flush) { }
260260
static inline void fpsimd_release_task(struct task_struct *task) { }
261261
static inline void sve_sync_to_fpsimd(struct task_struct *task) { }
262262
static inline void sve_sync_from_fpsimd_zeropad(struct task_struct *task) { }

arch/arm64/kernel/fpsimd.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -715,10 +715,12 @@ size_t sve_state_size(struct task_struct const *task)
715715
* do_sve_acc() case, there is no ABI requirement to hide stale data
716716
* written previously be task.
717717
*/
718-
void sve_alloc(struct task_struct *task)
718+
void sve_alloc(struct task_struct *task, bool flush)
719719
{
720720
if (task->thread.sve_state) {
721-
memset(task->thread.sve_state, 0, sve_state_size(task));
721+
if (flush)
722+
memset(task->thread.sve_state, 0,
723+
sve_state_size(task));
722724
return;
723725
}
724726

@@ -1388,7 +1390,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
13881390
return;
13891391
}
13901392

1391-
sve_alloc(current);
1393+
sve_alloc(current, true);
13921394
if (!current->thread.sve_state) {
13931395
force_sig(SIGKILL);
13941396
return;
@@ -1439,7 +1441,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
14391441
return;
14401442
}
14411443

1442-
sve_alloc(current);
1444+
sve_alloc(current, false);
14431445
sme_alloc(current);
14441446
if (!current->thread.sve_state || !current->thread.za_state) {
14451447
force_sig(SIGKILL);

arch/arm64/kernel/ptrace.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ static int sve_set_common(struct task_struct *target,
882882
* state and ensure there's storage.
883883
*/
884884
if (target->thread.svcr != old_svcr)
885-
sve_alloc(target);
885+
sve_alloc(target, true);
886886
}
887887

888888
/* Registers: FPSIMD-only case */
@@ -912,7 +912,7 @@ static int sve_set_common(struct task_struct *target,
912912
goto out;
913913
}
914914

915-
sve_alloc(target);
915+
sve_alloc(target, true);
916916
if (!target->thread.sve_state) {
917917
ret = -ENOMEM;
918918
clear_tsk_thread_flag(target, TIF_SVE);
@@ -1082,7 +1082,7 @@ static int za_set(struct task_struct *target,
10821082

10831083
/* Ensure there is some SVE storage for streaming mode */
10841084
if (!target->thread.sve_state) {
1085-
sve_alloc(target);
1085+
sve_alloc(target, false);
10861086
if (!target->thread.sve_state) {
10871087
clear_thread_flag(TIF_SME);
10881088
ret = -ENOMEM;

arch/arm64/kernel/signal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
310310
fpsimd_flush_task_state(current);
311311
/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
312312

313-
sve_alloc(current);
313+
sve_alloc(current, true);
314314
if (!current->thread.sve_state) {
315315
clear_thread_flag(TIF_SVE);
316316
return -ENOMEM;

0 commit comments

Comments
 (0)