xref: /linux/tools/testing/selftests/arm64/fp/sve-ptrace.c (revision 7fc2cd2e4b398c57c9cf961cfea05eadbf34c05c)
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 #ifndef NT_ARM_SSVE
30 #define NT_ARM_SSVE 0x40b
31 #endif
32 
33 /*
34  * The architecture defines the maximum VQ as 16 but for extensibility
35  * the kernel specifies the SVE_VQ_MAX as 512 resulting in us running
36  * a *lot* more tests than are useful if we use it.  Until the
37  * architecture is extended let's limit our coverage to what is
38  * currently allowed, plus one extra to ensure we cover constraining
39  * the VL as expected.
40  */
41 #define TEST_VQ_MAX 17
42 
43 struct vec_type {
44 	const char *name;
45 	unsigned long hwcap_type;
46 	unsigned long hwcap;
47 	int regset;
48 	int prctl_set;
49 };
50 
51 static const struct vec_type vec_types[] = {
52 	{
53 		.name = "SVE",
54 		.hwcap_type = AT_HWCAP,
55 		.hwcap = HWCAP_SVE,
56 		.regset = NT_ARM_SVE,
57 		.prctl_set = PR_SVE_SET_VL,
58 	},
59 	{
60 		.name = "Streaming SVE",
61 		.hwcap_type = AT_HWCAP2,
62 		.hwcap = HWCAP2_SME,
63 		.regset = NT_ARM_SSVE,
64 		.prctl_set = PR_SME_SET_VL,
65 	},
66 };
67 
68 #define VL_TESTS (((TEST_VQ_MAX - SVE_VQ_MIN) + 1) * 4)
69 #define FLAG_TESTS 4
70 #define FPSIMD_TESTS 2
71 
72 #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types))
73 
74 static void fill_buf(char *buf, size_t size)
75 {
76 	int i;
77 
78 	for (i = 0; i < size; i++)
79 		buf[i] = random();
80 }
81 
82 static int do_child(void)
83 {
84 	if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
85 		ksft_exit_fail_msg("ptrace(PTRACE_TRACEME) failed: %s (%d)\n",
86 				   strerror(errno), errno);
87 
88 	if (raise(SIGSTOP))
89 		ksft_exit_fail_msg("raise(SIGSTOP) failed: %s (%d)\n",
90 				   strerror(errno), errno);
91 
92 	return EXIT_SUCCESS;
93 }
94 
95 static int get_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
96 {
97 	struct iovec iov;
98 	int ret;
99 
100 	iov.iov_base = fpsimd;
101 	iov.iov_len = sizeof(*fpsimd);
102 	ret = ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov);
103 	if (ret == -1)
104 		ksft_perror("ptrace(PTRACE_GETREGSET)");
105 	return ret;
106 }
107 
108 static int set_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
109 {
110 	struct iovec iov;
111 	int ret;
112 
113 	iov.iov_base = fpsimd;
114 	iov.iov_len = sizeof(*fpsimd);
115 	ret = ptrace(PTRACE_SETREGSET, pid, NT_PRFPREG, &iov);
116 	if (ret == -1)
117 		ksft_perror("ptrace(PTRACE_SETREGSET)");
118 	return ret;
119 }
120 
121 static struct user_sve_header *get_sve(pid_t pid, const struct vec_type *type,
122 				       void **buf, size_t *size)
123 {
124 	struct user_sve_header *sve;
125 	void *p;
126 	size_t sz = sizeof(*sve);
127 	struct iovec iov;
128 	int ret;
129 
130 	while (1) {
131 		if (*size < sz) {
132 			p = realloc(*buf, sz);
133 			if (!p) {
134 				errno = ENOMEM;
135 				goto error;
136 			}
137 
138 			*buf = p;
139 			*size = sz;
140 		}
141 
142 		iov.iov_base = *buf;
143 		iov.iov_len = sz;
144 		ret = ptrace(PTRACE_GETREGSET, pid, type->regset, &iov);
145 		if (ret) {
146 			ksft_perror("ptrace(PTRACE_GETREGSET)");
147 			goto error;
148 		}
149 
150 		sve = *buf;
151 		if (sve->size <= sz)
152 			break;
153 
154 		sz = sve->size;
155 	}
156 
157 	return sve;
158 
159 error:
160 	return NULL;
161 }
162 
163 static int set_sve(pid_t pid, const struct vec_type *type,
164 		   const struct user_sve_header *sve)
165 {
166 	struct iovec iov;
167 	int ret;
168 
169 	iov.iov_base = (void *)sve;
170 	iov.iov_len = sve->size;
171 	ret = ptrace(PTRACE_SETREGSET, pid, type->regset, &iov);
172 	if (ret == -1)
173 		ksft_perror("ptrace(PTRACE_SETREGSET)");
174 	return ret;
175 }
176 
177 /* A read operation fails */
178 static void read_fails(pid_t child, const struct vec_type *type)
179 {
180 	struct user_sve_header *new_sve = NULL;
181 	size_t new_sve_size = 0;
182 	void *ret;
183 
184 	ret = get_sve(child, type, (void **)&new_sve, &new_sve_size);
185 
186 	ksft_test_result(ret == NULL, "%s unsupported read fails\n",
187 			 type->name);
188 
189 	free(new_sve);
190 }
191 
192 /* A write operation fails */
193 static void write_fails(pid_t child, const struct vec_type *type)
194 {
195 	struct user_sve_header sve;
196 	int ret;
197 
198 	/* Just the header, no data */
199 	memset(&sve, 0, sizeof(sve));
200 	sve.size = sizeof(sve);
201 	sve.flags = SVE_PT_REGS_SVE;
202 	sve.vl = SVE_VL_MIN;
203 	ret = set_sve(child, type, &sve);
204 
205 	ksft_test_result(ret != 0, "%s unsupported write fails\n",
206 			 type->name);
207 }
208 
209 /* Validate setting and getting the inherit flag */
210 static void ptrace_set_get_inherit(pid_t child, const struct vec_type *type)
211 {
212 	struct user_sve_header sve;
213 	struct user_sve_header *new_sve = NULL;
214 	size_t new_sve_size = 0;
215 	int ret;
216 
217 	/* First set the flag */
218 	memset(&sve, 0, sizeof(sve));
219 	sve.size = sizeof(sve);
220 	sve.vl = sve_vl_from_vq(SVE_VQ_MIN);
221 	sve.flags = SVE_PT_VL_INHERIT | SVE_PT_REGS_SVE;
222 	ret = set_sve(child, type, &sve);
223 	if (ret != 0) {
224 		ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
225 				      type->name);
226 		return;
227 	}
228 
229 	/*
230 	 * Read back the new register state and verify that we have
231 	 * set the flags we expected.
232 	 */
233 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
234 		ksft_test_result_fail("Failed to read %s SVE flags\n",
235 				      type->name);
236 		return;
237 	}
238 
239 	ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT,
240 			 "%s SVE_PT_VL_INHERIT set\n", type->name);
241 
242 	/* Now clear */
243 	sve.flags &= ~SVE_PT_VL_INHERIT;
244 	ret = set_sve(child, type, &sve);
245 	if (ret != 0) {
246 		ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
247 				      type->name);
248 		return;
249 	}
250 
251 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
252 		ksft_test_result_fail("Failed to read %s SVE flags\n",
253 				      type->name);
254 		return;
255 	}
256 
257 	ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT),
258 			 "%s SVE_PT_VL_INHERIT cleared\n", type->name);
259 
260 	free(new_sve);
261 }
262 
263 /* Validate attempting to set the specfied VL via ptrace */
264 static void ptrace_set_get_vl(pid_t child, const struct vec_type *type,
265 			      unsigned int vl, bool *supported)
266 {
267 	struct user_sve_header sve;
268 	struct user_sve_header *new_sve = NULL;
269 	size_t new_sve_size = 0;
270 	int ret, prctl_vl;
271 
272 	*supported = false;
273 
274 	/* Check if the VL is supported in this process */
275 	prctl_vl = prctl(type->prctl_set, vl);
276 	if (prctl_vl == -1)
277 		ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n",
278 				   type->name, strerror(errno), errno);
279 
280 	/* If the VL is not supported then a supported VL will be returned */
281 	*supported = (prctl_vl == vl);
282 
283 	/* Set the VL by doing a set with no register payload */
284 	memset(&sve, 0, sizeof(sve));
285 	sve.size = sizeof(sve);
286 	sve.flags = SVE_PT_REGS_SVE;
287 	sve.vl = vl;
288 	ret = set_sve(child, type, &sve);
289 	if (ret != 0) {
290 		ksft_test_result_fail("Failed to set %s VL %u\n",
291 				      type->name, vl);
292 		return;
293 	}
294 
295 	/*
296 	 * Read back the new register state and verify that we have the
297 	 * same VL that we got from prctl() on ourselves.
298 	 */
299 	if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
300 		ksft_test_result_fail("Failed to read %s VL %u\n",
301 				      type->name, vl);
302 		return;
303 	}
304 
305 	ksft_test_result(new_sve->vl == prctl_vl, "Set %s VL %u\n",
306 			 type->name, vl);
307 
308 	free(new_sve);
309 }
310 
311 static void check_u32(unsigned int vl, const char *reg,
312 		      uint32_t *in, uint32_t *out, int *errors)
313 {
314 	if (*in != *out) {
315 		printf("# VL %d %s wrote %x read %x\n",
316 		       vl, reg, *in, *out);
317 		(*errors)++;
318 	}
319 }
320 
321 /* Set out of range VLs */
322 static void ptrace_set_vl_ranges(pid_t child, const struct vec_type *type)
323 {
324 	struct user_sve_header sve;
325 	int ret;
326 
327 	memset(&sve, 0, sizeof(sve));
328 	sve.flags = SVE_PT_REGS_SVE;
329 	sve.size = sizeof(sve);
330 
331 	ret = set_sve(child, type, &sve);
332 	ksft_test_result(ret != 0, "%s Set invalid VL 0\n", type->name);
333 
334 	sve.vl = SVE_VL_MAX + SVE_VQ_BYTES;
335 	ret = set_sve(child, type, &sve);
336 	ksft_test_result(ret != 0, "%s Set invalid VL %d\n", type->name,
337 			 SVE_VL_MAX + SVE_VQ_BYTES);
338 }
339 
340 /* Access the FPSIMD registers via the SVE regset */
341 static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
342 {
343 	void *svebuf;
344 	struct user_sve_header *sve;
345 	struct user_fpsimd_state *fpsimd, new_fpsimd;
346 	unsigned int i, j;
347 	unsigned char *p;
348 	int ret;
349 
350 	svebuf = malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
351 	if (!svebuf) {
352 		ksft_test_result_fail("Failed to allocate FPSIMD buffer\n");
353 		return;
354 	}
355 
356 	memset(svebuf, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
357 	sve = svebuf;
358 	sve->flags = SVE_PT_REGS_FPSIMD;
359 	sve->size = SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD);
360 	sve->vl = 16;  /* We don't care what the VL is */
361 
362 	/* Try to set a known FPSIMD state via PT_REGS_SVE */
363 	fpsimd = (struct user_fpsimd_state *)((char *)sve +
364 					      SVE_PT_FPSIMD_OFFSET);
365 	for (i = 0; i < 32; ++i) {
366 		p = (unsigned char *)&fpsimd->vregs[i];
367 
368 		for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
369 			p[j] = j;
370 	}
371 
372 	/* This should only succeed for SVE */
373 	ret = set_sve(child, type, sve);
374 	ksft_test_result((type->regset == NT_ARM_SVE) == (ret == 0),
375 			 "%s FPSIMD set via SVE: %d\n",
376 			 type->name, ret);
377 	if (ret)
378 		goto out;
379 
380 	/* Verify via the FPSIMD regset */
381 	if (get_fpsimd(child, &new_fpsimd)) {
382 		ksft_test_result_fail("get_fpsimd(): %s\n",
383 				      strerror(errno));
384 		goto out;
385 	}
386 	if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0)
387 		ksft_test_result_pass("%s get_fpsimd() gave same state\n",
388 				      type->name);
389 	else
390 		ksft_test_result_fail("%s get_fpsimd() gave different state\n",
391 				      type->name);
392 
393 out:
394 	free(svebuf);
395 }
396 
397 /* Write the FPSIMD registers via the SVE regset when SVE is not supported */
398 static void ptrace_sve_fpsimd_no_sve(pid_t child)
399 {
400 	void *svebuf;
401 	struct user_sve_header *sve;
402 	struct user_fpsimd_state *fpsimd, new_fpsimd;
403 	unsigned int i, j;
404 	unsigned char *p;
405 	int ret;
406 
407 	svebuf = malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
408 	if (!svebuf) {
409 		ksft_test_result_fail("Failed to allocate FPSIMD buffer\n");
410 		return;
411 	}
412 
413 	/* On a system without SVE the VL should be set to 0 */
414 	memset(svebuf, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
415 	sve = svebuf;
416 	sve->flags = SVE_PT_REGS_FPSIMD;
417 	sve->size = SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD);
418 	sve->vl = 0;
419 
420 	/* Try to set a known FPSIMD state via PT_REGS_SVE */
421 	fpsimd = (struct user_fpsimd_state *)((char *)sve +
422 					      SVE_PT_FPSIMD_OFFSET);
423 	for (i = 0; i < 32; ++i) {
424 		p = (unsigned char *)&fpsimd->vregs[i];
425 
426 		for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
427 			p[j] = j;
428 	}
429 
430 	ret = set_sve(child, &vec_types[0], sve);
431 	ksft_test_result(ret == 0, "FPSIMD write via SVE\n");
432 	if (ret) {
433 		ksft_test_result_skip("Verify FPSIMD write via SVE\n");
434 		goto out;
435 	}
436 
437 	/* Verify via the FPSIMD regset */
438 	if (get_fpsimd(child, &new_fpsimd)) {
439 		ksft_test_result_skip("Verify FPSIMD write via SVE\n");
440 		goto out;
441 	}
442 	ksft_test_result(memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0,
443 			 "Verify FPSIMD write via SVE\n");
444 
445 out:
446 	free(svebuf);
447 }
448 
449 /* Validate attempting to set SVE data and read SVE data */
450 static void ptrace_set_sve_get_sve_data(pid_t child,
451 					const struct vec_type *type,
452 					unsigned int vl)
453 {
454 	void *write_buf;
455 	void *read_buf = NULL;
456 	struct user_sve_header *write_sve;
457 	struct user_sve_header *read_sve;
458 	size_t read_sve_size = 0;
459 	unsigned int vq = sve_vq_from_vl(vl);
460 	int ret, i;
461 	size_t data_size;
462 	int errors = 0;
463 
464 	data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
465 	write_buf = malloc(data_size);
466 	if (!write_buf) {
467 		ksft_test_result_fail("Error allocating %ld byte buffer for %s VL %u\n",
468 				      data_size, type->name, vl);
469 		return;
470 	}
471 	write_sve = write_buf;
472 
473 	/* Set up some data and write it out */
474 	memset(write_sve, 0, data_size);
475 	write_sve->size = data_size;
476 	write_sve->vl = vl;
477 	write_sve->flags = SVE_PT_REGS_SVE;
478 
479 	for (i = 0; i < __SVE_NUM_ZREGS; i++)
480 		fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
481 			 SVE_PT_SVE_ZREG_SIZE(vq));
482 
483 	for (i = 0; i < __SVE_NUM_PREGS; i++)
484 		fill_buf(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
485 			 SVE_PT_SVE_PREG_SIZE(vq));
486 
487 	fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
488 	fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
489 
490 	/* TODO: Generate a valid FFR pattern */
491 
492 	ret = set_sve(child, type, write_sve);
493 	if (ret != 0) {
494 		ksft_test_result_fail("Failed to set %s VL %u data\n",
495 				      type->name, vl);
496 		goto out;
497 	}
498 
499 	/* Read the data back */
500 	if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
501 		ksft_test_result_fail("Failed to read %s VL %u data\n",
502 				      type->name, vl);
503 		goto out;
504 	}
505 	read_sve = read_buf;
506 
507 	/* We might read more data if there's extensions we don't know */
508 	if (read_sve->size < write_sve->size) {
509 		ksft_test_result_fail("%s wrote %d bytes, only read %d\n",
510 				      type->name, write_sve->size,
511 				      read_sve->size);
512 		goto out_read;
513 	}
514 
515 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
516 		if (memcmp(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
517 			   read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
518 			   SVE_PT_SVE_ZREG_SIZE(vq)) != 0) {
519 			printf("# Mismatch in %u Z%d\n", vl, i);
520 			errors++;
521 		}
522 	}
523 
524 	for (i = 0; i < __SVE_NUM_PREGS; i++) {
525 		if (memcmp(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
526 			   read_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
527 			   SVE_PT_SVE_PREG_SIZE(vq)) != 0) {
528 			printf("# Mismatch in %u P%d\n", vl, i);
529 			errors++;
530 		}
531 	}
532 
533 	check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
534 		  read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
535 	check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
536 		  read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
537 
538 	ksft_test_result(errors == 0, "Set and get %s data for VL %u\n",
539 			 type->name, vl);
540 
541 out_read:
542 	free(read_buf);
543 out:
544 	free(write_buf);
545 }
546 
547 /* Validate attempting to set SVE data and read it via the FPSIMD regset */
548 static void ptrace_set_sve_get_fpsimd_data(pid_t child,
549 					   const struct vec_type *type,
550 					   unsigned int vl)
551 {
552 	void *write_buf;
553 	struct user_sve_header *write_sve;
554 	unsigned int vq = sve_vq_from_vl(vl);
555 	struct user_fpsimd_state fpsimd_state;
556 	int ret, i;
557 	size_t data_size;
558 	int errors = 0;
559 
560 	if (__BYTE_ORDER == __BIG_ENDIAN) {
561 		ksft_test_result_skip("Big endian not supported\n");
562 		return;
563 	}
564 
565 	data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
566 	write_buf = malloc(data_size);
567 	if (!write_buf) {
568 		ksft_test_result_fail("Error allocating %ld byte buffer for %s VL %u\n",
569 				      data_size, type->name, vl);
570 		return;
571 	}
572 	write_sve = write_buf;
573 
574 	/* Set up some data and write it out */
575 	memset(write_sve, 0, data_size);
576 	write_sve->size = data_size;
577 	write_sve->vl = vl;
578 	write_sve->flags = SVE_PT_REGS_SVE;
579 
580 	for (i = 0; i < __SVE_NUM_ZREGS; i++)
581 		fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
582 			 SVE_PT_SVE_ZREG_SIZE(vq));
583 
584 	fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
585 	fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
586 
587 	ret = set_sve(child, type, write_sve);
588 	if (ret != 0) {
589 		ksft_test_result_fail("Failed to set %s VL %u data\n",
590 				      type->name, vl);
591 		goto out;
592 	}
593 
594 	/* Read the data back */
595 	if (get_fpsimd(child, &fpsimd_state)) {
596 		ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n",
597 				      type->name, vl);
598 		goto out;
599 	}
600 
601 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
602 		__uint128_t tmp = 0;
603 
604 		/*
605 		 * Z regs are stored endianness invariant, this won't
606 		 * work for big endian
607 		 */
608 		memcpy(&tmp, write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
609 		       sizeof(tmp));
610 
611 		if (tmp != fpsimd_state.vregs[i]) {
612 			printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
613 			       type->name, vl, i);
614 			errors++;
615 		}
616 	}
617 
618 	check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
619 		  &fpsimd_state.fpsr, &errors);
620 	check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
621 		  &fpsimd_state.fpcr, &errors);
622 
623 	ksft_test_result(errors == 0, "Set and get FPSIMD data for %s VL %u\n",
624 			 type->name, vl);
625 
626 out:
627 	free(write_buf);
628 }
629 
630 /* Validate attempting to set FPSIMD data and read it via the SVE regset */
631 static void ptrace_set_fpsimd_get_sve_data(pid_t child,
632 					   const struct vec_type *type,
633 					   unsigned int vl)
634 {
635 	void *read_buf = NULL;
636 	unsigned char *p;
637 	struct user_sve_header *read_sve;
638 	unsigned int vq = sve_vq_from_vl(vl);
639 	struct user_fpsimd_state write_fpsimd;
640 	int ret, i, j;
641 	size_t read_sve_size = 0;
642 	size_t expected_size;
643 	int errors = 0;
644 
645 	if (__BYTE_ORDER == __BIG_ENDIAN) {
646 		ksft_test_result_skip("Big endian not supported\n");
647 		return;
648 	}
649 
650 	for (i = 0; i < 32; ++i) {
651 		p = (unsigned char *)&write_fpsimd.vregs[i];
652 
653 		for (j = 0; j < sizeof(write_fpsimd.vregs[i]); ++j)
654 			p[j] = j;
655 	}
656 
657 	ret = set_fpsimd(child, &write_fpsimd);
658 	if (ret != 0) {
659 		ksft_test_result_fail("Failed to set FPSIMD state: %d\n)",
660 				      ret);
661 		return;
662 	}
663 
664 	if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
665 		ksft_test_result_fail("Failed to read %s VL %u data\n",
666 				      type->name, vl);
667 		return;
668 	}
669 	read_sve = read_buf;
670 
671 	if (read_sve->vl != vl) {
672 		ksft_test_result_fail("Child VL != expected VL: %u != %u\n",
673 				      read_sve->vl, vl);
674 		goto out;
675 	}
676 
677 	/* The kernel may return either SVE or FPSIMD format */
678 	switch (read_sve->flags & SVE_PT_REGS_MASK) {
679 	case SVE_PT_REGS_FPSIMD:
680 		expected_size = SVE_PT_FPSIMD_SIZE(vq, SVE_PT_REGS_FPSIMD);
681 		if (read_sve_size < expected_size) {
682 			ksft_test_result_fail("Read %ld bytes, expected %ld\n",
683 					      read_sve_size, expected_size);
684 			goto out;
685 		}
686 
687 		ret = memcmp(&write_fpsimd, read_buf + SVE_PT_FPSIMD_OFFSET,
688 			     sizeof(write_fpsimd));
689 		if (ret != 0) {
690 			ksft_print_msg("Read FPSIMD data mismatch\n");
691 			errors++;
692 		}
693 		break;
694 
695 	case SVE_PT_REGS_SVE:
696 		expected_size = SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
697 		if (read_sve_size < expected_size) {
698 			ksft_test_result_fail("Read %ld bytes, expected %ld\n",
699 					      read_sve_size, expected_size);
700 			goto out;
701 		}
702 
703 		for (i = 0; i < __SVE_NUM_ZREGS; i++) {
704 			__uint128_t tmp = 0;
705 
706 			/*
707 			 * Z regs are stored endianness invariant, this won't
708 			 * work for big endian
709 			 */
710 			memcpy(&tmp, read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
711 			       sizeof(tmp));
712 
713 			if (tmp != write_fpsimd.vregs[i]) {
714 				ksft_print_msg("Mismatch in FPSIMD for %s VL %u Z%d/V%d\n",
715 					       type->name, vl, i, i);
716 				errors++;
717 			}
718 		}
719 
720 		check_u32(vl, "FPSR", &write_fpsimd.fpsr,
721 			  read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
722 		check_u32(vl, "FPCR", &write_fpsimd.fpcr,
723 			  read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
724 		break;
725 	default:
726 		ksft_print_msg("Unexpected regs type %d\n",
727 			       read_sve->flags & SVE_PT_REGS_MASK);
728 		errors++;
729 		break;
730 	}
731 
732 	ksft_test_result(errors == 0, "Set FPSIMD, read via SVE for %s VL %u\n",
733 			 type->name, vl);
734 
735 out:
736 	free(read_buf);
737 }
738 
739 static int do_parent(pid_t child)
740 {
741 	int ret = EXIT_FAILURE;
742 	pid_t pid;
743 	int status, i;
744 	siginfo_t si;
745 	unsigned int vq, vl;
746 	bool vl_supported;
747 
748 	ksft_print_msg("Parent is %d, child is %d\n", getpid(), child);
749 
750 	/* Attach to the child */
751 	while (1) {
752 		int sig;
753 
754 		pid = wait(&status);
755 		if (pid == -1) {
756 			perror("wait");
757 			goto error;
758 		}
759 
760 		/*
761 		 * This should never happen but it's hard to flag in
762 		 * the framework.
763 		 */
764 		if (pid != child)
765 			continue;
766 
767 		if (WIFEXITED(status) || WIFSIGNALED(status))
768 			ksft_exit_fail_msg("Child died unexpectedly\n");
769 
770 		if (!WIFSTOPPED(status))
771 			goto error;
772 
773 		sig = WSTOPSIG(status);
774 
775 		if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &si)) {
776 			if (errno == ESRCH)
777 				goto disappeared;
778 
779 			if (errno == EINVAL) {
780 				sig = 0; /* bust group-stop */
781 				goto cont;
782 			}
783 
784 			ksft_test_result_fail("PTRACE_GETSIGINFO: %s\n",
785 					      strerror(errno));
786 			goto error;
787 		}
788 
789 		if (sig == SIGSTOP && si.si_code == SI_TKILL &&
790 		    si.si_pid == pid)
791 			break;
792 
793 	cont:
794 		if (ptrace(PTRACE_CONT, pid, NULL, sig)) {
795 			if (errno == ESRCH)
796 				goto disappeared;
797 
798 			ksft_test_result_fail("PTRACE_CONT: %s\n",
799 					      strerror(errno));
800 			goto error;
801 		}
802 	}
803 
804 	for (i = 0; i < ARRAY_SIZE(vec_types); i++) {
805 		/*
806 		 * If the vector type isn't supported reads and writes
807 		 * should fail.
808 		 */
809 		if (!(getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap)) {
810 			read_fails(child, &vec_types[i]);
811 			write_fails(child, &vec_types[i]);
812 		} else {
813 			ksft_test_result_skip("%s unsupported read fails\n",
814 					      vec_types[i].name);
815 			ksft_test_result_skip("%s unsupported write fails\n",
816 					      vec_types[i].name);
817 		}
818 
819 		/* FPSIMD via SVE regset */
820 		if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
821 			ptrace_sve_fpsimd(child, &vec_types[i]);
822 		} else {
823 			ksft_test_result_skip("%s FPSIMD set via SVE\n",
824 					      vec_types[i].name);
825 			ksft_test_result_skip("%s FPSIMD read\n",
826 					      vec_types[i].name);
827 		}
828 
829 		/* prctl() flags */
830 		if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
831 			ptrace_set_get_inherit(child, &vec_types[i]);
832 		} else {
833 			ksft_test_result_skip("%s SVE_PT_VL_INHERIT set\n",
834 					      vec_types[i].name);
835 			ksft_test_result_skip("%s SVE_PT_VL_INHERIT cleared\n",
836 					      vec_types[i].name);
837 		}
838 
839 		/* Setting out of bounds VLs should fail */
840 		if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
841 			ptrace_set_vl_ranges(child, &vec_types[i]);
842 		} else {
843 			ksft_test_result_skip("%s Set invalid VL 0\n",
844 					      vec_types[i].name);
845 			ksft_test_result_skip("%s Set invalid VL %d\n",
846 					      vec_types[i].name,
847 					      SVE_VL_MAX + SVE_VQ_BYTES);
848 		}
849 
850 		/* Step through every possible VQ */
851 		for (vq = SVE_VQ_MIN; vq <= TEST_VQ_MAX; vq++) {
852 			vl = sve_vl_from_vq(vq);
853 
854 			/* First, try to set this vector length */
855 			if (getauxval(vec_types[i].hwcap_type) &
856 			    vec_types[i].hwcap) {
857 				ptrace_set_get_vl(child, &vec_types[i], vl,
858 						  &vl_supported);
859 			} else {
860 				ksft_test_result_skip("%s get/set VL %d\n",
861 						      vec_types[i].name, vl);
862 				vl_supported = false;
863 			}
864 
865 			/* If the VL is supported validate data set/get */
866 			if (vl_supported) {
867 				ptrace_set_sve_get_sve_data(child, &vec_types[i], vl);
868 				ptrace_set_sve_get_fpsimd_data(child, &vec_types[i], vl);
869 				ptrace_set_fpsimd_get_sve_data(child, &vec_types[i], vl);
870 			} else {
871 				ksft_test_result_skip("%s set SVE get SVE for VL %d\n",
872 						      vec_types[i].name, vl);
873 				ksft_test_result_skip("%s set SVE get FPSIMD for VL %d\n",
874 						      vec_types[i].name, vl);
875 				ksft_test_result_skip("%s set FPSIMD get SVE for VL %d\n",
876 						      vec_types[i].name, vl);
877 			}
878 		}
879 	}
880 
881 	/* We support SVE writes of FPSMID format on SME only systems */
882 	if (!(getauxval(AT_HWCAP) & HWCAP_SVE) &&
883 	    (getauxval(AT_HWCAP2) & HWCAP2_SME)) {
884 		ptrace_sve_fpsimd_no_sve(child);
885 	} else {
886 		ksft_test_result_skip("FPSIMD write via SVE\n");
887 		ksft_test_result_skip("Verify FPSIMD write via SVE\n");
888 	}
889 
890 	ret = EXIT_SUCCESS;
891 
892 error:
893 	kill(child, SIGKILL);
894 
895 disappeared:
896 	return ret;
897 }
898 
899 int main(void)
900 {
901 	int ret = EXIT_SUCCESS;
902 	pid_t child;
903 
904 	srandom(getpid());
905 
906 	ksft_print_header();
907 	ksft_set_plan(EXPECTED_TESTS);
908 
909 	child = fork();
910 	if (!child)
911 		return do_child();
912 
913 	if (do_parent(child))
914 		ret = EXIT_FAILURE;
915 
916 	ksft_print_cnts();
917 
918 	return ret;
919 }
920