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