[PATCH v12 04/29] arm64/sve: Factor virtualizable VL discovery out of SVE specific code

From: Mark Brown

Date: Thu Jul 09 2026 - 14:43:15 EST


In preparation for reuising it for SME pull the code for discovering the
maximum virtualizable vector length out of sve_setup() into a separate
function.

Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
---
arch/arm64/kernel/fpsimd.c | 41 ++++++++++++++++++++++++-----------------
1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index dc1ad10e39a2..5c156e2a47ea 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1114,6 +1114,29 @@ int vec_verify_vq_map(enum vec_type type)
return 0;
}

+static int vec_virtualisable_vl(struct vl_info *info)
+{
+ DECLARE_BITMAP(partial_only_map, SVE_VQ_MAX);
+ unsigned long b_min_partial, b_max_virt;
+
+ bitmap_andnot(partial_only_map, info->vq_partial_map, info->vq_map,
+ SVE_VQ_MAX);
+ b_min_partial = find_last_bit(partial_only_map, SVE_VQ_MAX);
+
+ /* All implemented VLs are virtualisable */
+ if (b_min_partial >= SVE_VQ_MAX)
+ return info->max_vl;
+
+ b_max_virt = find_next_bit(info->vq_map, SVE_VQ_MAX, b_min_partial);
+
+ /* No implemented VLs are virtualisable */
+ if (b_max_virt >= SVE_VQ_MAX)
+ return 0;
+
+ /* At least one virtualisable VL exists */
+ return sve_vl_from_vq(__bit_to_vq(b_max_virt));
+}
+
void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)
{
write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
@@ -1125,8 +1148,6 @@ void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)
void __init sve_setup(void)
{
struct vl_info *info = &vl_info[ARM64_VEC_SVE];
- DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
- unsigned long b;
int max_bit;

if (!system_supports_sve())
@@ -1149,21 +1170,7 @@ void __init sve_setup(void)
*/
set_sve_default_vl(find_supported_vector_length(ARM64_VEC_SVE, 64));

- bitmap_andnot(tmp_map, info->vq_partial_map, info->vq_map,
- SVE_VQ_MAX);
-
- b = find_last_bit(tmp_map, SVE_VQ_MAX);
- if (b >= SVE_VQ_MAX)
- /* No non-virtualisable VLs found */
- info->max_virtualisable_vl = SVE_VQ_MAX;
- else if (WARN_ON(b == SVE_VQ_MAX - 1))
- /* No virtualisable VLs? This is architecturally forbidden. */
- info->max_virtualisable_vl = SVE_VQ_MIN;
- else /* b + 1 < SVE_VQ_MAX */
- info->max_virtualisable_vl = sve_vl_from_vq(__bit_to_vq(b + 1));
-
- if (info->max_virtualisable_vl > info->max_vl)
- info->max_virtualisable_vl = info->max_vl;
+ info->max_virtualisable_vl = vec_virtualisable_vl(info);

pr_info("%s: maximum available vector length %u bytes per vector\n",
info->name, info->max_vl);

--
2.47.3