1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2024 ARM Limited 4 * 5 * Common helper functions for SVE and SME functionality. 6 */ 7 8 #include <stdbool.h> 9 #include <kselftest.h> 10 #include <asm/sigcontext.h> 11 #include <sys/prctl.h> 12 13 unsigned int vls[SVE_VQ_MAX]; 14 unsigned int nvls; 15 16 int sve_fill_vls(bool use_sme, int min_vls) 17 { 18 int vq, vl; 19 int pr_set_vl = use_sme ? PR_SME_SET_VL : PR_SVE_SET_VL; 20 int len_mask = use_sme ? PR_SME_VL_LEN_MASK : PR_SVE_VL_LEN_MASK; 21 22 /* 23 * Enumerate up to SVE_VQ_MAX vector lengths 24 */ 25 for (vq = SVE_VQ_MAX; vq > 0; --vq) { 26 vl = prctl(pr_set_vl, vq * 16); 27 if (vl == -1) 28 return KSFT_FAIL; 29 30 vl &= len_mask; 31 32 /* 33 * Unlike SVE, SME does not require the minimum vector length 34 * to be implemented, or the VLs to be consecutive, so any call 35 * to the prctl might return the single implemented VL, which 36 * might be larger than 16. So to avoid this loop never 37 * terminating, bail out here when we find a higher VL than 38 * we asked for. 39 * See the ARM ARM, DDI 0487K.a, B1.4.2: I_QQRNR and I_NWYBP. 40 */ 41 if (vq < sve_vq_from_vl(vl)) 42 break; 43 44 /* Skip missing VLs */ 45 vq = sve_vq_from_vl(vl); 46 47 vls[nvls++] = vl; 48 } 49 50 if (nvls < min_vls) { 51 fprintf(stderr, "Only %d VL supported\n", nvls); 52 return KSFT_SKIP; 53 } 54 55 return KSFT_PASS; 56 } 57