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
This commit is contained in:
@@ -356,7 +356,7 @@ static inline int sme_max_virtualisable_vl(void)
|
||||
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 int sme_set_current_vl(unsigned long arg);
|
||||
extern int sme_get_current_vl(void);
|
||||
@@ -388,7 +388,7 @@ static inline void sme_smstart_sm(void) { }
|
||||
static inline void sme_smstop_sm(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 unsigned int sme_get_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)
|
||||
* the interest of testability and predictability, the architecture
|
||||
* 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));
|
||||
return;
|
||||
}
|
||||
@@ -1515,7 +1515,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
sve_alloc(current, false);
|
||||
sme_alloc(current);
|
||||
sme_alloc(current, true);
|
||||
if (!current->thread.sve_state || !current->thread.sme_state) {
|
||||
force_sig(SIGKILL);
|
||||
return;
|
||||
|
||||
@@ -881,6 +881,13 @@ static int sve_set_common(struct task_struct *target,
|
||||
break;
|
||||
case ARM64_VEC_SME:
|
||||
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;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
@@ -1100,7 +1107,7 @@ static int za_set(struct task_struct *target,
|
||||
}
|
||||
|
||||
/* Allocate/reinit ZA storage */
|
||||
sme_alloc(target);
|
||||
sme_alloc(target, true);
|
||||
if (!target->thread.sme_state) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
@@ -1170,8 +1177,13 @@ static int zt_set(struct task_struct *target,
|
||||
if (!system_supports_sme2())
|
||||
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)) {
|
||||
sme_alloc(target);
|
||||
sme_alloc(target, true);
|
||||
if (!target->thread.sme_state)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -1179,8 +1191,10 @@ static int zt_set(struct task_struct *target,
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
thread_zt_state(&target->thread),
|
||||
0, ZT_SIG_REG_BYTES);
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
target->thread.svcr |= SVCR_ZA_MASK;
|
||||
set_tsk_thread_flag(target, TIF_SME);
|
||||
}
|
||||
|
||||
fpsimd_flush_task_state(target);
|
||||
|
||||
|
||||
@@ -475,7 +475,7 @@ static int restore_za_context(struct user_ctxs *user)
|
||||
fpsimd_flush_task_state(current);
|
||||
/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
|
||||
|
||||
sme_alloc(current);
|
||||
sme_alloc(current, true);
|
||||
if (!current->thread.sme_state) {
|
||||
current->thread.svcr &= ~SVCR_ZA_MASK;
|
||||
clear_thread_flag(TIF_SME);
|
||||
|
||||
Reference in New Issue
Block a user