1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2021 ARM Limited.
4  */
5 
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/auxv.h>
14 #include <sys/prctl.h>
15 #include <asm/hwcap.h>
16 #include <asm/sigcontext.h>
17 #include <asm/unistd.h>
18 
19 #include "../../kselftest.h"
20 
21 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
22 #define NUM_VL ((SVE_VQ_MAX - SVE_VQ_MIN) + 1)
23 
24 extern void do_syscall(int sve_vl);
25 
26 static void fill_random(void *buf, size_t size)
27 {
28 	int i;
29 	uint32_t *lbuf = buf;
30 
31 	/* random() returns a 32 bit number regardless of the size of long */
32 	for (i = 0; i < size / sizeof(uint32_t); i++)
33 		lbuf[i] = random();
34 }
35 
36 /*
37  * We also repeat the test for several syscalls to try to expose different
38  * behaviour.
39  */
40 static struct syscall_cfg {
41 	int syscall_nr;
42 	const char *name;
43 } syscalls[] = {
44 	{ __NR_getpid,		"getpid()" },
45 	{ __NR_sched_yield,	"sched_yield()" },
46 };
47 
48 #define NUM_GPR 31
49 uint64_t gpr_in[NUM_GPR];
50 uint64_t gpr_out[NUM_GPR];
51 
52 static void setup_gpr(struct syscall_cfg *cfg, int sve_vl)
53 {
54 	fill_random(gpr_in, sizeof(gpr_in));
55 	gpr_in[8] = cfg->syscall_nr;
56 	memset(gpr_out, 0, sizeof(gpr_out));
57 }
58 
59 static int check_gpr(struct syscall_cfg *cfg, int sve_vl)
60 {
61 	int errors = 0;
62 	int i;
63 
64 	/*
65 	 * GPR x0-x7 may be clobbered, and all others should be preserved.
66 	 */
67 	for (i = 9; i < ARRAY_SIZE(gpr_in); i++) {
68 		if (gpr_in[i] != gpr_out[i]) {
69 			ksft_print_msg("%s SVE VL %d mismatch in GPR %d: %llx != %llx\n",
70 				       cfg->name, sve_vl, i,
71 				       gpr_in[i], gpr_out[i]);
72 			errors++;
73 		}
74 	}
75 
76 	return errors;
77 }
78 
79 #define NUM_FPR 32
80 uint64_t fpr_in[NUM_FPR * 2];
81 uint64_t fpr_out[NUM_FPR * 2];
82 
83 static void setup_fpr(struct syscall_cfg *cfg, int sve_vl)
84 {
85 	fill_random(fpr_in, sizeof(fpr_in));
86 	memset(fpr_out, 0, sizeof(fpr_out));
87 }
88 
89 static int check_fpr(struct syscall_cfg *cfg, int sve_vl)
90 {
91 	int errors = 0;
92 	int i;
93 
94 	if (!sve_vl) {
95 		for (i = 0; i < ARRAY_SIZE(fpr_in); i++) {
96 			if (fpr_in[i] != fpr_out[i]) {
97 				ksft_print_msg("%s Q%d/%d mismatch %llx != %llx\n",
98 					       cfg->name,
99 					       i / 2, i % 2,
100 					       fpr_in[i], fpr_out[i]);
101 				errors++;
102 			}
103 		}
104 	}
105 
106 	return errors;
107 }
108 
109 static uint8_t z_zero[__SVE_ZREG_SIZE(SVE_VQ_MAX)];
110 uint8_t z_in[SVE_NUM_PREGS * __SVE_ZREG_SIZE(SVE_VQ_MAX)];
111 uint8_t z_out[SVE_NUM_PREGS * __SVE_ZREG_SIZE(SVE_VQ_MAX)];
112 
113 static void setup_z(struct syscall_cfg *cfg, int sve_vl)
114 {
115 	fill_random(z_in, sizeof(z_in));
116 	fill_random(z_out, sizeof(z_out));
117 }
118 
119 static int check_z(struct syscall_cfg *cfg, int sve_vl)
120 {
121 	size_t reg_size = sve_vl;
122 	int errors = 0;
123 	int i;
124 
125 	if (!sve_vl)
126 		return 0;
127 
128 	/*
129 	 * After a syscall the low 128 bits of the Z registers should
130 	 * be preserved and the rest be zeroed or preserved.
131 	 */
132 	for (i = 0; i < SVE_NUM_ZREGS; i++) {
133 		void *in = &z_in[reg_size * i];
134 		void *out = &z_out[reg_size * i];
135 
136 		if (memcmp(in, out, SVE_VQ_BYTES) != 0) {
137 			ksft_print_msg("%s SVE VL %d Z%d low 128 bits changed\n",
138 				       cfg->name, sve_vl, i);
139 			errors++;
140 		}
141 	}
142 
143 	return errors;
144 }
145 
146 uint8_t p_in[SVE_NUM_PREGS * __SVE_PREG_SIZE(SVE_VQ_MAX)];
147 uint8_t p_out[SVE_NUM_PREGS * __SVE_PREG_SIZE(SVE_VQ_MAX)];
148 
149 static void setup_p(struct syscall_cfg *cfg, int sve_vl)
150 {
151 	fill_random(p_in, sizeof(p_in));
152 	fill_random(p_out, sizeof(p_out));
153 }
154 
155 static int check_p(struct syscall_cfg *cfg, int sve_vl)
156 {
157 	size_t reg_size = sve_vq_from_vl(sve_vl) * 2; /* 1 bit per VL byte */
158 
159 	int errors = 0;
160 	int i;
161 
162 	if (!sve_vl)
163 		return 0;
164 
165 	/* After a syscall the P registers should be preserved or zeroed */
166 	for (i = 0; i < SVE_NUM_PREGS * reg_size; i++)
167 		if (p_out[i] && (p_in[i] != p_out[i]))
168 			errors++;
169 	if (errors)
170 		ksft_print_msg("%s SVE VL %d predicate registers non-zero\n",
171 			       cfg->name, sve_vl);
172 
173 	return errors;
174 }
175 
176 uint8_t ffr_in[__SVE_PREG_SIZE(SVE_VQ_MAX)];
177 uint8_t ffr_out[__SVE_PREG_SIZE(SVE_VQ_MAX)];
178 
179 static void setup_ffr(struct syscall_cfg *cfg, int sve_vl)
180 {
181 	/*
182 	 * It is only valid to set a contiguous set of bits starting
183 	 * at 0.  For now since we're expecting this to be cleared by
184 	 * a syscall just set all bits.
185 	 */
186 	memset(ffr_in, 0xff, sizeof(ffr_in));
187 	fill_random(ffr_out, sizeof(ffr_out));
188 }
189 
190 static int check_ffr(struct syscall_cfg *cfg, int sve_vl)
191 {
192 	size_t reg_size = sve_vq_from_vl(sve_vl) * 2;  /* 1 bit per VL byte */
193 	int errors = 0;
194 	int i;
195 
196 	if (!sve_vl)
197 		return 0;
198 
199 	/* After a syscall the P registers should be preserved or zeroed */
200 	for (i = 0; i < reg_size; i++)
201 		if (ffr_out[i] && (ffr_in[i] != ffr_out[i]))
202 			errors++;
203 	if (errors)
204 		ksft_print_msg("%s SVE VL %d FFR non-zero\n",
205 			       cfg->name, sve_vl);
206 
207 	return errors;
208 }
209 
210 typedef void (*setup_fn)(struct syscall_cfg *cfg, int sve_vl);
211 typedef int (*check_fn)(struct syscall_cfg *cfg, int sve_vl);
212 
213 /*
214  * Each set of registers has a setup function which is called before
215  * the syscall to fill values in a global variable for loading by the
216  * test code and a check function which validates that the results are
217  * as expected.  Vector lengths are passed everywhere, a vector length
218  * of 0 should be treated as do not test.
219  */
220 static struct {
221 	setup_fn setup;
222 	check_fn check;
223 } regset[] = {
224 	{ setup_gpr, check_gpr },
225 	{ setup_fpr, check_fpr },
226 	{ setup_z, check_z },
227 	{ setup_p, check_p },
228 	{ setup_ffr, check_ffr },
229 };
230 
231 static bool do_test(struct syscall_cfg *cfg, int sve_vl)
232 {
233 	int errors = 0;
234 	int i;
235 
236 	for (i = 0; i < ARRAY_SIZE(regset); i++)
237 		regset[i].setup(cfg, sve_vl);
238 
239 	do_syscall(sve_vl);
240 
241 	for (i = 0; i < ARRAY_SIZE(regset); i++)
242 		errors += regset[i].check(cfg, sve_vl);
243 
244 	return errors == 0;
245 }
246 
247 static void test_one_syscall(struct syscall_cfg *cfg)
248 {
249 	int sve_vq, sve_vl;
250 
251 	/* FPSIMD only case */
252 	ksft_test_result(do_test(cfg, 0),
253 			 "%s FPSIMD\n", cfg->name);
254 
255 	if (!(getauxval(AT_HWCAP) & HWCAP_SVE))
256 		return;
257 
258 	for (sve_vq = SVE_VQ_MAX; sve_vq > 0; --sve_vq) {
259 		sve_vl = prctl(PR_SVE_SET_VL, sve_vq * 16);
260 		if (sve_vl == -1)
261 			ksft_exit_fail_msg("PR_SVE_SET_VL failed: %s (%d)\n",
262 					   strerror(errno), errno);
263 
264 		sve_vl &= PR_SVE_VL_LEN_MASK;
265 
266 		if (sve_vq != sve_vq_from_vl(sve_vl))
267 			sve_vq = sve_vq_from_vl(sve_vl);
268 
269 		ksft_test_result(do_test(cfg, sve_vl),
270 				 "%s SVE VL %d\n", cfg->name, sve_vl);
271 	}
272 }
273 
274 int sve_count_vls(void)
275 {
276 	unsigned int vq;
277 	int vl_count = 0;
278 	int vl;
279 
280 	if (!(getauxval(AT_HWCAP) & HWCAP_SVE))
281 		return 0;
282 
283 	/*
284 	 * Enumerate up to SVE_VQ_MAX vector lengths
285 	 */
286 	for (vq = SVE_VQ_MAX; vq > 0; --vq) {
287 		vl = prctl(PR_SVE_SET_VL, vq * 16);
288 		if (vl == -1)
289 			ksft_exit_fail_msg("PR_SVE_SET_VL failed: %s (%d)\n",
290 					   strerror(errno), errno);
291 
292 		vl &= PR_SVE_VL_LEN_MASK;
293 
294 		if (vq != sve_vq_from_vl(vl))
295 			vq = sve_vq_from_vl(vl);
296 
297 		vl_count++;
298 	}
299 
300 	return vl_count;
301 }
302 
303 int main(void)
304 {
305 	int i;
306 
307 	srandom(getpid());
308 
309 	ksft_print_header();
310 	ksft_set_plan(ARRAY_SIZE(syscalls) * (sve_count_vls() + 1));
311 
312 	for (i = 0; i < ARRAY_SIZE(syscalls); i++)
313 		test_one_syscall(&syscalls[i]);
314 
315 	ksft_print_cnts();
316 
317 	return 0;
318 }
319