Commit 8738288a authored by Mark Rutland's avatar Mark Rutland Committed by Will Deacon
Browse files

arm64/fpsimd: Factor out {sve,sme}_state_size() helpers



In subsequent patches we'll need to determine the SVE/SME state size for
a given SVE VL and SME VL regardless of whether a task is currently
configured with those VLs. Split the sizing logic out of
sve_state_size() and sme_state_size() so that we don't need to open-code
this logic elsewhere.

At the same time, apply minor cleanups:

* Move sve_state_size() into fpsimd.h, matching the placement of
  sme_state_size().

* Remove the feature checks from sve_state_size(). We only call
  sve_state_size() when at least one of SVE and SME are supported, and
  when either of the two is not supported, the task's corresponding
  SVE/SME vector length will be zero.

Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20250508132644.1395904-8-mark.rutland@arm.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent b255be42
Loading
Loading
Loading
Loading
+37 −10
Original line number Diff line number Diff line
@@ -293,7 +293,22 @@ static inline bool sve_vq_available(unsigned int vq)
	return vq_available(ARM64_VEC_SVE, vq);
}

size_t sve_state_size(struct task_struct const *task);
static inline size_t __sve_state_size(unsigned int sve_vl, unsigned int sme_vl)
{
	unsigned int vl = max(sve_vl, sme_vl);
	return SVE_SIG_REGS_SIZE(sve_vq_from_vl(vl));
}

/*
 * Return how many bytes of memory are required to store the full SVE
 * state for task, given task's currently configured vector length.
 */
static inline size_t sve_state_size(struct task_struct const *task)
{
	unsigned int sve_vl = task_get_sve_vl(task);
	unsigned int sme_vl = task_get_sme_vl(task);
	return __sve_state_size(sve_vl, sme_vl);
}

#else /* ! CONFIG_ARM64_SVE */

@@ -334,6 +349,11 @@ static inline void vec_update_vq_map(enum vec_type t) { }
static inline int vec_verify_vq_map(enum vec_type t) { return 0; }
static inline void sve_setup(void) { }

static inline size_t __sve_state_size(unsigned int sve_vl, unsigned int sme_vl)
{
	return 0;
}

static inline size_t sve_state_size(struct task_struct const *task)
{
	return 0;
@@ -386,6 +406,16 @@ extern int sme_set_current_vl(unsigned long arg);
extern int sme_get_current_vl(void);
extern void sme_suspend_exit(void);

static inline size_t __sme_state_size(unsigned int sme_vl)
{
	size_t size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(sme_vl));

	if (system_supports_sme2())
		size += ZT_SIG_REG_SIZE;

	return size;
}

/*
 * Return how many bytes of memory are required to store the full SME
 * specific state for task, given task's currently configured vector
@@ -393,15 +423,7 @@ extern void sme_suspend_exit(void);
 */
static inline size_t sme_state_size(struct task_struct const *task)
{
	unsigned int vl = task_get_sme_vl(task);
	size_t size;

	size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl));

	if (system_supports_sme2())
		size += ZT_SIG_REG_SIZE;

	return size;
	return __sme_state_size(task_get_sme_vl(task));
}

#else
@@ -422,6 +444,11 @@ static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; }
static inline int sme_get_current_vl(void) { return -EINVAL; }
static inline void sme_suspend_exit(void) { }

static inline size_t __sme_state_size(unsigned int sme_vl)
{
	return 0;
}

static inline size_t sme_state_size(struct task_struct const *task)
{
	return 0;
+0 −16
Original line number Diff line number Diff line
@@ -719,22 +719,6 @@ static void sve_free(struct task_struct *task)
	__sve_free(task);
}

/*
 * Return how many bytes of memory are required to store the full SVE
 * state for task, given task's currently configured vector length.
 */
size_t sve_state_size(struct task_struct const *task)
{
	unsigned int vl = 0;

	if (system_supports_sve())
		vl = task_get_sve_vl(task);
	if (system_supports_sme())
		vl = max(vl, task_get_sme_vl(task));

	return SVE_SIG_REGS_SIZE(sve_vq_from_vl(vl));
}

/*
 * Ensure that task->thread.sve_state is allocated and sufficiently large.
 *