// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2024 ARM Limited * * Common helper functions for SVE and SME functionality. */ #include #include #include #include unsigned int vls[SVE_VQ_MAX]; unsigned int nvls; int sve_fill_vls(bool use_sme, int min_vls) { int vq, vl; int pr_set_vl = use_sme ? PR_SME_SET_VL : PR_SVE_SET_VL; int len_mask = use_sme ? PR_SME_VL_LEN_MASK : PR_SVE_VL_LEN_MASK; /* * Enumerate up to SVE_VQ_MAX vector lengths */ for (vq = SVE_VQ_MAX; vq > 0; --vq) { vl = prctl(pr_set_vl, vq * 16); if (vl == -1) return KSFT_FAIL; vl &= len_mask; /* * Unlike SVE, SME does not require the minimum vector length * to be implemented, or the VLs to be consecutive, so any call * to the prctl might return the single implemented VL, which * might be larger than 16. So to avoid this loop never * terminating, bail out here when we find a higher VL than * we asked for. * See the ARM ARM, DDI 0487K.a, B1.4.2: I_QQRNR and I_NWYBP. */ if (vq < sve_vq_from_vl(vl)) break; /* Skip missing VLs */ vq = sve_vq_from_vl(vl); vls[nvls++] = vl; } if (nvls < min_vls) { fprintf(stderr, "Only %d VL supported\n", nvls); return KSFT_SKIP; } return KSFT_PASS; }