Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
Subject: Re: [PATCH 5.15 v2 03/10] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE
Date: Thu,  3 Apr 2025 11:38:35 -0400	[thread overview]
Message-ID: <20250403095427-6690dadd0b0b61dc@stable.kernel.org> (raw)
In-Reply-To: <20250403-stable-sve-5-15-v2-3-30a36a78a20a@kernel.org>

[ Sasha's backport helper bot ]

Hi,

✅ All tests passed successfully. No issues detected.
No action required from the submitter.

The upstream commit SHA1 provided is correct: baa8515281b30861cff3da7db70662d2a25c6440

Status in newer kernel trees:
6.13.y | Present (exact SHA1)
6.12.y | Present (exact SHA1)
6.6.y | Present (exact SHA1)
6.1.y | Not found

Note: The patch differs from the upstream commit:
---
1:  baa8515281b30 ! 1:  e5d18d62553b8 arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE
    @@ Metadata
      ## Commit message ##
         arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE
     
    +    [ Upstream commit baa8515281b30861cff3da7db70662d2a25c6440 ]
    +
         When we save the state for the floating point registers this can be done
         in the form visible through either the FPSIMD V registers or the SVE Z and
         P registers. At present we track which format is currently used based on
    @@ Commit message
         Reviewed-by: Marc Zyngier <maz@kernel.org>
         Link: https://lore.kernel.org/r/20221115094640.112848-3-broonie@kernel.org
         Signed-off-by: Will Deacon <will@kernel.org>
    +    [ Mark: fix conflicts due to earlier backports ]
    +    Signed-off-by: Mark Rutland <mark.rutland@arm.com>
    +    Signed-off-by: Mark Brown <broonie@kernel.org>
     
      ## arch/arm64/include/asm/fpsimd.h ##
    -@@ arch/arm64/include/asm/fpsimd.h: extern void fpsimd_kvm_prepare(void);
    +@@ arch/arm64/include/asm/fpsimd.h: extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
    + extern void fpsimd_kvm_prepare(void);
    + 
      extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
    - 				     void *sve_state, unsigned int sve_vl,
    - 				     void *za_state, unsigned int sme_vl,
    --				     u64 *svcr);
    -+				     u64 *svcr, enum fp_type *type);
    +-				     void *sve_state, unsigned int sve_vl);
    ++				     void *sve_state, unsigned int sve_vl,
    ++				     enum fp_type *type);
      
      extern void fpsimd_flush_task_state(struct task_struct *target);
      extern void fpsimd_save_and_flush_cpu_state(void);
     
      ## arch/arm64/include/asm/kvm_host.h ##
     @@ arch/arm64/include/asm/kvm_host.h: struct vcpu_reset_state {
    + 
      struct kvm_vcpu_arch {
      	struct kvm_cpu_context ctxt;
    - 
    --	/* Guest floating point state */
    ++
     +	/*
     +	 * Guest floating point state
     +	 *
    @@ arch/arm64/include/asm/kvm_host.h: struct vcpu_reset_state {
      	void *sve_state;
     +	enum fp_type fp_type;
      	unsigned int sve_max_vl;
    - 	u64 svcr;
      
    + 	/* Stage 2 paging state used by the hardware on next switch */
     
      ## arch/arm64/include/asm/processor.h ##
    -@@ arch/arm64/include/asm/processor.h: enum vec_type {
    - 	ARM64_VEC_MAX,
    +@@ arch/arm64/include/asm/processor.h: struct debug_info {
    + #endif
      };
      
     +enum fp_type {
    @@ arch/arm64/include/asm/processor.h: struct thread_struct {
     +	enum fp_type		fp_type;	/* registers FPSIMD or SVE? */
      	unsigned int		fpsimd_cpu;
      	void			*sve_state;	/* SVE registers, if any */
    - 	void			*za_state;	/* ZA register, if any */
    + 	unsigned int		sve_vl;		/* SVE vector length */
     
      ## arch/arm64/kernel/fpsimd.c ##
     @@ arch/arm64/kernel/fpsimd.c: struct fpsimd_last_state_struct {
    - 	u64 *svcr;
    + 	struct user_fpsimd_state *st;
    + 	void *sve_state;
      	unsigned int sve_vl;
    - 	unsigned int sme_vl;
     +	enum fp_type *fp_type;
      };
      
      static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
    -@@ arch/arm64/kernel/fpsimd.c: void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
    +@@ arch/arm64/kernel/fpsimd.c: static void sve_free(struct task_struct *task)
       *    The task can execute SVE instructions while in userspace without
       *    trapping to the kernel.
       *
     - *    When stored, Z0-Z31 (incorporating Vn in bits[127:0] or the
    -- *    corresponding Zn), P0-P15 and FFR are encoded in
    +- *    corresponding Zn), P0-P15 and FFR are encoded in in
     - *    task->thread.sve_state, formatted appropriately for vector
    -- *    length task->thread.sve_vl or, if SVCR.SM is set,
    -- *    task->thread.sme_vl.
    +- *    length task->thread.sve_vl.
     - *
     - *    task->thread.sve_state must point to a valid buffer at least
     - *    sve_state_size(task) bytes in size.
    @@ arch/arm64/kernel/fpsimd.c: void task_set_vl_onexec(struct task_struct *task, en
       *    During any syscall, the kernel may optionally clear TIF_SVE and
       *    discard the vector state except for the FPSIMD subset.
       *
    -@@ arch/arm64/kernel/fpsimd.c: void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
    +@@ arch/arm64/kernel/fpsimd.c: static void sve_free(struct task_struct *task)
       *    do_sve_acc() to be called, which does some preparation and then
       *    sets TIF_SVE.
       *
    @@ arch/arm64/kernel/fpsimd.c: void task_set_vl_onexec(struct task_struct *task, en
       *    task->thread.uw.fpsimd_state; bits [max : 128] for each of Z0-Z31 are
       *    logically zero but not stored anywhere; P0-P15 and FFR are not
       *    stored and have unspecified values from userspace's point of
    -@@ arch/arm64/kernel/fpsimd.c: void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
    +@@ arch/arm64/kernel/fpsimd.c: static void sve_free(struct task_struct *task)
       *    task->thread.sve_state does not need to be non-NULL, valid or any
       *    particular size: it must not be dereferenced.
       *
    @@ arch/arm64/kernel/fpsimd.c: void task_set_vl_onexec(struct task_struct *task, en
       *    irrespective of whether TIF_SVE is clear or set, since these are
       *    not vector length dependent.
     @@ arch/arm64/kernel/fpsimd.c: static void task_fpsimd_load(void)
    - 		}
    - 	}
    + 	WARN_ON(!system_supports_fpsimd());
    + 	WARN_ON(!have_cpu_fpsimd_context());
      
    --	if (restore_sve_regs)
    -+	if (restore_sve_regs) {
    +-	if (IS_ENABLED(CONFIG_ARM64_SVE) && test_thread_flag(TIF_SVE))
    ++	if (IS_ENABLED(CONFIG_ARM64_SVE) && test_thread_flag(TIF_SVE)) {
     +		WARN_ON_ONCE(current->thread.fp_type != FP_STATE_SVE);
      		sve_load_state(sve_pffr(&current->thread),
      			       &current->thread.uw.fpsimd_state.fpsr,
    - 			       restore_ffr);
    + 			       sve_vq_from_vl(current->thread.sve_vl) - 1);
     -	else
     +	} else {
     +		WARN_ON_ONCE(current->thread.fp_type != FP_STATE_FPSIMD);
    @@ arch/arm64/kernel/fpsimd.c: static void task_fpsimd_load(void)
      
      /*
     @@ arch/arm64/kernel/fpsimd.c: static void fpsimd_save(void)
    - 		sve_save_state((char *)last->sve_state +
    - 					sve_ffr_offset(vl),
    - 			       &last->st->fpsr, save_ffr);
    -+		*last->fp_type = FP_STATE_SVE;
    - 	} else {
    - 		fpsimd_save_state(last->st);
    -+		*last->fp_type = FP_STATE_FPSIMD;
    + 			sve_save_state((char *)last->sve_state +
    + 						sve_ffr_offset(last->sve_vl),
    + 				       &last->st->fpsr);
    +-		} else
    ++			*last->fp_type = FP_STATE_SVE;
    ++		} else {
    + 			fpsimd_save_state(last->st);
    ++			*last->fp_type = FP_STATE_FPSIMD;
    ++		}
      	}
      }
      
    -@@ arch/arm64/kernel/fpsimd.c: int vec_set_vector_length(struct task_struct *task, enum vec_type type,
    +@@ arch/arm64/kernel/fpsimd.c: int sve_set_vector_length(struct task_struct *task,
    + 	}
      
      	fpsimd_flush_task_state(task);
    - 	if (test_and_clear_tsk_thread_flag(task, TIF_SVE) ||
    --	    thread_sm_enabled(&task->thread))
    -+	    thread_sm_enabled(&task->thread)) {
    +-	if (test_and_clear_tsk_thread_flag(task, TIF_SVE))
    ++	if (test_and_clear_tsk_thread_flag(task, TIF_SVE)) {
      		sve_to_fpsimd(task);
     +		task->thread.fp_type = FP_STATE_FPSIMD;
     +	}
      
    - 	if (system_supports_sme() && type == ARM64_VEC_SME) {
    - 		task->thread.svcr &= ~(SVCR_SM_MASK |
    -@@ arch/arm64/kernel/fpsimd.c: static void sve_init_regs(void)
    - 		fpsimd_bind_task_to_cpu();
    - 	} else {
    - 		fpsimd_to_sve(current);
    -+		current->thread.fp_type = FP_STATE_SVE;
    - 	}
    - }
    - 
    + 	if (task == current)
    + 		put_cpu_fpsimd_context();
     @@ arch/arm64/kernel/fpsimd.c: void fpsimd_flush_thread(void)
    - 		current->thread.svcr = 0;
    + 			current->thread.sve_vl_onexec = 0;
      	}
      
     +	current->thread.fp_type = FP_STATE_FPSIMD;
     +
      	put_cpu_fpsimd_context();
    - 	kfree(sve_state);
    - 	kfree(za_state);
    + }
    + 
     @@ arch/arm64/kernel/fpsimd.c: void fpsimd_kvm_prepare(void)
      	 */
      	get_cpu_fpsimd_context();
    @@ arch/arm64/kernel/fpsimd.c: void fpsimd_kvm_prepare(void)
      	put_cpu_fpsimd_context();
      }
     @@ arch/arm64/kernel/fpsimd.c: static void fpsimd_bind_task_to_cpu(void)
    - 	last->sve_vl = task_get_sve_vl(current);
    - 	last->sme_vl = task_get_sme_vl(current);
    - 	last->svcr = &current->thread.svcr;
    + 	last->st = &current->thread.uw.fpsimd_state;
    + 	last->sve_state = current->thread.sve_state;
    + 	last->sve_vl = current->thread.sve_vl;
     +	last->fp_type = &current->thread.fp_type;
      	current->thread.fpsimd_cpu = smp_processor_id();
      
    - 	/*
    + 	if (system_supports_sve()) {
     @@ arch/arm64/kernel/fpsimd.c: static void fpsimd_bind_task_to_cpu(void)
    + }
      
      void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
    - 			      unsigned int sve_vl, void *za_state,
    --			      unsigned int sme_vl, u64 *svcr)
    -+			      unsigned int sme_vl, u64 *svcr,
    -+			      enum fp_type *type)
    +-			      unsigned int sve_vl)
    ++			      unsigned int sve_vl, enum fp_type *type)
      {
      	struct fpsimd_last_state_struct *last =
      		this_cpu_ptr(&fpsimd_last_state);
     @@ arch/arm64/kernel/fpsimd.c: void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
    - 	last->za_state = za_state;
    + 	last->st = st;
    + 	last->sve_state = sve_state;
      	last->sve_vl = sve_vl;
    - 	last->sme_vl = sme_vl;
     +	last->fp_type = type;
      }
      
    @@ arch/arm64/kernel/fpsimd.c: void fpsimd_bind_state_to_cpu(struct user_fpsimd_sta
     
      ## arch/arm64/kernel/process.c ##
     @@ arch/arm64/kernel/process.c: int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
    - 		clear_tsk_thread_flag(dst, TIF_SME);
    - 	}
    + 	dst->thread.sve_state = NULL;
    + 	clear_tsk_thread_flag(dst, TIF_SVE);
      
    ++
     +	dst->thread.fp_type = FP_STATE_FPSIMD;
     +
      	/* clear any pending asynchronous tag fault raised by the parent */
    @@ arch/arm64/kernel/process.c: int arch_dup_task_struct(struct task_struct *dst, s
      
     
      ## arch/arm64/kernel/ptrace.c ##
    -@@ arch/arm64/kernel/ptrace.c: static int sve_set_common(struct task_struct *target,
    +@@ arch/arm64/kernel/ptrace.c: static int sve_set(struct task_struct *target,
    + 		ret = __fpr_set(target, regset, pos, count, kbuf, ubuf,
    + 				SVE_PT_FPSIMD_OFFSET);
      		clear_tsk_thread_flag(target, TIF_SVE);
    - 		if (type == ARM64_VEC_SME)
    - 			fpsimd_force_sync_to_sve(target);
     +		target->thread.fp_type = FP_STATE_FPSIMD;
      		goto out;
      	}
      
    -@@ arch/arm64/kernel/ptrace.c: static int sve_set_common(struct task_struct *target,
    +@@ arch/arm64/kernel/ptrace.c: static int sve_set(struct task_struct *target,
      	if (!target->thread.sve_state) {
      		ret = -ENOMEM;
      		clear_tsk_thread_flag(target, TIF_SVE);
    @@ arch/arm64/kernel/ptrace.c: static int sve_set_common(struct task_struct *target
      		goto out;
      	}
      
    -@@ arch/arm64/kernel/ptrace.c: static int sve_set_common(struct task_struct *target,
    +@@ arch/arm64/kernel/ptrace.c: static int sve_set(struct task_struct *target,
      	 */
      	fpsimd_sync_to_sve(target);
      	set_tsk_thread_flag(target, TIF_SVE);
    @@ arch/arm64/kernel/signal.c: static int restore_fpsimd_context(struct fpsimd_cont
      	/* load the hardware registers from the fpsimd_state structure */
      	if (!err)
     @@ arch/arm64/kernel/signal.c: static int restore_sve_fpsimd_context(struct user_ctxs *user)
    + 
      	if (sve.head.size <= sizeof(*user->sve)) {
      		clear_thread_flag(TIF_SVE);
    - 		current->thread.svcr &= ~SVCR_SM_MASK;
     +		current->thread.fp_type = FP_STATE_FPSIMD;
      		goto fpsimd_only;
      	}
      
     @@ arch/arm64/kernel/signal.c: static int restore_sve_fpsimd_context(struct user_ctxs *user)
    - 		current->thread.svcr |= SVCR_SM_MASK;
    - 	else
    - 		set_thread_flag(TIF_SVE);
    + 		return -EFAULT;
    + 
    + 	set_thread_flag(TIF_SVE);
     +	current->thread.fp_type = FP_STATE_SVE;
      
      fpsimd_only:
      	/* copy the FP and status/control registers */
    -@@ arch/arm64/kernel/signal.c: static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
    - 		 * FPSIMD register state - flush the saved FPSIMD
    - 		 * register state in case it gets loaded.
    - 		 */
    --		if (current->thread.svcr & SVCR_SM_MASK)
    -+		if (current->thread.svcr & SVCR_SM_MASK) {
    - 			memset(&current->thread.uw.fpsimd_state, 0,
    - 			       sizeof(current->thread.uw.fpsimd_state));
    -+			current->thread.fp_type = FP_STATE_FPSIMD;
    -+		}
    - 
    - 		current->thread.svcr &= ~(SVCR_ZA_MASK |
    - 					  SVCR_SM_MASK);
     
      ## arch/arm64/kvm/fpsimd.c ##
     @@ arch/arm64/kvm/fpsimd.c: void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
    + 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
      		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.fp_regs,
      					 vcpu->arch.sve_state,
    - 					 vcpu->arch.sve_max_vl,
    --					 NULL, 0, &vcpu->arch.svcr);
    -+					 NULL, 0, &vcpu->arch.svcr,
    +-					 vcpu->arch.sve_max_vl);
    ++					 vcpu->arch.sve_max_vl,
     +					 &vcpu->arch.fp_type);
      
      		clear_thread_flag(TIF_FOREIGN_FPSTATE);
---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-6.1.y        |  Success    |  Success   |

  reply	other threads:[~2025-04-03 15:38 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-02 23:20 [PATCH 5.15 v2 00/10] KVM: arm64: Backport of SVE fixes to v5.15 Mark Brown
2025-04-02 23:20 ` [PATCH 5.15 v2 01/10] KVM: arm64: Get rid of host SVE tracking/saving Mark Brown
2025-04-03 15:38   ` Sasha Levin
2025-04-03 16:04     ` Mark Brown
2025-04-03 16:10     ` Mark Brown
2025-04-02 23:20 ` [PATCH 5.15 v2 02/10] KVM: arm64: Discard any SVE state when entering KVM guests Mark Brown
2025-04-03 15:39   ` Sasha Levin
2025-04-03 16:27     ` Mark Brown
2025-04-02 23:20 ` [PATCH 5.15 v2 03/10] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE Mark Brown
2025-04-03 15:38   ` Sasha Levin [this message]
2025-04-02 23:20 ` [PATCH 5.15 v2 04/10] arm64/fpsimd: Have KVM explicitly say which FP registers to save Mark Brown
2025-04-03 15:39   ` Sasha Levin
2025-04-02 23:20 ` [PATCH 5.15 v2 05/10] arm64/fpsimd: Stop using TIF_SVE to manage register saving in KVM Mark Brown
2025-04-03 15:38   ` Sasha Levin
2025-04-02 23:20 ` [PATCH 5.15 v2 06/10] KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state Mark Brown
2025-04-03 15:39   ` Sasha Levin
2025-04-02 23:20 ` [PATCH 5.15 v2 07/10] KVM: arm64: Remove host FPSIMD saving for non-protected KVM Mark Brown
2025-04-03 15:39   ` Sasha Levin
2025-04-02 23:20 ` [PATCH 5.15 v2 08/10] KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN Mark Brown
2025-04-03 15:38   ` Sasha Levin
2025-04-02 23:20 ` [PATCH 5.15 v2 09/10] KVM: arm64: Calculate cptr_el2 traps on activating traps Mark Brown
2025-04-03 15:38   ` Sasha Levin
2025-04-02 23:20 ` [PATCH 5.15 v2 10/10] KVM: arm64: Eagerly switch ZCR_EL{1,2} Mark Brown
2025-04-03 15:39   ` Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250403095427-6690dadd0b0b61dc@stable.kernel.org \
    --to=sashal@kernel.org \
    --cc=broonie@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox