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\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 	int ret;
184 
185 	f = fopen(name, "w");
186 	if (!f) {
187 		ksft_test_result_fail("Unable to open %s: %d (%s)\n",
188 				      name, errno,
189 				      strerror(errno));
190 		return -1;
191 	}
192 
193 	fprintf(f, "%d", val);
194 	fclose(f);
195 	if (ret < 0) {
196 		ksft_test_result_fail("Error writing %d to %s\n",
197 				      val, name);
198 		return -1;
199 	}
200 
201 	return 0;
202 }
203 
204 /*
205  * Verify that we can read the default VL via proc, checking that it
206  * is set in a freshly spawned child.
207  */
208 static void proc_read_default(struct vec_data *data)
209 {
210 	int default_vl, child_vl, ret;
211 
212 	ret = file_read_integer(data->default_vl_file, &default_vl);
213 	if (ret != 0)
214 		return;
215 
216 	/* Is this the actual default seen by new processes? */
217 	child_vl = get_child_rdvl(data);
218 	if (child_vl != default_vl) {
219 		ksft_test_result_fail("%s is %d but child VL is %d\n",
220 				      data->default_vl_file,
221 				      default_vl, child_vl);
222 		return;
223 	}
224 
225 	ksft_test_result_pass("%s default vector length %d\n", data->name,
226 			      default_vl);
227 	data->default_vl = default_vl;
228 }
229 
230 /* Verify that we can write a minimum value and have it take effect */
231 static void proc_write_min(struct vec_data *data)
232 {
233 	int ret, new_default, child_vl;
234 
235 	if (geteuid() != 0) {
236 		ksft_test_result_skip("Need to be root to write to /proc\n");
237 		return;
238 	}
239 
240 	ret = file_write_integer(data->default_vl_file, ARCH_MIN_VL);
241 	if (ret != 0)
242 		return;
243 
244 	/* What was the new value? */
245 	ret = file_read_integer(data->default_vl_file, &new_default);
246 	if (ret != 0)
247 		return;
248 
249 	/* Did it take effect in a new process? */
250 	child_vl = get_child_rdvl(data);
251 	if (child_vl != new_default) {
252 		ksft_test_result_fail("%s is %d but child VL is %d\n",
253 				      data->default_vl_file,
254 				      new_default, child_vl);
255 		return;
256 	}
257 
258 	ksft_test_result_pass("%s minimum vector length %d\n", data->name,
259 			      new_default);
260 	data->min_vl = new_default;
261 
262 	file_write_integer(data->default_vl_file, data->default_vl);
263 }
264 
265 /* Verify that we can write a maximum value and have it take effect */
266 static void proc_write_max(struct vec_data *data)
267 {
268 	int ret, new_default, child_vl;
269 
270 	if (geteuid() != 0) {
271 		ksft_test_result_skip("Need to be root to write to /proc\n");
272 		return;
273 	}
274 
275 	/* -1 is accepted by the /proc interface as the maximum VL */
276 	ret = file_write_integer(data->default_vl_file, -1);
277 	if (ret != 0)
278 		return;
279 
280 	/* What was the new value? */
281 	ret = file_read_integer(data->default_vl_file, &new_default);
282 	if (ret != 0)
283 		return;
284 
285 	/* Did it take effect in a new process? */
286 	child_vl = get_child_rdvl(data);
287 	if (child_vl != new_default) {
288 		ksft_test_result_fail("%s is %d but child VL is %d\n",
289 				      data->default_vl_file,
290 				      new_default, child_vl);
291 		return;
292 	}
293 
294 	ksft_test_result_pass("%s maximum vector length %d\n", data->name,
295 			      new_default);
296 	data->max_vl = new_default;
297 
298 	file_write_integer(data->default_vl_file, data->default_vl);
299 }
300 
301 /* Can we read back a VL from prctl? */
302 static void prctl_get(struct vec_data *data)
303 {
304 	int ret;
305 
306 	ret = prctl(data->prctl_get);
307 	if (ret == -1) {
308 		ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
309 				      data->name, errno, strerror(errno));
310 		return;
311 	}
312 
313 	/* Mask out any flags */
314 	ret &= PR_SVE_VL_LEN_MASK;
315 
316 	/* Is that what we can read back directly? */
317 	if (ret == data->rdvl())
318 		ksft_test_result_pass("%s current VL is %d\n",
319 				      data->name, ret);
320 	else
321 		ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
322 				      data->name, ret, data->rdvl());
323 }
324 
325 /* Does the prctl let us set the VL we already have? */
326 static void prctl_set_same(struct vec_data *data)
327 {
328 	int cur_vl = data->rdvl();
329 	int ret;
330 
331 	ret = prctl(data->prctl_set, cur_vl);
332 	if (ret < 0) {
333 		ksft_test_result_fail("%s prctl set failed: %d (%s)\n",
334 				      data->name, errno, strerror(errno));
335 		return;
336 	}
337 
338 	if (cur_vl != data->rdvl())
339 		ksft_test_result_pass("%s current VL is %d\n",
340 				      data->name, ret);
341 	else
342 		ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
343 				      data->name, ret, data->rdvl());
344 }
345 
346 /* Can we set a new VL for this process? */
347 static void prctl_set(struct vec_data *data)
348 {
349 	int ret;
350 
351 	if (data->min_vl == data->max_vl) {
352 		ksft_test_result_skip("%s only one VL supported\n",
353 				      data->name);
354 		return;
355 	}
356 
357 	/* Try to set the minimum VL */
358 	ret = prctl(data->prctl_set, data->min_vl);
359 	if (ret < 0) {
360 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
361 				      data->name, data->min_vl,
362 				      errno, strerror(errno));
363 		return;
364 	}
365 
366 	if ((ret & PR_SVE_VL_LEN_MASK) != data->min_vl) {
367 		ksft_test_result_fail("%s prctl set %d but return value is %d\n",
368 				      data->name, data->min_vl, data->rdvl());
369 		return;
370 	}
371 
372 	if (data->rdvl() != data->min_vl) {
373 		ksft_test_result_fail("%s set %d but RDVL is %d\n",
374 				      data->name, data->min_vl, data->rdvl());
375 		return;
376 	}
377 
378 	/* Try to set the maximum VL */
379 	ret = prctl(data->prctl_set, data->max_vl);
380 	if (ret < 0) {
381 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
382 				      data->name, data->max_vl,
383 				      errno, strerror(errno));
384 		return;
385 	}
386 
387 	if ((ret & PR_SVE_VL_LEN_MASK) != data->max_vl) {
388 		ksft_test_result_fail("%s prctl() set %d but return value is %d\n",
389 				      data->name, data->max_vl, data->rdvl());
390 		return;
391 	}
392 
393 	/* The _INHERIT flag should not be present when we read the VL */
394 	ret = prctl(data->prctl_get);
395 	if (ret == -1) {
396 		ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
397 				      data->name, errno, strerror(errno));
398 		return;
399 	}
400 
401 	if (ret & PR_SVE_VL_INHERIT) {
402 		ksft_test_result_fail("%s prctl() reports _INHERIT\n",
403 				      data->name);
404 		return;
405 	}
406 
407 	ksft_test_result_pass("%s prctl() set min/max\n", data->name);
408 }
409 
410 /* If we didn't request it a new VL shouldn't affect the child */
411 static void prctl_set_no_child(struct vec_data *data)
412 {
413 	int ret, child_vl;
414 
415 	if (data->min_vl == data->max_vl) {
416 		ksft_test_result_skip("%s only one VL supported\n",
417 				      data->name);
418 		return;
419 	}
420 
421 	ret = prctl(data->prctl_set, data->min_vl);
422 	if (ret < 0) {
423 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
424 				      data->name, data->min_vl,
425 				      errno, strerror(errno));
426 		return;
427 	}
428 
429 	/* Ensure the default VL is different */
430 	ret = file_write_integer(data->default_vl_file, data->max_vl);
431 	if (ret != 0)
432 		return;
433 
434 	/* Check that the child has the default we just set */
435 	child_vl = get_child_rdvl(data);
436 	if (child_vl != data->max_vl) {
437 		ksft_test_result_fail("%s is %d but child VL is %d\n",
438 				      data->default_vl_file,
439 				      data->max_vl, child_vl);
440 		return;
441 	}
442 
443 	ksft_test_result_pass("%s vector length used default\n", data->name);
444 
445 	file_write_integer(data->default_vl_file, data->default_vl);
446 }
447 
448 /* If we didn't request it a new VL shouldn't affect the child */
449 static void prctl_set_for_child(struct vec_data *data)
450 {
451 	int ret, child_vl;
452 
453 	if (data->min_vl == data->max_vl) {
454 		ksft_test_result_skip("%s only one VL supported\n",
455 				      data->name);
456 		return;
457 	}
458 
459 	ret = prctl(data->prctl_set, data->min_vl | PR_SVE_VL_INHERIT);
460 	if (ret < 0) {
461 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
462 				      data->name, data->min_vl,
463 				      errno, strerror(errno));
464 		return;
465 	}
466 
467 	/* The _INHERIT flag should be present when we read the VL */
468 	ret = prctl(data->prctl_get);
469 	if (ret == -1) {
470 		ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
471 				      data->name, errno, strerror(errno));
472 		return;
473 	}
474 	if (!(ret & PR_SVE_VL_INHERIT)) {
475 		ksft_test_result_fail("%s prctl() does not report _INHERIT\n",
476 				      data->name);
477 		return;
478 	}
479 
480 	/* Ensure the default VL is different */
481 	ret = file_write_integer(data->default_vl_file, data->max_vl);
482 	if (ret != 0)
483 		return;
484 
485 	/* Check that the child inherited our VL */
486 	child_vl = get_child_rdvl(data);
487 	if (child_vl != data->min_vl) {
488 		ksft_test_result_fail("%s is %d but child VL is %d\n",
489 				      data->default_vl_file,
490 				      data->min_vl, child_vl);
491 		return;
492 	}
493 
494 	ksft_test_result_pass("%s vector length was inherited\n", data->name);
495 
496 	file_write_integer(data->default_vl_file, data->default_vl);
497 }
498 
499 /* _ONEXEC takes effect only in the child process */
500 static void prctl_set_onexec(struct vec_data *data)
501 {
502 	int ret, child_vl;
503 
504 	if (data->min_vl == data->max_vl) {
505 		ksft_test_result_skip("%s only one VL supported\n",
506 				      data->name);
507 		return;
508 	}
509 
510 	/* Set a known value for the default and our current VL */
511 	ret = file_write_integer(data->default_vl_file, data->max_vl);
512 	if (ret != 0)
513 		return;
514 
515 	ret = prctl(data->prctl_set, data->max_vl);
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 	/* Set a different value for the child to have on exec */
524 	ret = prctl(data->prctl_set, data->min_vl | PR_SVE_SET_VL_ONEXEC);
525 	if (ret < 0) {
526 		ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
527 				      data->name, data->min_vl,
528 				      errno, strerror(errno));
529 		return;
530 	}
531 
532 	/* Our current VL should stay the same */
533 	if (data->rdvl() != data->max_vl) {
534 		ksft_test_result_fail("%s VL changed by _ONEXEC prctl()\n",
535 				      data->name);
536 		return;
537 	}
538 
539 	/* Check that the child inherited our VL */
540 	child_vl = get_child_rdvl(data);
541 	if (child_vl != data->min_vl) {
542 		ksft_test_result_fail("Set %d _ONEXEC but child VL is %d\n",
543 				      data->min_vl, child_vl);
544 		return;
545 	}
546 
547 	ksft_test_result_pass("%s vector length set on exec\n", data->name);
548 
549 	file_write_integer(data->default_vl_file, data->default_vl);
550 }
551 
552 typedef void (*test_type)(struct vec_data *);
553 
554 static const test_type tests[] = {
555 	/*
556 	 * The default/min/max tests must be first and in this order
557 	 * to provide data for other tests.
558 	 */
559 	proc_read_default,
560 	proc_write_min,
561 	proc_write_max,
562 
563 	prctl_get,
564 	prctl_set,
565 	prctl_set_no_child,
566 	prctl_set_for_child,
567 	prctl_set_onexec,
568 };
569 
570 int main(void)
571 {
572 	int i, j;
573 
574 	ksft_print_header();
575 	ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data));
576 
577 	for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
578 		struct vec_data *data = &vec_data[i];
579 		unsigned long supported;
580 
581 		supported = getauxval(data->hwcap_type) & data->hwcap;
582 
583 		for (j = 0; j < ARRAY_SIZE(tests); j++) {
584 			if (supported)
585 				tests[j](data);
586 			else
587 				ksft_test_result_skip("%s not supported\n",
588 						      data->name);
589 		}
590 	}
591 
592 	ksft_exit_pass();
593 }
594