Commit d4ddefee authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fixes from Catalin Marinas:
 "Two more SME fixes related to ptrace(): ensure that the SME is
  properly set up for the target thread and that the thread sees
  the ZT registers set via ptrace"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64/ptrace: Ensure that the task sees ZT writes on first use
  arm64/ptrace: Ensure that SME is set up for target when writing SSVE state
parents 3e13eee1 2f43f549
...@@ -356,7 +356,7 @@ static inline int sme_max_virtualisable_vl(void) ...@@ -356,7 +356,7 @@ static inline int sme_max_virtualisable_vl(void)
return vec_max_virtualisable_vl(ARM64_VEC_SME); return vec_max_virtualisable_vl(ARM64_VEC_SME);
} }
extern void sme_alloc(struct task_struct *task); extern void sme_alloc(struct task_struct *task, bool flush);
extern unsigned int sme_get_vl(void); extern unsigned int sme_get_vl(void);
extern int sme_set_current_vl(unsigned long arg); extern int sme_set_current_vl(unsigned long arg);
extern int sme_get_current_vl(void); extern int sme_get_current_vl(void);
...@@ -388,7 +388,7 @@ static inline void sme_smstart_sm(void) { } ...@@ -388,7 +388,7 @@ static inline void sme_smstart_sm(void) { }
static inline void sme_smstop_sm(void) { } static inline void sme_smstop_sm(void) { }
static inline void sme_smstop(void) { } static inline void sme_smstop(void) { }
static inline void sme_alloc(struct task_struct *task) { } static inline void sme_alloc(struct task_struct *task, bool flush) { }
static inline void sme_setup(void) { } static inline void sme_setup(void) { }
static inline unsigned int sme_get_vl(void) { return 0; } static inline unsigned int sme_get_vl(void) { return 0; }
static inline int sme_max_vl(void) { return 0; } static inline int sme_max_vl(void) { return 0; }
......
...@@ -1285,9 +1285,9 @@ void fpsimd_release_task(struct task_struct *dead_task) ...@@ -1285,9 +1285,9 @@ void fpsimd_release_task(struct task_struct *dead_task)
* the interest of testability and predictability, the architecture * the interest of testability and predictability, the architecture
* guarantees that when ZA is enabled it will be zeroed. * guarantees that when ZA is enabled it will be zeroed.
*/ */
void sme_alloc(struct task_struct *task) void sme_alloc(struct task_struct *task, bool flush)
{ {
if (task->thread.sme_state) { if (task->thread.sme_state && flush) {
memset(task->thread.sme_state, 0, sme_state_size(task)); memset(task->thread.sme_state, 0, sme_state_size(task));
return; return;
} }
...@@ -1515,7 +1515,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs) ...@@ -1515,7 +1515,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
} }
sve_alloc(current, false); sve_alloc(current, false);
sme_alloc(current); sme_alloc(current, true);
if (!current->thread.sve_state || !current->thread.sme_state) { if (!current->thread.sve_state || !current->thread.sme_state) {
force_sig(SIGKILL); force_sig(SIGKILL);
return; return;
......
...@@ -881,6 +881,13 @@ static int sve_set_common(struct task_struct *target, ...@@ -881,6 +881,13 @@ static int sve_set_common(struct task_struct *target,
break; break;
case ARM64_VEC_SME: case ARM64_VEC_SME:
target->thread.svcr |= SVCR_SM_MASK; target->thread.svcr |= SVCR_SM_MASK;
/*
* Disable traps and ensure there is SME storage but
* preserve any currently set values in ZA/ZT.
*/
sme_alloc(target, false);
set_tsk_thread_flag(target, TIF_SME);
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
...@@ -1100,7 +1107,7 @@ static int za_set(struct task_struct *target, ...@@ -1100,7 +1107,7 @@ static int za_set(struct task_struct *target,
} }
/* Allocate/reinit ZA storage */ /* Allocate/reinit ZA storage */
sme_alloc(target); sme_alloc(target, true);
if (!target->thread.sme_state) { if (!target->thread.sme_state) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -1170,8 +1177,13 @@ static int zt_set(struct task_struct *target, ...@@ -1170,8 +1177,13 @@ static int zt_set(struct task_struct *target,
if (!system_supports_sme2()) if (!system_supports_sme2())
return -EINVAL; return -EINVAL;
/* Ensure SVE storage in case this is first use of SME */
sve_alloc(target, false);
if (!target->thread.sve_state)
return -ENOMEM;
if (!thread_za_enabled(&target->thread)) { if (!thread_za_enabled(&target->thread)) {
sme_alloc(target); sme_alloc(target, true);
if (!target->thread.sme_state) if (!target->thread.sme_state)
return -ENOMEM; return -ENOMEM;
} }
...@@ -1179,8 +1191,10 @@ static int zt_set(struct task_struct *target, ...@@ -1179,8 +1191,10 @@ static int zt_set(struct task_struct *target,
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
thread_zt_state(&target->thread), thread_zt_state(&target->thread),
0, ZT_SIG_REG_BYTES); 0, ZT_SIG_REG_BYTES);
if (ret == 0) if (ret == 0) {
target->thread.svcr |= SVCR_ZA_MASK; target->thread.svcr |= SVCR_ZA_MASK;
set_tsk_thread_flag(target, TIF_SME);
}
fpsimd_flush_task_state(target); fpsimd_flush_task_state(target);
......
...@@ -475,7 +475,7 @@ static int restore_za_context(struct user_ctxs *user) ...@@ -475,7 +475,7 @@ static int restore_za_context(struct user_ctxs *user)
fpsimd_flush_task_state(current); fpsimd_flush_task_state(current);
/* From now, fpsimd_thread_switch() won't touch thread.sve_state */ /* From now, fpsimd_thread_switch() won't touch thread.sve_state */
sme_alloc(current); sme_alloc(current, true);
if (!current->thread.sme_state) { if (!current->thread.sme_state) {
current->thread.svcr &= ~SVCR_ZA_MASK; current->thread.svcr &= ~SVCR_ZA_MASK;
clear_thread_flag(TIF_SME); clear_thread_flag(TIF_SME);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment