[PATCH 2/4] arm64/fpsimd: Discover maximum vector length implemented by any CPU

Fuad Tabba tabba at google.com
Wed Jun 5 05:03:16 PDT 2024


Hi Mark,

On Wed, Jun 5, 2024 at 12:50 PM Mark Brown <broonie at kernel.org> wrote:
>
> When discovering the vector lengths for SVE and SME we do not currently
> record the maximum VL supported on any individual CPU.  This is expected
> to be the same for all CPUs but the architecture allows asymmetry, if we
> do encounter an asymmetric system then some CPUs may support VLs higher
> than the maximum Linux will use.  Since the pKVM hypervisor needs to
> support saving and restoring anything the host can physically set it
> needs to know the maximum value any CPU could have, add support for
> enumerating it and validation for late CPUs.
>
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---
>  arch/arm64/include/asm/fpsimd.h | 13 +++++++++++++
>  arch/arm64/kernel/fpsimd.c      | 26 +++++++++++++++++++++++++-
>  2 files changed, 38 insertions(+), 1 deletion(-)

Actually, I was working on fixing it and was about to send this, which
I think might be a bit simpler than what you have. Let me know what
you think and I'll send it as a proper patch if you agree:

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index bc69ac368d73..8bde13b7faa3 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -184,6 +184,9 @@ struct vl_info {
        int max_vl;
        int max_virtualisable_vl;

+       /* The maximum vl encountered for any cpu in the system. */
+       int max_system_vl;
+
        /*
         * Set of available vector lengths,
         * where length vq encoded as bit __vq_to_bit(vq):
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 82e8a6017382..e0af4c3c9a40 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1006,7 +1006,7 @@ int sme_get_current_vl(void)
 static void vec_probe_vqs(struct vl_info *info,
                          DECLARE_BITMAP(map, SVE_VQ_MAX))
 {
-       unsigned int vq, vl;
+       unsigned int vq, vl, max_vl = 0;

        bitmap_zero(map, SVE_VQ_MAX);

@@ -1031,7 +1031,12 @@ static void vec_probe_vqs(struct vl_info *info,

                vq = sve_vq_from_vl(vl); /* skip intervening lengths */
                set_bit(__vq_to_bit(vq), map);
+
+               if (!max_vl)
+                       max_vl = vl;
        }
+
+       info->max_system_vl = max((int) max_vl, info->max_system_vl);
 }

 /*
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 3fc8ca164dbe..9f751cce8081 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -52,7 +52,7 @@ int __init kvm_arm_init_sve(void)
 {
        if (system_supports_sve()) {
                kvm_sve_max_vl = sve_max_virtualisable_vl();
-               kvm_host_sve_max_vl = sve_max_vl();
+               kvm_host_sve_max_vl = vl_info[ARM64_VEC_SVE].max_system_vl;
                kvm_nvhe_sym(kvm_host_sve_max_vl) = kvm_host_sve_max_vl;

                /*



More information about the linux-arm-kernel mailing list