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