On Fri, Mar 06, 2026 at 05:00:56PM +0000, Mark Brown wrote:
> As with SVE we can only virtualise SME vector lengths that are supported by
> all CPUs in the system, implement similar checks to those for SVE. Since
> unlike SVE there are no specific vector lengths that are architecturally
> required the handling is subtly different, we report a system where this
> happens with a maximum vector length of SME_VQ_INVALID.
> 
> Signed-off-by: Mark Brown <[email protected]>
> ---
>  arch/arm64/include/asm/fpsimd.h |  2 ++
>  arch/arm64/kernel/fpsimd.c      | 21 ++++++++++++++++++++-
>  2 files changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index e97729aa3b2f..0cd8a866e844 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -69,6 +69,8 @@ static inline void cpacr_restore(unsigned long cpacr)
>  #define ARCH_SVE_VQ_MAX ((ZCR_ELx_LEN_MASK >> ZCR_ELx_LEN_SHIFT) + 1)
>  #define SME_VQ_MAX   ((SMCR_ELx_LEN_MASK >> SMCR_ELx_LEN_SHIFT) + 1)
>  
> +#define SME_VQ_INVALID       (SME_VQ_MAX + 1)
> +
>  struct task_struct;
>  
>  extern void fpsimd_save_state(struct user_fpsimd_state *state);
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 2af0e0c5b9f4..49c050ef6db9 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -1218,7 +1218,8 @@ void cpu_enable_sme(const struct arm64_cpu_capabilities 
> *__always_unused p)
>  void __init sme_setup(void)
>  {
>       struct vl_info *info = &vl_info[ARM64_VEC_SME];
> -     int min_bit, max_bit;
> +     DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> +     int min_bit, max_bit, b;
>  
>       if (!system_supports_sme())
>               return;
> @@ -1249,12 +1250,30 @@ void __init sme_setup(void)
>        */
>       set_sme_default_vl(find_supported_vector_length(ARM64_VEC_SME, 32));
>  
> +     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)
> +             /* All VLs virtualisable */
> +             info->max_virtualisable_vl = sve_vl_from_vq(ARCH_SVE_VQ_MAX);
> +     else if (b == SVE_VQ_MAX - 1)
> +             /* No virtualisable VLs */
> +             info->max_virtualisable_vl = sve_vl_from_vq(SME_VQ_INVALID);
> +     else
> +             info->max_virtualisable_vl = sve_vl_from_vq(__bit_to_vq(b +  
> 1));

nit: "b + 1"

Reviewed-by: Jean-Philippe Brucker <[email protected]>

> +
>       pr_info("SME: minimum available vector length %u bytes per vector\n",
>               info->min_vl);
>       pr_info("SME: maximum available vector length %u bytes per vector\n",
>               info->max_vl);
>       pr_info("SME: default vector length %u bytes per vector\n",
>               get_sme_default_vl());
> +
> +     /* KVM decides whether to support mismatched systems. Just warn here: */
> +     if (info->max_virtualisable_vl < info->max_vl ||
> +         info->max_virtualisable_vl == sve_vl_from_vq(SME_VQ_INVALID))
> +             pr_warn("SME: unvirtualisable vector lengths present\n");
>  }
>  
>  void sme_suspend_exit(void)
> 
> -- 
> 2.47.3
> 
> 

Reply via email to