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