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

From: Fuad Tabba

Date: Sun Jul 12 2026 - 10:13:24 EST


Hi Mark,

On Thu, 9 Jul 2026 at 19:40, Mark Brown <broonie@xxxxxxxxxx> wrote:
>
> 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;

nit: this is a reimplementation rather than a straight move, the
no-virtualisable case returns 0 (and drops the WARN_ON) where
sve_setup() returned SVE_VQ_MIN. No change for SVE (that case isn't
architecturally possible), and 0 is correct for the SME case this
helper now also serves. Might be worth a word in the changelog, since
"pull ... into a separate function" reads as pure code motion.

Reviewed-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>

Cheers,
/fuad



> +
> + /* 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
>