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 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
25 #ifndef NT_ARM_SVE
26 #define NT_ARM_SVE 0x405
27 #endif
28 
29 struct vec_type {
30 	const char *name;
31 	unsigned long hwcap_type;
32 	unsigned long hwcap;
33 	int regset;
34 	int prctl_set;
35 };
36 
37 static const struct vec_type vec_types[] = {
38 	{
39 		.name = "SVE",
40 		.hwcap_type = AT_HWCAP,
41 		.hwcap = HWCAP_SVE,
42 		.regset = NT_ARM_SVE,
43 		.prctl_set = PR_SVE_SET_VL,
44 	},
45 };
46 
47 #define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 3)
48 #define FLAG_TESTS 2
49 #define FPSIMD_TESTS 3
50 
51 #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types))
52 
53 static void fill_buf(char *buf, size_t size)
54 {
55 	int i;
56 
57 	for (i = 0; i < size; i++)
58 		buf[i] = random();
59 }
60 
61 static int do_child(void)
62 {
63 	if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
64 		ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno));
65 
66 	if (raise(SIGSTOP))
67 		ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno));
68 
69 	return EXIT_SUCCESS;
70 }
71 
72 static int get_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
73 {
74 	struct iovec iov;
75 
76 	iov.iov_base = fpsimd;
77 	iov.iov_len = sizeof(*fpsimd);
78 	return ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov);
79 }
80 
81 static struct user_sve_header *get_sve(pid_t pid, const struct vec_type *type,
82 				       void **buf, size_t *size)
83 {
84 	struct user_sve_header *sve;
85 	void *p;
86 	size_t sz = sizeof *sve;
87 	struct iovec iov;
88 
89 	while (1) {
90 		if (*size < sz) {
91 			p = realloc(*buf, sz);
92 			if (!p) {
93 				errno = ENOMEM;
94 				goto error;
95 			}
96 
97 			*buf = p;
98 			*size = sz;
99 		}
100 
101 		iov.iov_base = *buf;
102 		iov.iov_len = sz;
103 		if (ptrace(PTRACE_GETREGSET, pid, type->regset, &iov))
104 			goto error;
105 
106 		sve = *buf;
107 		if (sve->size <= sz)
108 			break;
109 
110 		sz = sve->size;
111 	}
112 
113 	return sve;
114 
115 error:
116 	return NULL;
117 }
118 
119 static int set_sve(pid_t pid, const struct vec_type *type,
120 		   const struct user_sve_header *sve)
121 {
122 	struct iovec iov;
123 
124 	iov.iov_base = (void *)sve;
125 	iov.iov_len = sve->size;
126 	return ptrace(PTRACE_SETREGSET, pid, type->regset, &iov);
127 }
128 
129 /* Validate setting and getting the inherit flag */
130 static void ptrace_set_get_inherit(pid_t child, const struct vec_type *type)
131 {
132 	struct user_sve_header sve;
133 	struct user_sve_header *new_sve = NULL;
134 	size_t new_sve_size = 0;
135 	int ret;
136 
137 	/* First set the flag */
138 	memset(&sve, 0, sizeof(sve));
139 	sve.size = sizeof(sve);
140 	sve.vl = sve_vl_from_vq(SVE_VQ_MIN);
141 	sve.flags = SVE_PT_VL_INHERIT;
142 	ret = set_sve(child, type, &sve);
143 	if (ret != 0) {
144 		ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
145 				      type->name);
146 		return;
147 	}
148 
149 	/*
150 	 * Read back the new register state and verify that we have
151 	 * set the flags we expected.
152 	 */
153 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
154 		ksft_test_result_fail("Failed to read %s SVE flags\n",
155 				      type->name);
156 		return;
157 	}
158 
159 	ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT,
160 			 "%s SVE_PT_VL_INHERIT set\n", type->name);
161 
162 	/* Now clear */
163 	sve.flags &= ~SVE_PT_VL_INHERIT;
164 	ret = set_sve(child, type, &sve);
165 	if (ret != 0) {
166 		ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
167 				      type->name);
168 		return;
169 	}
170 
171 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
172 		ksft_test_result_fail("Failed to read %s SVE flags\n",
173 				      type->name);
174 		return;
175 	}
176 
177 	ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT),
178 			 "%s SVE_PT_VL_INHERIT cleared\n", type->name);
179 
180 	free(new_sve);
181 }
182 
183 /* Validate attempting to set the specfied VL via ptrace */
184 static void ptrace_set_get_vl(pid_t child, const struct vec_type *type,
185 			      unsigned int vl, bool *supported)
186 {
187 	struct user_sve_header sve;
188 	struct user_sve_header *new_sve = NULL;
189 	size_t new_sve_size = 0;
190 	int ret, prctl_vl;
191 
192 	*supported = false;
193 
194 	/* Check if the VL is supported in this process */
195 	prctl_vl = prctl(type->prctl_set, vl);
196 	if (prctl_vl == -1)
197 		ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n",
198 				   type->name, strerror(errno), errno);
199 
200 	/* If the VL is not supported then a supported VL will be returned */
201 	*supported = (prctl_vl == vl);
202 
203 	/* Set the VL by doing a set with no register payload */
204 	memset(&sve, 0, sizeof(sve));
205 	sve.size = sizeof(sve);
206 	sve.vl = vl;
207 	ret = set_sve(child, type, &sve);
208 	if (ret != 0) {
209 		ksft_test_result_fail("Failed to set %s VL %u\n",
210 				      type->name, vl);
211 		return;
212 	}
213 
214 	/*
215 	 * Read back the new register state and verify that we have the
216 	 * same VL that we got from prctl() on ourselves.
217 	 */
218 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
219 		ksft_test_result_fail("Failed to read %s VL %u\n",
220 				      type->name, vl);
221 		return;
222 	}
223 
224 	ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n",
225 			 type->name, vl);
226 
227 	free(new_sve);
228 }
229 
230 static void check_u32(unsigned int vl, const char *reg,
231 		      uint32_t *in, uint32_t *out, int *errors)
232 {
233 	if (*in != *out) {
234 		printf("# VL %d %s wrote %x read %x\n",
235 		       vl, reg, *in, *out);
236 		(*errors)++;
237 	}
238 }
239 
240 /* Access the FPSIMD registers via the SVE regset */
241 static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
242 {
243 	void *svebuf = NULL;
244 	size_t svebufsz = 0;
245 	struct user_sve_header *sve;
246 	struct user_fpsimd_state *fpsimd, new_fpsimd;
247 	unsigned int i, j;
248 	unsigned char *p;
249 
250 	/* New process should start with FPSIMD registers only */
251 	sve = get_sve(child, type, &svebuf, &svebufsz);
252 	if (!sve) {
253 		ksft_test_result_fail("get_sve(%s): %s\n",
254 				      type->name, strerror(errno));
255 
256 		return;
257 	} else {
258 		ksft_test_result_pass("get_sve(%s FPSIMD)\n", type->name);
259 	}
260 
261 	ksft_test_result((sve->flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD,
262 			 "Got FPSIMD registers via %s\n", type->name);
263 	if ((sve->flags & SVE_PT_REGS_MASK) != SVE_PT_REGS_FPSIMD)
264 		goto out;
265 
266 	/* Try to set a known FPSIMD state via PT_REGS_SVE */
267 	fpsimd = (struct user_fpsimd_state *)((char *)sve +
268 					      SVE_PT_FPSIMD_OFFSET);
269 	for (i = 0; i < 32; ++i) {
270 		p = (unsigned char *)&fpsimd->vregs[i];
271 
272 		for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
273 			p[j] = j;
274 	}
275 
276 	if (set_sve(child, type, sve)) {
277 		ksft_test_result_fail("set_sve(%s FPSIMD): %s\n",
278 				      type->name, strerror(errno));
279 
280 		goto out;
281 	}
282 
283 	/* Verify via the FPSIMD regset */
284 	if (get_fpsimd(child, &new_fpsimd)) {
285 		ksft_test_result_fail("get_fpsimd(): %s\n",
286 				      strerror(errno));
287 		goto out;
288 	}
289 	if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0)
290 		ksft_test_result_pass("%s get_fpsimd() gave same state\n",
291 				      type->name);
292 	else
293 		ksft_test_result_fail("%s get_fpsimd() gave different state\n",
294 				      type->name);
295 
296 out:
297 	free(svebuf);
298 }
299 
300 /* Validate attempting to set SVE data and read SVE data */
301 static void ptrace_set_sve_get_sve_data(pid_t child,
302 					const struct vec_type *type,
303 					unsigned int vl)
304 {
305 	void *write_buf;
306 	void *read_buf = NULL;
307 	struct user_sve_header *write_sve;
308 	struct user_sve_header *read_sve;
309 	size_t read_sve_size = 0;
310 	unsigned int vq = sve_vq_from_vl(vl);
311 	int ret, i;
312 	size_t data_size;
313 	int errors = 0;
314 
315 	data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
316 	write_buf = malloc(data_size);
317 	if (!write_buf) {
318 		ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
319 				      data_size, type->name, vl);
320 		return;
321 	}
322 	write_sve = write_buf;
323 
324 	/* Set up some data and write it out */
325 	memset(write_sve, 0, data_size);
326 	write_sve->size = data_size;
327 	write_sve->vl = vl;
328 	write_sve->flags = SVE_PT_REGS_SVE;
329 
330 	for (i = 0; i < __SVE_NUM_ZREGS; i++)
331 		fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
332 			 SVE_PT_SVE_ZREG_SIZE(vq));
333 
334 	for (i = 0; i < __SVE_NUM_PREGS; i++)
335 		fill_buf(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
336 			 SVE_PT_SVE_PREG_SIZE(vq));
337 
338 	fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
339 	fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
340 
341 	/* TODO: Generate a valid FFR pattern */
342 
343 	ret = set_sve(child, type, write_sve);
344 	if (ret != 0) {
345 		ksft_test_result_fail("Failed to set %s VL %u data\n",
346 				      type->name, vl);
347 		goto out;
348 	}
349 
350 	/* Read the data back */
351 	if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
352 		ksft_test_result_fail("Failed to read %s VL %u data\n",
353 				      type->name, vl);
354 		goto out;
355 	}
356 	read_sve = read_buf;
357 
358 	/* We might read more data if there's extensions we don't know */
359 	if (read_sve->size < write_sve->size) {
360 		ksft_test_result_fail("%s wrote %d bytes, only read %d\n",
361 				      type->name, write_sve->size,
362 				      read_sve->size);
363 		goto out_read;
364 	}
365 
366 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
367 		if (memcmp(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
368 			   read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
369 			   SVE_PT_SVE_ZREG_SIZE(vq)) != 0) {
370 			printf("# Mismatch in %u Z%d\n", vl, i);
371 			errors++;
372 		}
373 	}
374 
375 	for (i = 0; i < __SVE_NUM_PREGS; i++) {
376 		if (memcmp(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
377 			   read_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
378 			   SVE_PT_SVE_PREG_SIZE(vq)) != 0) {
379 			printf("# Mismatch in %u P%d\n", vl, i);
380 			errors++;
381 		}
382 	}
383 
384 	check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
385 		  read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
386 	check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
387 		  read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
388 
389 	ksft_test_result(errors == 0, "Set and get %s data for VL %u\n",
390 			 type->name, vl);
391 
392 out_read:
393 	free(read_buf);
394 out:
395 	free(write_buf);
396 }
397 
398 /* Validate attempting to set SVE data and read SVE data */
399 static void ptrace_set_sve_get_fpsimd_data(pid_t child,
400 					   const struct vec_type *type,
401 					   unsigned int vl)
402 {
403 	void *write_buf;
404 	struct user_sve_header *write_sve;
405 	unsigned int vq = sve_vq_from_vl(vl);
406 	struct user_fpsimd_state fpsimd_state;
407 	int ret, i;
408 	size_t data_size;
409 	int errors = 0;
410 
411 	if (__BYTE_ORDER == __BIG_ENDIAN) {
412 		ksft_test_result_skip("Big endian not supported\n");
413 		return;
414 	}
415 
416 	data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
417 	write_buf = malloc(data_size);
418 	if (!write_buf) {
419 		ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
420 				      data_size, type->name, vl);
421 		return;
422 	}
423 	write_sve = write_buf;
424 
425 	/* Set up some data and write it out */
426 	memset(write_sve, 0, data_size);
427 	write_sve->size = data_size;
428 	write_sve->vl = vl;
429 	write_sve->flags = SVE_PT_REGS_SVE;
430 
431 	for (i = 0; i < __SVE_NUM_ZREGS; i++)
432 		fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
433 			 SVE_PT_SVE_ZREG_SIZE(vq));
434 
435 	fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
436 	fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
437 
438 	ret = set_sve(child, type, write_sve);
439 	if (ret != 0) {
440 		ksft_test_result_fail("Failed to set %s VL %u data\n",
441 				      type->name, vl);
442 		goto out;
443 	}
444 
445 	/* Read the data back */
446 	if (get_fpsimd(child, &fpsimd_state)) {
447 		ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n",
448 				      type->name, vl);
449 		goto out;
450 	}
451 
452 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
453 		__uint128_t tmp = 0;
454 
455 		/*
456 		 * Z regs are stored endianness invariant, this won't
457 		 * work for big endian
458 		 */
459 		memcpy(&tmp, write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
460 		       sizeof(tmp));
461 
462 		if (tmp != fpsimd_state.vregs[i]) {
463 			printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
464 			       type->name, vl, i);
465 			errors++;
466 		}
467 	}
468 
469 	check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
470 		  &fpsimd_state.fpsr, &errors);
471 	check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
472 		  &fpsimd_state.fpcr, &errors);
473 
474 	ksft_test_result(errors == 0, "Set and get FPSIMD data for %s VL %u\n",
475 			 type->name, vl);
476 
477 out:
478 	free(write_buf);
479 }
480 
481 static int do_parent(pid_t child)
482 {
483 	int ret = EXIT_FAILURE;
484 	pid_t pid;
485 	int status, i;
486 	siginfo_t si;
487 	unsigned int vq, vl;
488 	bool vl_supported;
489 
490 	ksft_print_msg("Parent is %d, child is %d\n", getpid(), child);
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