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

From: Fuad Tabba
Date: Wed Jun 05 2024 - 08:39:19 EST


Hi Mark,

On Wed, Jun 5, 2024 at 12:50 PM Mark Brown <broonie@xxxxxxxxxx> 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@xxxxxxxxxx>
> ---
> 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;

/*