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