Commit e85d3e9d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull arm64 fixes from Catalin Marinas:

 - A set of fixes for FPSIMD/SVE/SME state management (around signal
   handling and ptrace) where a task can be placed in an invalid state

 - __nocfi added to swsusp_arch_resume() to avoid a data abort on
   resuming from hibernate

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64: Set __nocfi on swsusp_arch_resume()
  arm64/fpsimd: signal: Fix restoration of SVE context
  arm64/fpsimd: signal: Allocate SSVE storage when restoring ZA
  arm64/fpsimd: ptrace: Fix SVE writes on !SME systems
parents 6d064432 e2f8216c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -402,7 +402,7 @@ int swsusp_arch_suspend(void)
 * Memory allocated by get_safe_page() will be dealt with by the hibernate code,
 * we don't need to free it here.
 */
int swsusp_arch_resume(void)
int __nocfi swsusp_arch_resume(void)
{
	int rc;
	void *zero_page;
+12 −14
Original line number Diff line number Diff line
@@ -968,7 +968,6 @@ static int sve_set_common(struct task_struct *target,
	vq = sve_vq_from_vl(task_get_vl(target, type));

	/* Enter/exit streaming mode */
	if (system_supports_sme()) {
	switch (type) {
	case ARM64_VEC_SVE:
		target->thread.svcr &= ~SVCR_SM_MASK;
@@ -982,7 +981,6 @@ static int sve_set_common(struct task_struct *target,
		WARN_ON_ONCE(1);
		return -EINVAL;
	}
	}

	/* Always zero V regs, FPSR, and FPCR */
	memset(&current->thread.uw.fpsimd_state, 0,
+20 −6
Original line number Diff line number Diff line
@@ -449,12 +449,28 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
	if (user->sve_size < SVE_SIG_CONTEXT_SIZE(vq))
		return -EINVAL;

	if (sm) {
		sme_alloc(current, false);
		if (!current->thread.sme_state)
			return -ENOMEM;
	}

	sve_alloc(current, true);
	if (!current->thread.sve_state) {
		clear_thread_flag(TIF_SVE);
		return -ENOMEM;
	}

	if (sm) {
		current->thread.svcr |= SVCR_SM_MASK;
		set_thread_flag(TIF_SME);
	} else {
		current->thread.svcr &= ~SVCR_SM_MASK;
		set_thread_flag(TIF_SVE);
	}

	current->thread.fp_type = FP_STATE_SVE;

	err = __copy_from_user(current->thread.sve_state,
			       (char __user const *)user->sve +
					SVE_SIG_REGS_OFFSET,
@@ -462,12 +478,6 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
	if (err)
		return -EFAULT;

	if (flags & SVE_SIG_FLAG_SM)
		current->thread.svcr |= SVCR_SM_MASK;
	else
		set_thread_flag(TIF_SVE);
	current->thread.fp_type = FP_STATE_SVE;

	err = read_fpsimd_context(&fpsimd, user);
	if (err)
		return err;
@@ -576,6 +586,10 @@ static int restore_za_context(struct user_ctxs *user)
	if (user->za_size < ZA_SIG_CONTEXT_SIZE(vq))
		return -EINVAL;

	sve_alloc(current, false);
	if (!current->thread.sve_state)
		return -ENOMEM;

	sme_alloc(current, true);
	if (!current->thread.sme_state) {
		current->thread.svcr &= ~SVCR_ZA_MASK;