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