1*2b6d6371SAlex Bennée /*
2*2b6d6371SAlex Bennée * SVE ioctls tests
3*2b6d6371SAlex Bennée *
4*2b6d6371SAlex Bennée * Test the SVE width setting ioctls work and provide a base for
5*2b6d6371SAlex Bennée * testing the gdbstub.
6*2b6d6371SAlex Bennée *
7*2b6d6371SAlex Bennée * Copyright (c) 2019 Linaro Ltd
8*2b6d6371SAlex Bennée *
9*2b6d6371SAlex Bennée * SPDX-License-Identifier: GPL-2.0-or-later
10*2b6d6371SAlex Bennée */
11*2b6d6371SAlex Bennée #include <sys/prctl.h>
12*2b6d6371SAlex Bennée #include <asm/hwcap.h>
13*2b6d6371SAlex Bennée #include <stdio.h>
14*2b6d6371SAlex Bennée #include <sys/auxv.h>
15*2b6d6371SAlex Bennée #include <stdint.h>
16*2b6d6371SAlex Bennée #include <stdlib.h>
17*2b6d6371SAlex Bennée
18*2b6d6371SAlex Bennée #ifndef HWCAP_CPUID
19*2b6d6371SAlex Bennée #define HWCAP_CPUID (1 << 11)
20*2b6d6371SAlex Bennée #endif
21*2b6d6371SAlex Bennée
22*2b6d6371SAlex Bennée #define SVE_MAX_QUADS (2048 / 128)
23*2b6d6371SAlex Bennée #define BYTES_PER_QUAD (128 / 8)
24*2b6d6371SAlex Bennée
25*2b6d6371SAlex Bennée #define get_cpu_reg(id) ({ \
26*2b6d6371SAlex Bennée unsigned long __val; \
27*2b6d6371SAlex Bennée asm("mrs %0, "#id : "=r" (__val)); \
28*2b6d6371SAlex Bennée __val; \
29*2b6d6371SAlex Bennée })
30*2b6d6371SAlex Bennée
do_sve_ioctl_test(void)31*2b6d6371SAlex Bennée static int do_sve_ioctl_test(void)
32*2b6d6371SAlex Bennée {
33*2b6d6371SAlex Bennée int i, res, init_vq;
34*2b6d6371SAlex Bennée
35*2b6d6371SAlex Bennée res = prctl(PR_SVE_GET_VL, 0, 0, 0, 0);
36*2b6d6371SAlex Bennée if (res < 0) {
37*2b6d6371SAlex Bennée printf("FAILED to PR_SVE_GET_VL (%d)", res);
38*2b6d6371SAlex Bennée return -1;
39*2b6d6371SAlex Bennée }
40*2b6d6371SAlex Bennée init_vq = res & PR_SVE_VL_LEN_MASK;
41*2b6d6371SAlex Bennée
42*2b6d6371SAlex Bennée for (i = init_vq; i > 15; i /= 2) {
43*2b6d6371SAlex Bennée printf("Checking PR_SVE_SET_VL=%d\n", i);
44*2b6d6371SAlex Bennée res = prctl(PR_SVE_SET_VL, i, 0, 0, 0, 0);
45*2b6d6371SAlex Bennée if (res < 0) {
46*2b6d6371SAlex Bennée printf("FAILED to PR_SVE_SET_VL (%d)", res);
47*2b6d6371SAlex Bennée return -1;
48*2b6d6371SAlex Bennée }
49*2b6d6371SAlex Bennée asm("index z0.b, #0, #1\n"
50*2b6d6371SAlex Bennée ".global __sve_ld_done\n"
51*2b6d6371SAlex Bennée "__sve_ld_done:\n"
52*2b6d6371SAlex Bennée "mov z0.b, #0\n"
53*2b6d6371SAlex Bennée : /* no outputs kept */
54*2b6d6371SAlex Bennée : /* no inputs */
55*2b6d6371SAlex Bennée : "memory", "z0");
56*2b6d6371SAlex Bennée }
57*2b6d6371SAlex Bennée printf("PASS\n");
58*2b6d6371SAlex Bennée return 0;
59*2b6d6371SAlex Bennée }
60*2b6d6371SAlex Bennée
main(int argc,char ** argv)61*2b6d6371SAlex Bennée int main(int argc, char **argv)
62*2b6d6371SAlex Bennée {
63*2b6d6371SAlex Bennée /* we also need to probe for the ioctl support */
64*2b6d6371SAlex Bennée if (getauxval(AT_HWCAP) & HWCAP_SVE) {
65*2b6d6371SAlex Bennée return do_sve_ioctl_test();
66*2b6d6371SAlex Bennée } else {
67*2b6d6371SAlex Bennée printf("SKIP: no HWCAP_SVE on this system\n");
68*2b6d6371SAlex Bennée return 0;
69*2b6d6371SAlex Bennée }
70*2b6d6371SAlex Bennée }
71