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 > >

