1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2021 ARM Limited.
4  * Original author: Mark Brown <broonie@kernel.org>
5  */
6 #include <assert.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stddef.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/auxv.h>
15 #include <sys/prctl.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <asm/sigcontext.h>
19 #include <asm/hwcap.h>
20 
21 #include "../../kselftest.h"
22 #include "rdvl.h"
23 
24 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
25 
26 #define ARCH_MIN_VL SVE_VL_MIN
27 
28 struct vec_data {
29 	const char *name;
30 	unsigned long hwcap_type;
31 	unsigned long hwcap;
32 	const char *rdvl_binary;
33 	int (*rdvl)(void);
34 
35 	int prctl_get;
36 	int prctl_set;
37 	const char *default_vl_file;
38 
39 	int default_vl;
40 	int min_vl;
41 	int max_vl;
42 };
43 
44 
45 static struct vec_data vec_data[] = {
46 	{
47 		.name = "SVE",
48 		.hwcap_type = AT_HWCAP,
49 		.hwcap = HWCAP_SVE,
50 		.rdvl = rdvl_sve,
51 		.rdvl_binary = "./rdvl-sve",
52 		.prctl_get = PR_SVE_GET_VL,
53 		.prctl_set = PR_SVE_SET_VL,
54 		.default_vl_file = "/proc/sys/abi/sve_default_vector_length",
55 	},
56 };
57 
58 static int stdio_read_integer(FILE *f, const char *what, int *val)
59 {
60 	int n = 0;
61 	int ret;
62 
63 	ret = fscanf(f, "%d%*1[\n]%n", val, &n);
64 	if (ret < 1 || n < 1) {
65 		ksft_print_msg("failed to parse integer from %s\n", what);
66 		return -1;
67 	}
68 
69 	return 0;
70 }
71 
72 /* Start a new process and return the vector length it sees */
73 static int get_child_rdvl(struct vec_data *data)
74 {
75 	FILE *out;
76 	int pipefd[2];
77 	pid_t pid, child;
78 	int read_vl, ret;
79 
80 	ret = pipe(pipefd);
81 	if (ret == -1) {
82 		ksft_print_msg("pipe() failed: %d (%s)\n",
83 			       errno, strerror(errno));
84 		return -1;
85 	}
86 
87 	fflush(stdout);
88 
89 	child = fork();
90 	if (child == -1) {
91 		ksft_print_msg("fork() failed: %d (%s)\n",
92 			       errno, strerror(errno));
93 		close(pipefd[0]);
94 		close(pipefd[1]);
95 		return -1;
96 	}
97 
98 	/* Child: put vector length on the pipe */
99 	if (child == 0) {
100 		/*
101 		 * Replace stdout with the pipe, errors to stderr from
102 		 * here as kselftest prints to stdout.
103 		 */
104 		ret = dup2(pipefd[1], 1);
105 		if (ret == -1) {
106 			fprintf(stderr, "dup2() %d\n", errno);
107 			exit(EXIT_FAILURE);
108 		}
109 
110 		/* exec() a new binary which puts the VL on stdout */
111 		ret = execl(data->rdvl_binary, data->rdvl_binary, NULL);
112 		fprintf(stderr, "execl(%s) failed: %d (%s)\n",
113 			data->rdvl_binary, errno, strerror(errno));
114 
115 		exit(EXIT_FAILURE);
116 	}
117 
118 	close(pipefd[1]);
119 
120 	/* Parent; wait for the exit status from the child & verify it */
121 	do {
122 		pid = wait(&ret);
123 		if (pid == -1) {
124 			ksft_print_msg("wait() failed: %d (%s)\n",
125 				       errno, strerror(errno));
126 			close(pipefd[0]);
127 			return -1;
128 		}
129 	} while (pid != child);
130 
131 	assert(pid == child);
132 
133 	if (!WIFEXITED(ret)) {
134 		ksft_print_msg("child exited abnormally\n");
135 		close(pipefd[0]);
136 		return -1;
137 	}
138 
139 	if (WEXITSTATUS(ret) != 0) {
140 		ksft_print_msg("child returned error %d\n",
141 			       WEXITSTATUS(ret));
142 		close(pipefd[0]);
143 		return -1;
144 	}
145 
146 	out = fdopen(pipefd[0], "r");
147 	if (!out) {
148 		ksft_print_msg("failed to open child stdout\n");
149 		close(pipefd[0]);
150 		return -1;
151 	}
152 
153 	ret = stdio_read_integer(out, "child", &read_vl);
154 	fclose(out);
155 	if (ret != 0)
156 		return ret;
157 
158 	return read_vl;
159 }
160 
161 static int file_read_integer(const char *name, int *val)
162 {
163 	FILE *f;
164 	int ret;
165 
166 	f = fopen(name, "r");
167 	if (!f) {
168 		ksft_test_result_fail("Unable to open %s: %d (%s)\n",
169 				      name, errno,
170 				      strerror(errno));
171 		return -1;
172 	}
173 
174 	ret = stdio_read_integer(f, name, val);
175 	fclose(f);
176 
177 	return ret;
178 }
179 
180 static int file_write_integer(const char *name, int val)
181 {
182 	FILE *f;
183 
184 	f = fopen(name, "w");
185 	if (!f) {
186 		ksft_test_result_fail("Unable to open %s: %d (%s)\n",
187 				      name, errno,
188 				      strerror(errno));
189 		return -1;
190 	}
191 
192 	fprintf(f, "%d", val);
193 	fclose(f);
194 
195 	return 0;
196 }
197 
198 /*
199  * Verify that we can read the default VL via proc, checking that it
200  * is set in a freshly spawned child.
201  */
202 static void proc_read_default(struct vec_data *data)
203 {
204 	int default_vl, child_vl, ret;
205 
206 	ret = file_read_integer(data->default_vl_file, &default_vl);
207 	if (ret != 0)
208 		return;
209 
210 	/* Is this the actual default seen by new processes? */
211 	child_vl = get_child_rdvl(data);
212 	if (child_vl != default_vl) {
213 		ksft_test_result_fail("%s is %d but child VL is %d\n",
214 				      data->default_vl_file,
215 				      default_vl, child_vl);
216 		return;
217 	}
218 
219 	ksft_test_result_pass("%s default vector length %d\n", data->name,
220 			      default_vl);
221 	data->default_vl = default_vl;
222 }
223 
224 /* Verify that we can write a minimum value and have it take effect */
225 static void proc_write_min(struct vec_data *data)
226 {
227 	int ret, new_default, child_vl;
228 
229 	if (geteuid() != 0) {
230 		ksft_test_result_skip("Need to be root to write to /proc\n");
231 		return;
232 	}
233 
234 	ret = file_write_integer(data->default_vl_file, ARCH_MIN_VL);
235 	if (ret != 0)
236 		return;
237 
238 	/* What was the new value? */
239 	ret = file_read_integer(data->default_vl_file, &new_default);
240 	if (ret != 0)
241 		return;
242 
243 	/* Did it take effect in a new process? */
244 	child_vl = get_child_rdvl(data);
245 	if (child_vl != new_default) {
246 		ksft_test_result_fail("%s is %d but child VL is %d\n",
247 				      data->default_vl_file,
248 				      new_default, child_vl);
249 		return;
250 	}
251 
252 	ksft_test_result_pass("%s minimum vector length %d\n", data->name,
253 			      new_default);
254 	data->min_vl = new_default;
255 
256 	file_write_integer(data->default_vl_file, data->default_vl);
257 }
258 
259 /* Verify that we can write a maximum value and have it take effect */
260 static void proc_write_max(struct vec_data *data)
261 {
262 	int ret, new_default, child_vl;
263 
264 	if (geteuid() != 0) {
265 		ksft_test_result_skip("Need to be root to write to /proc\n");
266 		return;
267 	}
268 
269 	/* -1 is accepted by the /proc interface as the maximum VL */
270 	ret = file_write_integer(data->default_vl_file, -1);
271 	if (ret != 0)
272 		return;
273 
274 	/* What was the new value? */
275 	ret = file_read_integer(data->default_vl_file, &new_default);
276 	if (ret != 0)
277 		return;
278 
279 	/* Did it take effect in a new process? */
280 	child_vl = get_child_rdvl(data);
281 	if (child_vl != new_default) {
282 		ksft_test_result_fail("%s is %d but child VL is %d\n",
283 				      data->default_vl_file,
284 				      new_default, child_vl);
285 		return;
286 	}
287 
288 	ksft_test_result_pass("%s maximum vector length %d\n", data->name,
289 			      new_default);
290 	data->max_vl = new_default;
291 
292 	file_write_integer(data->default_vl_file, data->default_vl);
293 }
294 
295 /* Can we read back a VL from prctl? */
296 static void prctl_get(struct vec_data *data)
297 {
298 	int ret;
299 
300 	ret = prctl(data->prctl_get);
301 	if (ret == -1) {
302 		ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
303 				      data->name, errno, strerror(errno));
304 		return;
305 	}
306 
307 	/* Mask out any flags */
308 	ret &= PR_SVE_VL_LEN_MASK;
309 
310 	/* Is that what we can read back directly? */
311 	if (ret == data->rdvl())
312 		ksft_test_result_pass("%s current VL is %d\n",
313 				      data->name, ret);
314 	else
315 		ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
316 				      data->name, ret, data->rdvl());
317 }
318 
319 /* Does the prctl let us set the VL we already have? */
320 static void prctl_set_same(struct vec_data *data)
321 {
322 	int cur_vl = data->rdvl();
323 	int ret;
324 
325 	ret = prctl(data->prctl_set, cur_vl);
326 	if (ret < 0) {
327 		ksft_test_result_fail("%s prctl set failed: %d (%s)\n",
328 				      data->name, errno, strerror(errno));
329 		return;
330 	}
331 
332 	ksft_test_result(cur_vl == data->rdvl(),
333 			 "%s set VL %d and have VL %d\n",
334 			 data->name, cur_vl, data->rdvl());
335 }
336 
337 /* Can we set a new VL for this process? */
338 static void prctl_set(struct vec_data *data)
339 {
340 	int ret;
341 
342 	if (data->min_vl == data->max_vl) {
343 		ksft_test_result_skip("%s only one VL supported\n",
344 				      data->name);
345 		return;
346 	}
347 
348 	/* Try to set the minimum VL */
349 	ret = prctl(data->prctl_set, data->min_vl);
350 	if (ret < 0) {
351 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
352 				      data->name, data->min_vl,
353 				      errno, strerror(errno));
354 		return;
355 	}
356 
357 	if ((ret & PR_SVE_VL_LEN_MASK) != data->min_vl) {
358 		ksft_test_result_fail("%s prctl set %d but return value is %d\n",
359 				      data->name, data->min_vl, data->rdvl());
360 		return;
361 	}
362 
363 	if (data->rdvl() != data->min_vl) {
364 		ksft_test_result_fail("%s set %d but RDVL is %d\n",
365 				      data->name, data->min_vl, data->rdvl());
366 		return;
367 	}
368 
369 	/* Try to set the maximum VL */
370 	ret = prctl(data->prctl_set, data->max_vl);
371 	if (ret < 0) {
372 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
373 				      data->name, data->max_vl,
374 				      errno, strerror(errno));
375 		return;
376 	}
377 
378 	if ((ret & PR_SVE_VL_LEN_MASK) != data->max_vl) {
379 		ksft_test_result_fail("%s prctl() set %d but return value is %d\n",
380 				      data->name, data->max_vl, data->rdvl());
381 		return;
382 	}
383 
384 	/* The _INHERIT flag should not be present when we read the VL */
385 	ret = prctl(data->prctl_get);
386 	if (ret == -1) {
387 		ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
388 				      data->name, errno, strerror(errno));
389 		return;
390 	}
391 
392 	if (ret & PR_SVE_VL_INHERIT) {
393 		ksft_test_result_fail("%s prctl() reports _INHERIT\n",
394 				      data->name);
395 		return;
396 	}
397 
398 	ksft_test_result_pass("%s prctl() set min/max\n", data->name);
399 }
400 
401 /* If we didn't request it a new VL shouldn't affect the child */
402 static void prctl_set_no_child(struct vec_data *data)
403 {
404 	int ret, child_vl;
405 
406 	if (data->min_vl == data->max_vl) {
407 		ksft_test_result_skip("%s only one VL supported\n",
408 				      data->name);
409 		return;
410 	}
411 
412 	ret = prctl(data->prctl_set, data->min_vl);
413 	if (ret < 0) {
414 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
415 				      data->name, data->min_vl,
416 				      errno, strerror(errno));
417 		return;
418 	}
419 
420 	/* Ensure the default VL is different */
421 	ret = file_write_integer(data->default_vl_file, data->max_vl);
422 	if (ret != 0)
423 		return;
424 
425 	/* Check that the child has the default we just set */
426 	child_vl = get_child_rdvl(data);
427 	if (child_vl != data->max_vl) {
428 		ksft_test_result_fail("%s is %d but child VL is %d\n",
429 				      data->default_vl_file,
430 				      data->max_vl, child_vl);
431 		return;
432 	}
433 
434 	ksft_test_result_pass("%s vector length used default\n", data->name);
435 
436 	file_write_integer(data->default_vl_file, data->default_vl);
437 }
438 
439 /* If we didn't request it a new VL shouldn't affect the child */
440 static void prctl_set_for_child(struct vec_data *data)
441 {
442 	int ret, child_vl;
443 
444 	if (data->min_vl == data->max_vl) {
445 		ksft_test_result_skip("%s only one VL supported\n",
446 				      data->name);
447 		return;
448 	}
449 
450 	ret = prctl(data->prctl_set, data->min_vl | PR_SVE_VL_INHERIT);
451 	if (ret < 0) {
452 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
453 				      data->name, data->min_vl,
454 				      errno, strerror(errno));
455 		return;
456 	}
457 
458 	/* The _INHERIT flag should be present when we read the VL */
459 	ret = prctl(data->prctl_get);
460 	if (ret == -1) {
461 		ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
462 				      data->name, errno, strerror(errno));
463 		return;
464 	}
465 	if (!(ret & PR_SVE_VL_INHERIT)) {
466 		ksft_test_result_fail("%s prctl() does not report _INHERIT\n",
467 				      data->name);
468 		return;
469 	}
470 
471 	/* Ensure the default VL is different */
472 	ret = file_write_integer(data->default_vl_file, data->max_vl);
473 	if (ret != 0)
474 		return;
475 
476 	/* Check that the child inherited our VL */
477 	child_vl = get_child_rdvl(data);
478 	if (child_vl != data->min_vl) {
479 		ksft_test_result_fail("%s is %d but child VL is %d\n",
480 				      data->default_vl_file,
481 				      data->min_vl, child_vl);
482 		return;
483 	}
484 
485 	ksft_test_result_pass("%s vector length was inherited\n", data->name);
486 
487 	file_write_integer(data->default_vl_file, data->default_vl);
488 }
489 
490 /* _ONEXEC takes effect only in the child process */
491 static void prctl_set_onexec(struct vec_data *data)
492 {
493 	int ret, child_vl;
494 
495 	if (data->min_vl == data->max_vl) {
496 		ksft_test_result_skip("%s only one VL supported\n",
497 				      data->name);
498 		return;
499 	}
500 
501 	/* Set a known value for the default and our current VL */
502 	ret = file_write_integer(data->default_vl_file, data->max_vl);
503 	if (ret != 0)
504 		return;
505 
506 	ret = prctl(data->prctl_set, data->max_vl);
507 	if (ret < 0) {
508 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
509 				      data->name, data->min_vl,
510 				      errno, strerror(errno));
511 		return;
512 	}
513 
514 	/* Set a different value for the child to have on exec */
515 	ret = prctl(data->prctl_set, data->min_vl | PR_SVE_SET_VL_ONEXEC);
516 	if (ret < 0) {
517 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
518 				      data->name, data->min_vl,
519 				      errno, strerror(errno));
520 		return;
521 	}
522 
523 	/* Our current VL should stay the same */
524 	if (data->rdvl() != data->max_vl) {
525 		ksft_test_result_fail("%s VL changed by _ONEXEC prctl()\n",
526 				      data->name);
527 		return;
528 	}
529 
530 	/* Check that the child inherited our VL */
531 	child_vl = get_child_rdvl(data);
532 	if (child_vl != data->min_vl) {
533 		ksft_test_result_fail("Set %d _ONEXEC but child VL is %d\n",
534 				      data->min_vl, child_vl);
535 		return;
536 	}
537 
538 	ksft_test_result_pass("%s vector length set on exec\n", data->name);
539 
540 	file_write_integer(data->default_vl_file, data->default_vl);
541 }
542 
543 /* For each VQ verify that setting via prctl() does the right thing */
544 static void prctl_set_all_vqs(struct vec_data *data)
545 {
546 	int ret, vq, vl, new_vl;
547 	int errors = 0;
548 
549 	if (!data->min_vl || !data->max_vl) {
550 		ksft_test_result_skip("%s Failed to enumerate VLs, not testing VL setting\n",
551 				      data->name);
552 		return;
553 	}
554 
555 	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
556 		vl = sve_vl_from_vq(vq);
557 
558 		/* Attempt to set the VL */
559 		ret = prctl(data->prctl_set, vl);
560 		if (ret < 0) {
561 			errors++;
562 			ksft_print_msg("%s prctl set failed for %d: %d (%s)\n",
563 				       data->name, vl,
564 				       errno, strerror(errno));
565 			continue;
566 		}
567 
568 		new_vl = ret & PR_SVE_VL_LEN_MASK;
569 
570 		/* Check that we actually have the reported new VL */
571 		if (data->rdvl() != new_vl) {
572 			ksft_print_msg("Set %s VL %d but RDVL reports %d\n",
573 				       data->name, new_vl, data->rdvl());
574 			errors++;
575 		}
576 
577 		/* Was that the VL we asked for? */
578 		if (new_vl == vl)
579 			continue;
580 
581 		/* Should round up to the minimum VL if below it */
582 		if (vl < data->min_vl) {
583 			if (new_vl != data->min_vl) {
584 				ksft_print_msg("%s VL %d returned %d not minimum %d\n",
585 					       data->name, vl, new_vl,
586 					       data->min_vl);
587 				errors++;
588 			}
589 
590 			continue;
591 		}
592 
593 		/* Should round down to maximum VL if above it */
594 		if (vl > data->max_vl) {
595 			if (new_vl != data->max_vl) {
596 				ksft_print_msg("%s VL %d returned %d not maximum %d\n",
597 					       data->name, vl, new_vl,
598 					       data->max_vl);
599 				errors++;
600 			}
601 
602 			continue;
603 		}
604 
605 		/* Otherwise we should've rounded down */
606 		if (!(new_vl < vl)) {
607 			ksft_print_msg("%s VL %d returned %d, did not round down\n",
608 				       data->name, vl, new_vl);
609 			errors++;
610 
611 			continue;
612 		}
613 	}
614 
615 	ksft_test_result(errors == 0, "%s prctl() set all VLs, %d errors\n",
616 			 data->name, errors);
617 }
618 
619 typedef void (*test_type)(struct vec_data *);
620 
621 static const test_type tests[] = {
622 	/*
623 	 * The default/min/max tests must be first and in this order
624 	 * to provide data for other tests.
625 	 */
626 	proc_read_default,
627 	proc_write_min,
628 	proc_write_max,
629 
630 	prctl_get,
631 	prctl_set_same,
632 	prctl_set,
633 	prctl_set_no_child,
634 	prctl_set_for_child,
635 	prctl_set_onexec,
636 	prctl_set_all_vqs,
637 };
638 
639 int main(void)
640 {
641 	int i, j;
642 
643 	ksft_print_header();
644 	ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data));
645 
646 	for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
647 		struct vec_data *data = &vec_data[i];
648 		unsigned long supported;
649 
650 		supported = getauxval(data->hwcap_type) & data->hwcap;
651 
652 		for (j = 0; j < ARRAY_SIZE(tests); j++) {
653 			if (supported)
654 				tests[j](data);
655 			else
656 				ksft_test_result_skip("%s not supported\n",
657 						      data->name);
658 		}
659 	}
660 
661 	ksft_exit_pass();
662 }
663