Commit d4ddefee authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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; }
+3 −3
Original line number Diff line number Diff line
@@ -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;
+17 −3
Original line number Diff line number Diff line
@@ -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);

+1 −1
Original line number Diff line number Diff line
@@ -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);