1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2015-2021 ARM Limited.
4  * Original author: Dave Martin <Dave.Martin@arm.com>
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 <sys/ptrace.h>
16 #include <sys/types.h>
17 #include <sys/uio.h>
18 #include <sys/wait.h>
19 #include <asm/sigcontext.h>
20 #include <asm/ptrace.h>
21 
22 #include "../../kselftest.h"
23 
24 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
25 
26 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
27 #ifndef NT_ARM_SVE
28 #define NT_ARM_SVE 0x405
29 #endif
30 
31 struct vec_type {
32 	const char *name;
33 	unsigned long hwcap_type;
34 	unsigned long hwcap;
35 	int regset;
36 	int prctl_set;
37 };
38 
39 static const struct vec_type vec_types[] = {
40 	{
41 		.name = "SVE",
42 		.hwcap_type = AT_HWCAP,
43 		.hwcap = HWCAP_SVE,
44 		.regset = NT_ARM_SVE,
45 		.prctl_set = PR_SVE_SET_VL,
46 	},
47 };
48 
49 #define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 3)
50 #define FLAG_TESTS 2
51 #define FPSIMD_TESTS 3
52 
53 #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types))
54 
55 static void fill_buf(char *buf, size_t size)
56 {
57 	int i;
58 
59 	for (i = 0; i < size; i++)
60 		buf[i] = random();
61 }
62 
63 static int do_child(void)
64 {
65 	if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
66 		ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno));
67 
68 	if (raise(SIGSTOP))
69 		ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno));
70 
71 	return EXIT_SUCCESS;
72 }
73 
74 static int get_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
75 {
76 	struct iovec iov;
77 
78 	iov.iov_base = fpsimd;
79 	iov.iov_len = sizeof(*fpsimd);
80 	return ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov);
81 }
82 
83 static struct user_sve_header *get_sve(pid_t pid, const struct vec_type *type,
84 				       void **buf, size_t *size)
85 {
86 	struct user_sve_header *sve;
87 	void *p;
88 	size_t sz = sizeof *sve;
89 	struct iovec iov;
90 
91 	while (1) {
92 		if (*size < sz) {
93 			p = realloc(*buf, sz);
94 			if (!p) {
95 				errno = ENOMEM;
96 				goto error;
97 			}
98 
99 			*buf = p;
100 			*size = sz;
101 		}
102 
103 		iov.iov_base = *buf;
104 		iov.iov_len = sz;
105 		if (ptrace(PTRACE_GETREGSET, pid, type->regset, &iov))
106 			goto error;
107 
108 		sve = *buf;
109 		if (sve->size <= sz)
110 			break;
111 
112 		sz = sve->size;
113 	}
114 
115 	return sve;
116 
117 error:
118 	return NULL;
119 }
120 
121 static int set_sve(pid_t pid, const struct vec_type *type,
122 		   const struct user_sve_header *sve)
123 {
124 	struct iovec iov;
125 
126 	iov.iov_base = (void *)sve;
127 	iov.iov_len = sve->size;
128 	return ptrace(PTRACE_SETREGSET, pid, type->regset, &iov);
129 }
130 
131 /* Validate setting and getting the inherit flag */
132 static void ptrace_set_get_inherit(pid_t child, const struct vec_type *type)
133 {
134 	struct user_sve_header sve;
135 	struct user_sve_header *new_sve = NULL;
136 	size_t new_sve_size = 0;
137 	int ret;
138 
139 	/* First set the flag */
140 	memset(&sve, 0, sizeof(sve));
141 	sve.size = sizeof(sve);
142 	sve.vl = sve_vl_from_vq(SVE_VQ_MIN);
143 	sve.flags = SVE_PT_VL_INHERIT;
144 	ret = set_sve(child, type, &sve);
145 	if (ret != 0) {
146 		ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
147 				      type->name);
148 		return;
149 	}
150 
151 	/*
152 	 * Read back the new register state and verify that we have
153 	 * set the flags we expected.
154 	 */
155 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
156 		ksft_test_result_fail("Failed to read %s SVE flags\n",
157 				      type->name);
158 		return;
159 	}
160 
161 	ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT,
162 			 "%s SVE_PT_VL_INHERIT set\n", type->name);
163 
164 	/* Now clear */
165 	sve.flags &= ~SVE_PT_VL_INHERIT;
166 	ret = set_sve(child, type, &sve);
167 	if (ret != 0) {
168 		ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
169 				      type->name);
170 		return;
171 	}
172 
173 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
174 		ksft_test_result_fail("Failed to read %s SVE flags\n",
175 				      type->name);
176 		return;
177 	}
178 
179 	ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT),
180 			 "%s SVE_PT_VL_INHERIT cleared\n", type->name);
181 
182 	free(new_sve);
183 }
184 
185 /* Validate attempting to set the specfied VL via ptrace */
186 static void ptrace_set_get_vl(pid_t child, const struct vec_type *type,
187 			      unsigned int vl, bool *supported)
188 {
189 	struct user_sve_header sve;
190 	struct user_sve_header *new_sve = NULL;
191 	size_t new_sve_size = 0;
192 	int ret, prctl_vl;
193 
194 	*supported = false;
195 
196 	/* Check if the VL is supported in this process */
197 	prctl_vl = prctl(type->prctl_set, vl);
198 	if (prctl_vl == -1)
199 		ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n",
200 				   type->name, strerror(errno), errno);
201 
202 	/* If the VL is not supported then a supported VL will be returned */
203 	*supported = (prctl_vl == vl);
204 
205 	/* Set the VL by doing a set with no register payload */
206 	memset(&sve, 0, sizeof(sve));
207 	sve.size = sizeof(sve);
208 	sve.vl = vl;
209 	ret = set_sve(child, type, &sve);
210 	if (ret != 0) {
211 		ksft_test_result_fail("Failed to set %s VL %u\n",
212 				      type->name, vl);
213 		return;
214 	}
215 
216 	/*
217 	 * Read back the new register state and verify that we have the
218 	 * same VL that we got from prctl() on ourselves.
219 	 */
220 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
221 		ksft_test_result_fail("Failed to read %s VL %u\n",
222 				      type->name, vl);
223 		return;
224 	}
225 
226 	ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n",
227 			 type->name, vl);
228 
229 	free(new_sve);
230 }
231 
232 static void check_u32(unsigned int vl, const char *reg,
233 		      uint32_t *in, uint32_t *out, int *errors)
234 {
235 	if (*in != *out) {
236 		printf("# VL %d %s wrote %x read %x\n",
237 		       vl, reg, *in, *out);
238 		(*errors)++;
239 	}
240 }
241 
242 /* Access the FPSIMD registers via the SVE regset */
243 static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
244 {
245 	void *svebuf = NULL;
246 	size_t svebufsz = 0;
247 	struct user_sve_header *sve;
248 	struct user_fpsimd_state *fpsimd, new_fpsimd;
249 	unsigned int i, j;
250 	unsigned char *p;
251 
252 	/* New process should start with FPSIMD registers only */
253 	sve = get_sve(child, type, &svebuf, &svebufsz);
254 	if (!sve) {
255 		ksft_test_result_fail("get_sve(%s): %s\n",
256 				      type->name, strerror(errno));
257 
258 		return;
259 	} else {
260 		ksft_test_result_pass("get_sve(%s FPSIMD)\n", type->name);
261 	}
262 
263 	ksft_test_result((sve->flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD,
264 			 "Got FPSIMD registers via %s\n", type->name);
265 	if ((sve->flags & SVE_PT_REGS_MASK) != SVE_PT_REGS_FPSIMD)
266 		goto out;
267 
268 	/* Try to set a known FPSIMD state via PT_REGS_SVE */
269 	fpsimd = (struct user_fpsimd_state *)((char *)sve +
270 					      SVE_PT_FPSIMD_OFFSET);
271 	for (i = 0; i < 32; ++i) {
272 		p = (unsigned char *)&fpsimd->vregs[i];
273 
274 		for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
275 			p[j] = j;
276 	}
277 
278 	if (set_sve(child, type, sve)) {
279 		ksft_test_result_fail("set_sve(%s FPSIMD): %s\n",
280 				      type->name, strerror(errno));
281 
282 		goto out;
283 	}
284 
285 	/* Verify via the FPSIMD regset */
286 	if (get_fpsimd(child, &new_fpsimd)) {
287 		ksft_test_result_fail("get_fpsimd(): %s\n",
288 				      strerror(errno));
289 		goto out;
290 	}
291 	if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0)
292 		ksft_test_result_pass("%s get_fpsimd() gave same state\n",
293 				      type->name);
294 	else
295 		ksft_test_result_fail("%s get_fpsimd() gave different state\n",
296 				      type->name);
297 
298 out:
299 	free(svebuf);
300 }
301 
302 /* Validate attempting to set SVE data and read SVE data */
303 static void ptrace_set_sve_get_sve_data(pid_t child,
304 					const struct vec_type *type,
305 					unsigned int vl)
306 {
307 	void *write_buf;
308 	void *read_buf = NULL;
309 	struct user_sve_header *write_sve;
310 	struct user_sve_header *read_sve;
311 	size_t read_sve_size = 0;
312 	unsigned int vq = sve_vq_from_vl(vl);
313 	int ret, i;
314 	size_t data_size;
315 	int errors = 0;
316 
317 	data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
318 	write_buf = malloc(data_size);
319 	if (!write_buf) {
320 		ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
321 				      data_size, type->name, vl);
322 		return;
323 	}
324 	write_sve = write_buf;
325 
326 	/* Set up some data and write it out */
327 	memset(write_sve, 0, data_size);
328 	write_sve->size = data_size;
329 	write_sve->vl = vl;
330 	write_sve->flags = SVE_PT_REGS_SVE;
331 
332 	for (i = 0; i < __SVE_NUM_ZREGS; i++)
333 		fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
334 			 SVE_PT_SVE_ZREG_SIZE(vq));
335 
336 	for (i = 0; i < __SVE_NUM_PREGS; i++)
337 		fill_buf(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
338 			 SVE_PT_SVE_PREG_SIZE(vq));
339 
340 	fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
341 	fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
342 
343 	/* TODO: Generate a valid FFR pattern */
344 
345 	ret = set_sve(child, type, write_sve);
346 	if (ret != 0) {
347 		ksft_test_result_fail("Failed to set %s VL %u data\n",
348 				      type->name, vl);
349 		goto out;
350 	}
351 
352 	/* Read the data back */
353 	if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
354 		ksft_test_result_fail("Failed to read %s VL %u data\n",
355 				      type->name, vl);
356 		goto out;
357 	}
358 	read_sve = read_buf;
359 
360 	/* We might read more data if there's extensions we don't know */
361 	if (read_sve->size < write_sve->size) {
362 		ksft_test_result_fail("%s wrote %d bytes, only read %d\n",
363 				      type->name, write_sve->size,
364 				      read_sve->size);
365 		goto out_read;
366 	}
367 
368 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
369 		if (memcmp(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
370 			   read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
371 			   SVE_PT_SVE_ZREG_SIZE(vq)) != 0) {
372 			printf("# Mismatch in %u Z%d\n", vl, i);
373 			errors++;
374 		}
375 	}
376 
377 	for (i = 0; i < __SVE_NUM_PREGS; i++) {
378 		if (memcmp(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
379 			   read_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
380 			   SVE_PT_SVE_PREG_SIZE(vq)) != 0) {
381 			printf("# Mismatch in %u P%d\n", vl, i);
382 			errors++;
383 		}
384 	}
385 
386 	check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
387 		  read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
388 	check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
389 		  read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
390 
391 	ksft_test_result(errors == 0, "Set and get %s data for VL %u\n",
392 			 type->name, vl);
393 
394 out_read:
395 	free(read_buf);
396 out:
397 	free(write_buf);
398 }
399 
400 /* Validate attempting to set SVE data and read SVE data */
401 static void ptrace_set_sve_get_fpsimd_data(pid_t child,
402 					   const struct vec_type *type,
403 					   unsigned int vl)
404 {
405 	void *write_buf;
406 	struct user_sve_header *write_sve;
407 	unsigned int vq = sve_vq_from_vl(vl);
408 	struct user_fpsimd_state fpsimd_state;
409 	int ret, i;
410 	size_t data_size;
411 	int errors = 0;
412 
413 	if (__BYTE_ORDER == __BIG_ENDIAN) {
414 		ksft_test_result_skip("Big endian not supported\n");
415 		return;
416 	}
417 
418 	data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
419 	write_buf = malloc(data_size);
420 	if (!write_buf) {
421 		ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
422 				      data_size, type->name, vl);
423 		return;
424 	}
425 	write_sve = write_buf;
426 
427 	/* Set up some data and write it out */
428 	memset(write_sve, 0, data_size);
429 	write_sve->size = data_size;
430 	write_sve->vl = vl;
431 	write_sve->flags = SVE_PT_REGS_SVE;
432 
433 	for (i = 0; i < __SVE_NUM_ZREGS; i++)
434 		fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
435 			 SVE_PT_SVE_ZREG_SIZE(vq));
436 
437 	fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
438 	fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
439 
440 	ret = set_sve(child, type, write_sve);
441 	if (ret != 0) {
442 		ksft_test_result_fail("Failed to set %s VL %u data\n",
443 				      type->name, vl);
444 		goto out;
445 	}
446 
447 	/* Read the data back */
448 	if (get_fpsimd(child, &fpsimd_state)) {
449 		ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n",
450 				      type->name, vl);
451 		goto out;
452 	}
453 
454 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
455 		__uint128_t tmp = 0;
456 
457 		/*
458 		 * Z regs are stored endianness invariant, this won't
459 		 * work for big endian
460 		 */
461 		memcpy(&tmp, write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
462 		       sizeof(tmp));
463 
464 		if (tmp != fpsimd_state.vregs[i]) {
465 			printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
466 			       type->name, vl, i);
467 			errors++;
468 		}
469 	}
470 
471 	check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
472 		  &fpsimd_state.fpsr, &errors);
473 	check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
474 		  &fpsimd_state.fpcr, &errors);
475 
476 	ksft_test_result(errors == 0, "Set and get FPSIMD data for %s VL %u\n",
477 			 type->name, vl);
478 
479 out:
480 	free(write_buf);
481 }
482 
483 static int do_parent(pid_t child)
484 {
485 	int ret = EXIT_FAILURE;
486 	pid_t pid;
487 	int status, i;
488 	siginfo_t si;
489 	unsigned int vq, vl;
490 	bool vl_supported;
491 
492 	/* Attach to the child */
493 	while (1) {
494 		int sig;
495 
496 		pid = wait(&status);
497 		if (pid == -1) {
498 			perror("wait");
499 			goto error;
500 		}
501 
502 		/*
503 		 * This should never happen but it's hard to flag in
504 		 * the framework.
505 		 */
506 		if (pid != child)
507 			continue;
508 
509 		if (WIFEXITED(status) || WIFSIGNALED(status))
510 			ksft_exit_fail_msg("Child died unexpectedly\n");
511 
512 		if (!WIFSTOPPED(status))
513 			goto error;
514 
515 		sig = WSTOPSIG(status);
516 
517 		if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &si)) {
518 			if (errno == ESRCH)
519 				goto disappeared;
520 
521 			if (errno == EINVAL) {
522 				sig = 0; /* bust group-stop */
523 				goto cont;
524 			}
525 
526 			ksft_test_result_fail("PTRACE_GETSIGINFO: %s\n",
527 					      strerror(errno));
528 			goto error;
529 		}
530 
531 		if (sig == SIGSTOP && si.si_code == SI_TKILL &&
532 		    si.si_pid == pid)
533 			break;
534 
535 	cont:
536 		if (ptrace(PTRACE_CONT, pid, NULL, sig)) {
537 			if (errno == ESRCH)
538 				goto disappeared;
539 
540 			ksft_test_result_fail("PTRACE_CONT: %s\n",
541 					      strerror(errno));
542 			goto error;
543 		}
544 	}
545 
546 	for (i = 0; i < ARRAY_SIZE(vec_types); i++) {
547 		/* FPSIMD via SVE regset */
548 		if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
549 			ptrace_sve_fpsimd(child, &vec_types[i]);
550 		} else {
551 			ksft_test_result_skip("%s FPSIMD get via SVE\n",
552 					      vec_types[i].name);
553 			ksft_test_result_skip("%s FPSIMD set via SVE\n",
554 					      vec_types[i].name);
555 			ksft_test_result_skip("%s set read via FPSIMD\n",
556 					      vec_types[i].name);
557 		}
558 
559 		/* prctl() flags */
560 		if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
561 			ptrace_set_get_inherit(child, &vec_types[i]);
562 		} else {
563 			ksft_test_result_skip("%s SVE_PT_VL_INHERIT set\n",
564 					      vec_types[i].name);
565 			ksft_test_result_skip("%s SVE_PT_VL_INHERIT cleared\n",
566 					      vec_types[i].name);
567 		}
568 
569 		/* Step through every possible VQ */
570 		for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
571 			vl = sve_vl_from_vq(vq);
572 
573 			/* First, try to set this vector length */
574 			if (getauxval(vec_types[i].hwcap_type) &
575 			    vec_types[i].hwcap) {
576 				ptrace_set_get_vl(child, &vec_types[i], vl,
577 						  &vl_supported);
578 			} else {
579 				ksft_test_result_skip("%s get/set VL %d\n",
580 						      vec_types[i].name, vl);
581 				vl_supported = false;
582 			}
583 
584 			/* If the VL is supported validate data set/get */
585 			if (vl_supported) {
586 				ptrace_set_sve_get_sve_data(child, &vec_types[i], vl);
587 				ptrace_set_sve_get_fpsimd_data(child, &vec_types[i], vl);
588 			} else {
589 				ksft_test_result_skip("%s set SVE get SVE for VL %d\n",
590 						      vec_types[i].name, vl);
591 				ksft_test_result_skip("%s set SVE get FPSIMD for VL %d\n",
592 						      vec_types[i].name, vl);
593 			}
594 		}
595 	}
596 
597 	ret = EXIT_SUCCESS;
598 
599 error:
600 	kill(child, SIGKILL);
601 
602 disappeared:
603 	return ret;
604 }
605 
606 int main(void)
607 {
608 	int ret = EXIT_SUCCESS;
609 	pid_t child;
610 
611 	srandom(getpid());
612 
613 	ksft_print_header();
614 	ksft_set_plan(EXPECTED_TESTS);
615 
616 	if (!(getauxval(AT_HWCAP) & HWCAP_SVE))
617 		ksft_exit_skip("SVE not available\n");
618 
619 	child = fork();
620 	if (!child)
621 		return do_child();
622 
623 	if (do_parent(child))
624 		ret = EXIT_FAILURE;
625 
626 	ksft_print_cnts();
627 
628 	return ret;
629 }
630