xref: /linux/tools/testing/selftests/arm64/fp/fp-ptrace.c (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2023 ARM Limited.
4  * Original author: Mark Brown <broonie@kernel.org>
5  */
6 
7 #define _GNU_SOURCE
8 
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 #include <sys/auxv.h>
18 #include <sys/prctl.h>
19 #include <sys/ptrace.h>
20 #include <sys/types.h>
21 #include <sys/uio.h>
22 #include <sys/wait.h>
23 
24 #include <linux/kernel.h>
25 
26 #include <asm/sigcontext.h>
27 #include <asm/sve_context.h>
28 #include <asm/ptrace.h>
29 
30 #include "../../kselftest.h"
31 
32 #include "fp-ptrace.h"
33 
34 #include <linux/bits.h>
35 
36 #define FPMR_LSCALE2_MASK                               GENMASK(37, 32)
37 #define FPMR_NSCALE_MASK                                GENMASK(31, 24)
38 #define FPMR_LSCALE_MASK                                GENMASK(22, 16)
39 #define FPMR_OSC_MASK                                   GENMASK(15, 15)
40 #define FPMR_OSM_MASK                                   GENMASK(14, 14)
41 
42 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
43 #ifndef NT_ARM_SVE
44 #define NT_ARM_SVE 0x405
45 #endif
46 
47 #ifndef NT_ARM_SSVE
48 #define NT_ARM_SSVE 0x40b
49 #endif
50 
51 #ifndef NT_ARM_ZA
52 #define NT_ARM_ZA 0x40c
53 #endif
54 
55 #ifndef NT_ARM_ZT
56 #define NT_ARM_ZT 0x40d
57 #endif
58 
59 #ifndef NT_ARM_FPMR
60 #define NT_ARM_FPMR 0x40e
61 #endif
62 
63 #define ARCH_VQ_MAX 256
64 
65 /* VL 128..2048 in powers of 2 */
66 #define MAX_NUM_VLS 5
67 
68 /*
69  * FPMR bits we can set without doing feature checks to see if values
70  * are valid.
71  */
72 #define FPMR_SAFE_BITS (FPMR_LSCALE2_MASK | FPMR_NSCALE_MASK | \
73 			FPMR_LSCALE_MASK | FPMR_OSC_MASK | FPMR_OSM_MASK)
74 
75 #define NUM_FPR 32
76 __uint128_t v_in[NUM_FPR];
77 __uint128_t v_expected[NUM_FPR];
78 __uint128_t v_out[NUM_FPR];
79 
80 char z_in[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)];
81 char z_expected[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)];
82 char z_out[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)];
83 
84 char p_in[__SVE_PREGS_SIZE(ARCH_VQ_MAX)];
85 char p_expected[__SVE_PREGS_SIZE(ARCH_VQ_MAX)];
86 char p_out[__SVE_PREGS_SIZE(ARCH_VQ_MAX)];
87 
88 char ffr_in[__SVE_PREG_SIZE(ARCH_VQ_MAX)];
89 char ffr_expected[__SVE_PREG_SIZE(ARCH_VQ_MAX)];
90 char ffr_out[__SVE_PREG_SIZE(ARCH_VQ_MAX)];
91 
92 char za_in[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)];
93 char za_expected[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)];
94 char za_out[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)];
95 
96 char zt_in[ZT_SIG_REG_BYTES];
97 char zt_expected[ZT_SIG_REG_BYTES];
98 char zt_out[ZT_SIG_REG_BYTES];
99 
100 uint64_t fpmr_in, fpmr_expected, fpmr_out;
101 
102 uint64_t sve_vl_out;
103 uint64_t sme_vl_out;
104 uint64_t svcr_in, svcr_expected, svcr_out;
105 
106 void load_and_save(int flags);
107 
108 static bool got_alarm;
109 
110 static void handle_alarm(int sig, siginfo_t *info, void *context)
111 {
112 	got_alarm = true;
113 }
114 
115 #ifdef CONFIG_CPU_BIG_ENDIAN
116 static __uint128_t arm64_cpu_to_le128(__uint128_t x)
117 {
118 	u64 a = swab64(x);
119 	u64 b = swab64(x >> 64);
120 
121 	return ((__uint128_t)a << 64) | b;
122 }
123 #else
124 static __uint128_t arm64_cpu_to_le128(__uint128_t x)
125 {
126 	return x;
127 }
128 #endif
129 
130 #define arm64_le128_to_cpu(x) arm64_cpu_to_le128(x)
131 
132 static bool sve_supported(void)
133 {
134 	return getauxval(AT_HWCAP) & HWCAP_SVE;
135 }
136 
137 static bool sme_supported(void)
138 {
139 	return getauxval(AT_HWCAP2) & HWCAP2_SME;
140 }
141 
142 static bool sme2_supported(void)
143 {
144 	return getauxval(AT_HWCAP2) & HWCAP2_SME2;
145 }
146 
147 static bool fa64_supported(void)
148 {
149 	return getauxval(AT_HWCAP2) & HWCAP2_SME_FA64;
150 }
151 
152 static bool fpmr_supported(void)
153 {
154 	return getauxval(AT_HWCAP2) & HWCAP2_FPMR;
155 }
156 
157 static bool compare_buffer(const char *name, void *out,
158 			   void *expected, size_t size)
159 {
160 	void *tmp;
161 
162 	if (memcmp(out, expected, size) == 0)
163 		return true;
164 
165 	ksft_print_msg("Mismatch in %s\n", name);
166 
167 	/* Did we just get zeros back? */
168 	tmp = malloc(size);
169 	if (!tmp) {
170 		ksft_print_msg("OOM allocating %lu bytes for %s\n",
171 			       size, name);
172 		ksft_exit_fail();
173 	}
174 	memset(tmp, 0, size);
175 
176 	if (memcmp(out, tmp, size) == 0)
177 		ksft_print_msg("%s is zero\n", name);
178 
179 	free(tmp);
180 
181 	return false;
182 }
183 
184 struct test_config {
185 	int sve_vl_in;
186 	int sve_vl_expected;
187 	int sme_vl_in;
188 	int sme_vl_expected;
189 	int svcr_in;
190 	int svcr_expected;
191 };
192 
193 struct test_definition {
194 	const char *name;
195 	bool sve_vl_change;
196 	bool (*supported)(struct test_config *config);
197 	void (*set_expected_values)(struct test_config *config);
198 	void (*modify_values)(pid_t child, struct test_config *test_config);
199 };
200 
201 static int vl_in(struct test_config *config)
202 {
203 	int vl;
204 
205 	if (config->svcr_in & SVCR_SM)
206 		vl = config->sme_vl_in;
207 	else
208 		vl = config->sve_vl_in;
209 
210 	return vl;
211 }
212 
213 static int vl_expected(struct test_config *config)
214 {
215 	int vl;
216 
217 	if (config->svcr_expected & SVCR_SM)
218 		vl = config->sme_vl_expected;
219 	else
220 		vl = config->sve_vl_expected;
221 
222 	return vl;
223 }
224 
225 static void run_child(struct test_config *config)
226 {
227 	int ret, flags;
228 
229 	/* Let the parent attach to us */
230 	ret = ptrace(PTRACE_TRACEME, 0, 0, 0);
231 	if (ret < 0)
232 		ksft_exit_fail_msg("PTRACE_TRACEME failed: %s (%d)\n",
233 				   strerror(errno), errno);
234 
235 	/* VL setup */
236 	if (sve_supported()) {
237 		ret = prctl(PR_SVE_SET_VL, config->sve_vl_in);
238 		if (ret != config->sve_vl_in) {
239 			ksft_print_msg("Failed to set SVE VL %d: %d\n",
240 				       config->sve_vl_in, ret);
241 		}
242 	}
243 
244 	if (sme_supported()) {
245 		ret = prctl(PR_SME_SET_VL, config->sme_vl_in);
246 		if (ret != config->sme_vl_in) {
247 			ksft_print_msg("Failed to set SME VL %d: %d\n",
248 				       config->sme_vl_in, ret);
249 		}
250 	}
251 
252 	/* Load values and wait for the parent */
253 	flags = 0;
254 	if (sve_supported())
255 		flags |= HAVE_SVE;
256 	if (sme_supported())
257 		flags |= HAVE_SME;
258 	if (sme2_supported())
259 		flags |= HAVE_SME2;
260 	if (fa64_supported())
261 		flags |= HAVE_FA64;
262 	if (fpmr_supported())
263 		flags |= HAVE_FPMR;
264 
265 	load_and_save(flags);
266 
267 	exit(0);
268 }
269 
270 static void read_one_child_regs(pid_t child, char *name,
271 				struct iovec *iov_parent,
272 				struct iovec *iov_child)
273 {
274 	int len = iov_parent->iov_len;
275 	int ret;
276 
277 	ret = process_vm_readv(child, iov_parent, 1, iov_child, 1, 0);
278 	if (ret == -1)
279 		ksft_print_msg("%s read failed: %s (%d)\n",
280 			       name, strerror(errno), errno);
281 	else if (ret != len)
282 		ksft_print_msg("Short read of %s: %d\n", name, ret);
283 }
284 
285 static void read_child_regs(pid_t child)
286 {
287 	struct iovec iov_parent, iov_child;
288 
289 	/*
290 	 * Since the child fork()ed from us the buffer addresses are
291 	 * the same in parent and child.
292 	 */
293 	iov_parent.iov_base = &v_out;
294 	iov_parent.iov_len = sizeof(v_out);
295 	iov_child.iov_base = &v_out;
296 	iov_child.iov_len = sizeof(v_out);
297 	read_one_child_regs(child, "FPSIMD", &iov_parent, &iov_child);
298 
299 	if (sve_supported() || sme_supported()) {
300 		iov_parent.iov_base = &sve_vl_out;
301 		iov_parent.iov_len = sizeof(sve_vl_out);
302 		iov_child.iov_base = &sve_vl_out;
303 		iov_child.iov_len = sizeof(sve_vl_out);
304 		read_one_child_regs(child, "SVE VL", &iov_parent, &iov_child);
305 
306 		iov_parent.iov_base = &z_out;
307 		iov_parent.iov_len = sizeof(z_out);
308 		iov_child.iov_base = &z_out;
309 		iov_child.iov_len = sizeof(z_out);
310 		read_one_child_regs(child, "Z", &iov_parent, &iov_child);
311 
312 		iov_parent.iov_base = &p_out;
313 		iov_parent.iov_len = sizeof(p_out);
314 		iov_child.iov_base = &p_out;
315 		iov_child.iov_len = sizeof(p_out);
316 		read_one_child_regs(child, "P", &iov_parent, &iov_child);
317 
318 		iov_parent.iov_base = &ffr_out;
319 		iov_parent.iov_len = sizeof(ffr_out);
320 		iov_child.iov_base = &ffr_out;
321 		iov_child.iov_len = sizeof(ffr_out);
322 		read_one_child_regs(child, "FFR", &iov_parent, &iov_child);
323 	}
324 
325 	if (sme_supported()) {
326 		iov_parent.iov_base = &sme_vl_out;
327 		iov_parent.iov_len = sizeof(sme_vl_out);
328 		iov_child.iov_base = &sme_vl_out;
329 		iov_child.iov_len = sizeof(sme_vl_out);
330 		read_one_child_regs(child, "SME VL", &iov_parent, &iov_child);
331 
332 		iov_parent.iov_base = &svcr_out;
333 		iov_parent.iov_len = sizeof(svcr_out);
334 		iov_child.iov_base = &svcr_out;
335 		iov_child.iov_len = sizeof(svcr_out);
336 		read_one_child_regs(child, "SVCR", &iov_parent, &iov_child);
337 
338 		iov_parent.iov_base = &za_out;
339 		iov_parent.iov_len = sizeof(za_out);
340 		iov_child.iov_base = &za_out;
341 		iov_child.iov_len = sizeof(za_out);
342 		read_one_child_regs(child, "ZA", &iov_parent, &iov_child);
343 	}
344 
345 	if (sme2_supported()) {
346 		iov_parent.iov_base = &zt_out;
347 		iov_parent.iov_len = sizeof(zt_out);
348 		iov_child.iov_base = &zt_out;
349 		iov_child.iov_len = sizeof(zt_out);
350 		read_one_child_regs(child, "ZT", &iov_parent, &iov_child);
351 	}
352 
353 	if (fpmr_supported()) {
354 		iov_parent.iov_base = &fpmr_out;
355 		iov_parent.iov_len = sizeof(fpmr_out);
356 		iov_child.iov_base = &fpmr_out;
357 		iov_child.iov_len = sizeof(fpmr_out);
358 		read_one_child_regs(child, "FPMR", &iov_parent, &iov_child);
359 	}
360 }
361 
362 static bool continue_breakpoint(pid_t child,
363 				enum __ptrace_request restart_type)
364 {
365 	struct user_pt_regs pt_regs;
366 	struct iovec iov;
367 	int ret;
368 
369 	/* Get PC */
370 	iov.iov_base = &pt_regs;
371 	iov.iov_len = sizeof(pt_regs);
372 	ret = ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov);
373 	if (ret < 0) {
374 		ksft_print_msg("Failed to get PC: %s (%d)\n",
375 			       strerror(errno), errno);
376 		return false;
377 	}
378 
379 	/* Skip over the BRK */
380 	pt_regs.pc += 4;
381 	ret = ptrace(PTRACE_SETREGSET, child, NT_PRSTATUS, &iov);
382 	if (ret < 0) {
383 		ksft_print_msg("Failed to skip BRK: %s (%d)\n",
384 			       strerror(errno), errno);
385 		return false;
386 	}
387 
388 	/* Restart */
389 	ret = ptrace(restart_type, child, 0, 0);
390 	if (ret < 0) {
391 		ksft_print_msg("Failed to restart child: %s (%d)\n",
392 			       strerror(errno), errno);
393 		return false;
394 	}
395 
396 	return true;
397 }
398 
399 static bool check_ptrace_values_sve(pid_t child, struct test_config *config)
400 {
401 	struct user_sve_header *sve;
402 	struct user_fpsimd_state *fpsimd;
403 	struct iovec iov;
404 	int ret, vq;
405 	bool pass = true;
406 
407 	if (!sve_supported())
408 		return true;
409 
410 	vq = __sve_vq_from_vl(config->sve_vl_in);
411 
412 	iov.iov_len = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
413 	iov.iov_base = malloc(iov.iov_len);
414 	if (!iov.iov_base) {
415 		ksft_print_msg("OOM allocating %lu byte SVE buffer\n",
416 			       iov.iov_len);
417 		return false;
418 	}
419 
420 	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_SVE, &iov);
421 	if (ret != 0) {
422 		ksft_print_msg("Failed to read initial SVE: %s (%d)\n",
423 			       strerror(errno), errno);
424 		pass = false;
425 		goto out;
426 	}
427 
428 	sve = iov.iov_base;
429 
430 	if (sve->vl != config->sve_vl_in) {
431 		ksft_print_msg("Mismatch in initial SVE VL: %d != %d\n",
432 			       sve->vl, config->sve_vl_in);
433 		pass = false;
434 	}
435 
436 	/* If we are in streaming mode we should just read FPSIMD */
437 	if ((config->svcr_in & SVCR_SM) && (sve->flags & SVE_PT_REGS_SVE)) {
438 		ksft_print_msg("NT_ARM_SVE reports SVE with PSTATE.SM\n");
439 		pass = false;
440 	}
441 
442 	if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
443 		ksft_print_msg("Mismatch in SVE header size: %d != %lu\n",
444 			       sve->size, SVE_PT_SIZE(vq, sve->flags));
445 		pass = false;
446 	}
447 
448 	/* The registers might be in completely different formats! */
449 	if (sve->flags & SVE_PT_REGS_SVE) {
450 		if (!compare_buffer("initial SVE Z",
451 				    iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0),
452 				    z_in, SVE_PT_SVE_ZREGS_SIZE(vq)))
453 			pass = false;
454 
455 		if (!compare_buffer("initial SVE P",
456 				    iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0),
457 				    p_in, SVE_PT_SVE_PREGS_SIZE(vq)))
458 			pass = false;
459 
460 		if (!compare_buffer("initial SVE FFR",
461 				    iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq),
462 				    ffr_in, SVE_PT_SVE_PREG_SIZE(vq)))
463 			pass = false;
464 	} else {
465 		fpsimd = iov.iov_base + SVE_PT_FPSIMD_OFFSET;
466 		if (!compare_buffer("initial V via SVE", &fpsimd->vregs[0],
467 				    v_in, sizeof(v_in)))
468 			pass = false;
469 	}
470 
471 out:
472 	free(iov.iov_base);
473 	return pass;
474 }
475 
476 static bool check_ptrace_values_ssve(pid_t child, struct test_config *config)
477 {
478 	struct user_sve_header *sve;
479 	struct user_fpsimd_state *fpsimd;
480 	struct iovec iov;
481 	int ret, vq;
482 	bool pass = true;
483 
484 	if (!sme_supported())
485 		return true;
486 
487 	vq = __sve_vq_from_vl(config->sme_vl_in);
488 
489 	iov.iov_len = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
490 	iov.iov_base = malloc(iov.iov_len);
491 	if (!iov.iov_base) {
492 		ksft_print_msg("OOM allocating %lu byte SSVE buffer\n",
493 			       iov.iov_len);
494 		return false;
495 	}
496 
497 	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_SSVE, &iov);
498 	if (ret != 0) {
499 		ksft_print_msg("Failed to read initial SSVE: %s (%d)\n",
500 			       strerror(errno), errno);
501 		pass = false;
502 		goto out;
503 	}
504 
505 	sve = iov.iov_base;
506 
507 	if (sve->vl != config->sme_vl_in) {
508 		ksft_print_msg("Mismatch in initial SSVE VL: %d != %d\n",
509 			       sve->vl, config->sme_vl_in);
510 		pass = false;
511 	}
512 
513 	if ((config->svcr_in & SVCR_SM) && !(sve->flags & SVE_PT_REGS_SVE)) {
514 		ksft_print_msg("NT_ARM_SSVE reports FPSIMD with PSTATE.SM\n");
515 		pass = false;
516 	}
517 
518 	if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
519 		ksft_print_msg("Mismatch in SSVE header size: %d != %lu\n",
520 			       sve->size, SVE_PT_SIZE(vq, sve->flags));
521 		pass = false;
522 	}
523 
524 	/* The registers might be in completely different formats! */
525 	if (sve->flags & SVE_PT_REGS_SVE) {
526 		if (!compare_buffer("initial SSVE Z",
527 				    iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0),
528 				    z_in, SVE_PT_SVE_ZREGS_SIZE(vq)))
529 			pass = false;
530 
531 		if (!compare_buffer("initial SSVE P",
532 				    iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0),
533 				    p_in, SVE_PT_SVE_PREGS_SIZE(vq)))
534 			pass = false;
535 
536 		if (!compare_buffer("initial SSVE FFR",
537 				    iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq),
538 				    ffr_in, SVE_PT_SVE_PREG_SIZE(vq)))
539 			pass = false;
540 	} else {
541 		fpsimd = iov.iov_base + SVE_PT_FPSIMD_OFFSET;
542 		if (!compare_buffer("initial V via SSVE",
543 				    &fpsimd->vregs[0], v_in, sizeof(v_in)))
544 			pass = false;
545 	}
546 
547 out:
548 	free(iov.iov_base);
549 	return pass;
550 }
551 
552 static bool check_ptrace_values_za(pid_t child, struct test_config *config)
553 {
554 	struct user_za_header *za;
555 	struct iovec iov;
556 	int ret, vq;
557 	bool pass = true;
558 
559 	if (!sme_supported())
560 		return true;
561 
562 	vq = __sve_vq_from_vl(config->sme_vl_in);
563 
564 	iov.iov_len = ZA_SIG_CONTEXT_SIZE(vq);
565 	iov.iov_base = malloc(iov.iov_len);
566 	if (!iov.iov_base) {
567 		ksft_print_msg("OOM allocating %lu byte ZA buffer\n",
568 			       iov.iov_len);
569 		return false;
570 	}
571 
572 	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_ZA, &iov);
573 	if (ret != 0) {
574 		ksft_print_msg("Failed to read initial ZA: %s (%d)\n",
575 			       strerror(errno), errno);
576 		pass = false;
577 		goto out;
578 	}
579 
580 	za = iov.iov_base;
581 
582 	if (za->vl != config->sme_vl_in) {
583 		ksft_print_msg("Mismatch in initial SME VL: %d != %d\n",
584 			       za->vl, config->sme_vl_in);
585 		pass = false;
586 	}
587 
588 	/* If PSTATE.ZA is not set we should just read the header */
589 	if (config->svcr_in & SVCR_ZA) {
590 		if (za->size != ZA_PT_SIZE(vq)) {
591 			ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n",
592 				       za->size, ZA_PT_SIZE(vq));
593 			pass = false;
594 		}
595 
596 		if (!compare_buffer("initial ZA",
597 				    iov.iov_base + ZA_PT_ZA_OFFSET,
598 				    za_in, ZA_PT_ZA_SIZE(vq)))
599 			pass = false;
600 	} else {
601 		if (za->size != sizeof(*za)) {
602 			ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n",
603 				       za->size, sizeof(*za));
604 			pass = false;
605 		}
606 	}
607 
608 out:
609 	free(iov.iov_base);
610 	return pass;
611 }
612 
613 static bool check_ptrace_values_zt(pid_t child, struct test_config *config)
614 {
615 	uint8_t buf[512];
616 	struct iovec iov;
617 	int ret;
618 
619 	if (!sme2_supported())
620 		return true;
621 
622 	iov.iov_base = &buf;
623 	iov.iov_len = ZT_SIG_REG_BYTES;
624 	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_ZT, &iov);
625 	if (ret != 0) {
626 		ksft_print_msg("Failed to read initial ZT: %s (%d)\n",
627 			       strerror(errno), errno);
628 		return false;
629 	}
630 
631 	return compare_buffer("initial ZT", buf, zt_in, ZT_SIG_REG_BYTES);
632 }
633 
634 static bool check_ptrace_values_fpmr(pid_t child, struct test_config *config)
635 {
636 	uint64_t val;
637 	struct iovec iov;
638 	int ret;
639 
640 	if (!fpmr_supported())
641 		return true;
642 
643 	iov.iov_base = &val;
644 	iov.iov_len = sizeof(val);
645 	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_FPMR, &iov);
646 	if (ret != 0) {
647 		ksft_print_msg("Failed to read initial FPMR: %s (%d)\n",
648 			       strerror(errno), errno);
649 		return false;
650 	}
651 
652 	return compare_buffer("initial FPMR", &val, &fpmr_in, sizeof(val));
653 }
654 
655 static bool check_ptrace_values(pid_t child, struct test_config *config)
656 {
657 	bool pass = true;
658 	struct user_fpsimd_state fpsimd;
659 	struct iovec iov;
660 	int ret;
661 
662 	iov.iov_base = &fpsimd;
663 	iov.iov_len = sizeof(fpsimd);
664 	ret = ptrace(PTRACE_GETREGSET, child, NT_PRFPREG, &iov);
665 	if (ret == 0) {
666 		if (!compare_buffer("initial V", &fpsimd.vregs, v_in,
667 				    sizeof(v_in))) {
668 			pass = false;
669 		}
670 	} else {
671 		ksft_print_msg("Failed to read initial V: %s (%d)\n",
672 			       strerror(errno), errno);
673 		pass = false;
674 	}
675 
676 	if (!check_ptrace_values_sve(child, config))
677 		pass = false;
678 
679 	if (!check_ptrace_values_ssve(child, config))
680 		pass = false;
681 
682 	if (!check_ptrace_values_za(child, config))
683 		pass = false;
684 
685 	if (!check_ptrace_values_zt(child, config))
686 		pass = false;
687 
688 	if (!check_ptrace_values_fpmr(child, config))
689 		pass = false;
690 
691 	return pass;
692 }
693 
694 static bool run_parent(pid_t child, struct test_definition *test,
695 		       struct test_config *config)
696 {
697 	int wait_status, ret;
698 	pid_t pid;
699 	bool pass;
700 
701 	/* Initial attach */
702 	while (1) {
703 		pid = waitpid(child, &wait_status, 0);
704 		if (pid < 0) {
705 			if (errno == EINTR)
706 				continue;
707 			ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
708 					   strerror(errno), errno);
709 		}
710 
711 		if (pid == child)
712 			break;
713 	}
714 
715 	if (WIFEXITED(wait_status)) {
716 		ksft_print_msg("Child exited loading values with status %d\n",
717 			       WEXITSTATUS(wait_status));
718 		pass = false;
719 		goto out;
720 	}
721 
722 	if (WIFSIGNALED(wait_status)) {
723 		ksft_print_msg("Child died from signal %d loading values\n",
724 			       WTERMSIG(wait_status));
725 		pass = false;
726 		goto out;
727 	}
728 
729 	/* Read initial values via ptrace */
730 	pass = check_ptrace_values(child, config);
731 
732 	/* Do whatever writes we want to do */
733 	if (test->modify_values)
734 		test->modify_values(child, config);
735 
736 	if (!continue_breakpoint(child, PTRACE_CONT))
737 		goto cleanup;
738 
739 	while (1) {
740 		pid = waitpid(child, &wait_status, 0);
741 		if (pid < 0) {
742 			if (errno == EINTR)
743 				continue;
744 			ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
745 					   strerror(errno), errno);
746 		}
747 
748 		if (pid == child)
749 			break;
750 	}
751 
752 	if (WIFEXITED(wait_status)) {
753 		ksft_print_msg("Child exited saving values with status %d\n",
754 			       WEXITSTATUS(wait_status));
755 		pass = false;
756 		goto out;
757 	}
758 
759 	if (WIFSIGNALED(wait_status)) {
760 		ksft_print_msg("Child died from signal %d saving values\n",
761 			       WTERMSIG(wait_status));
762 		pass = false;
763 		goto out;
764 	}
765 
766 	/* See what happened as a result */
767 	read_child_regs(child);
768 
769 	if (!continue_breakpoint(child, PTRACE_DETACH))
770 		goto cleanup;
771 
772 	/* The child should exit cleanly */
773 	got_alarm = false;
774 	alarm(1);
775 	while (1) {
776 		if (got_alarm) {
777 			ksft_print_msg("Wait for child timed out\n");
778 			goto cleanup;
779 		}
780 
781 		pid = waitpid(child, &wait_status, 0);
782 		if (pid < 0) {
783 			if (errno == EINTR)
784 				continue;
785 			ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
786 					   strerror(errno), errno);
787 		}
788 
789 		if (pid == child)
790 			break;
791 	}
792 	alarm(0);
793 
794 	if (got_alarm) {
795 		ksft_print_msg("Timed out waiting for child\n");
796 		pass = false;
797 		goto cleanup;
798 	}
799 
800 	if (pid == child && WIFSIGNALED(wait_status)) {
801 		ksft_print_msg("Child died from signal %d cleaning up\n",
802 			       WTERMSIG(wait_status));
803 		pass = false;
804 		goto out;
805 	}
806 
807 	if (pid == child && WIFEXITED(wait_status)) {
808 		if (WEXITSTATUS(wait_status) != 0) {
809 			ksft_print_msg("Child exited with error %d\n",
810 				       WEXITSTATUS(wait_status));
811 			pass = false;
812 		}
813 	} else {
814 		ksft_print_msg("Child did not exit cleanly\n");
815 		pass = false;
816 		goto cleanup;
817 	}
818 
819 	goto out;
820 
821 cleanup:
822 	ret = kill(child, SIGKILL);
823 	if (ret != 0) {
824 		ksft_print_msg("kill() failed: %s (%d)\n",
825 			       strerror(errno), errno);
826 		return false;
827 	}
828 
829 	while (1) {
830 		pid = waitpid(child, &wait_status, 0);
831 		if (pid < 0) {
832 			if (errno == EINTR)
833 				continue;
834 			ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
835 					   strerror(errno), errno);
836 		}
837 
838 		if (pid == child)
839 			break;
840 	}
841 
842 out:
843 	return pass;
844 }
845 
846 static void fill_random(void *buf, size_t size)
847 {
848 	int i;
849 	uint32_t *lbuf = buf;
850 
851 	/* random() returns a 32 bit number regardless of the size of long */
852 	for (i = 0; i < size / sizeof(uint32_t); i++)
853 		lbuf[i] = random();
854 }
855 
856 static void fill_random_ffr(void *buf, size_t vq)
857 {
858 	uint8_t *lbuf = buf;
859 	int bits, i;
860 
861 	/*
862 	 * Only values with a continuous set of 0..n bits set are
863 	 * valid for FFR, set all bits then clear a random number of
864 	 * high bits.
865 	 */
866 	memset(buf, 0, __SVE_FFR_SIZE(vq));
867 
868 	bits = random() % (__SVE_FFR_SIZE(vq) * 8);
869 	for (i = 0; i < bits / 8; i++)
870 		lbuf[i] = 0xff;
871 	if (bits / 8 != __SVE_FFR_SIZE(vq))
872 		lbuf[i] = (1 << (bits % 8)) - 1;
873 }
874 
875 static void fpsimd_to_sve(__uint128_t *v, char *z, int vl)
876 {
877 	int vq = __sve_vq_from_vl(vl);
878 	int i;
879 	__uint128_t *p;
880 
881 	if (!vl)
882 		return;
883 
884 	for (i = 0; i < __SVE_NUM_ZREGS; i++) {
885 		p = (__uint128_t *)&z[__SVE_ZREG_OFFSET(vq, i)];
886 		*p = arm64_cpu_to_le128(v[i]);
887 	}
888 }
889 
890 static void set_initial_values(struct test_config *config)
891 {
892 	int vq = __sve_vq_from_vl(vl_in(config));
893 	int sme_vq = __sve_vq_from_vl(config->sme_vl_in);
894 	bool sm_change;
895 
896 	svcr_in = config->svcr_in;
897 	svcr_expected = config->svcr_expected;
898 	svcr_out = 0;
899 
900 	if (sme_supported() &&
901 	    (svcr_in & SVCR_SM) != (svcr_expected & SVCR_SM))
902 		sm_change = true;
903 	else
904 		sm_change = false;
905 
906 	fill_random(&v_in, sizeof(v_in));
907 	memcpy(v_expected, v_in, sizeof(v_in));
908 	memset(v_out, 0, sizeof(v_out));
909 
910 	/* Changes will be handled in the test case */
911 	if (sve_supported() || (config->svcr_in & SVCR_SM)) {
912 		/* The low 128 bits of Z are shared with the V registers */
913 		fill_random(&z_in, __SVE_ZREGS_SIZE(vq));
914 		fpsimd_to_sve(v_in, z_in, vl_in(config));
915 		memcpy(z_expected, z_in, __SVE_ZREGS_SIZE(vq));
916 		memset(z_out, 0, sizeof(z_out));
917 
918 		fill_random(&p_in, __SVE_PREGS_SIZE(vq));
919 		memcpy(p_expected, p_in, __SVE_PREGS_SIZE(vq));
920 		memset(p_out, 0, sizeof(p_out));
921 
922 		if ((config->svcr_in & SVCR_SM) && !fa64_supported())
923 			memset(ffr_in, 0, __SVE_PREG_SIZE(vq));
924 		else
925 			fill_random_ffr(&ffr_in, vq);
926 		memcpy(ffr_expected, ffr_in, __SVE_PREG_SIZE(vq));
927 		memset(ffr_out, 0, __SVE_PREG_SIZE(vq));
928 	}
929 
930 	if (config->svcr_in & SVCR_ZA)
931 		fill_random(za_in, ZA_SIG_REGS_SIZE(sme_vq));
932 	else
933 		memset(za_in, 0, ZA_SIG_REGS_SIZE(sme_vq));
934 	if (config->svcr_expected & SVCR_ZA)
935 		memcpy(za_expected, za_in, ZA_SIG_REGS_SIZE(sme_vq));
936 	else
937 		memset(za_expected, 0, ZA_SIG_REGS_SIZE(sme_vq));
938 	if (sme_supported())
939 		memset(za_out, 0, sizeof(za_out));
940 
941 	if (sme2_supported()) {
942 		if (config->svcr_in & SVCR_ZA)
943 			fill_random(zt_in, ZT_SIG_REG_BYTES);
944 		else
945 			memset(zt_in, 0, ZT_SIG_REG_BYTES);
946 		if (config->svcr_expected & SVCR_ZA)
947 			memcpy(zt_expected, zt_in, ZT_SIG_REG_BYTES);
948 		else
949 			memset(zt_expected, 0, ZT_SIG_REG_BYTES);
950 		memset(zt_out, 0, sizeof(zt_out));
951 	}
952 
953 	if (fpmr_supported()) {
954 		fill_random(&fpmr_in, sizeof(fpmr_in));
955 		fpmr_in &= FPMR_SAFE_BITS;
956 
957 		/* Entering or exiting streaming mode clears FPMR */
958 		if (sm_change)
959 			fpmr_expected = 0;
960 		else
961 			fpmr_expected = fpmr_in;
962 	} else {
963 		fpmr_in = 0;
964 		fpmr_expected = 0;
965 		fpmr_out = 0;
966 	}
967 }
968 
969 static bool check_memory_values(struct test_config *config)
970 {
971 	bool pass = true;
972 	int vq, sme_vq;
973 
974 	if (!compare_buffer("saved V", v_out, v_expected, sizeof(v_out)))
975 		pass = false;
976 
977 	vq = __sve_vq_from_vl(vl_expected(config));
978 	sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
979 
980 	if (svcr_out != svcr_expected) {
981 		ksft_print_msg("Mismatch in saved SVCR %lx != %lx\n",
982 			       svcr_out, svcr_expected);
983 		pass = false;
984 	}
985 
986 	if (sve_vl_out != config->sve_vl_expected) {
987 		ksft_print_msg("Mismatch in SVE VL: %ld != %d\n",
988 			       sve_vl_out, config->sve_vl_expected);
989 		pass = false;
990 	}
991 
992 	if (sme_vl_out != config->sme_vl_expected) {
993 		ksft_print_msg("Mismatch in SME VL: %ld != %d\n",
994 			       sme_vl_out, config->sme_vl_expected);
995 		pass = false;
996 	}
997 
998 	if (!compare_buffer("saved Z", z_out, z_expected,
999 			    __SVE_ZREGS_SIZE(vq)))
1000 		pass = false;
1001 
1002 	if (!compare_buffer("saved P", p_out, p_expected,
1003 			    __SVE_PREGS_SIZE(vq)))
1004 		pass = false;
1005 
1006 	if (!compare_buffer("saved FFR", ffr_out, ffr_expected,
1007 			    __SVE_PREG_SIZE(vq)))
1008 		pass = false;
1009 
1010 	if (!compare_buffer("saved ZA", za_out, za_expected,
1011 			    ZA_PT_ZA_SIZE(sme_vq)))
1012 		pass = false;
1013 
1014 	if (!compare_buffer("saved ZT", zt_out, zt_expected, ZT_SIG_REG_BYTES))
1015 		pass = false;
1016 
1017 	if (fpmr_out != fpmr_expected) {
1018 		ksft_print_msg("Mismatch in saved FPMR: %lx != %lx\n",
1019 			       fpmr_out, fpmr_expected);
1020 		pass = false;
1021 	}
1022 
1023 	return pass;
1024 }
1025 
1026 static bool sve_sme_same(struct test_config *config)
1027 {
1028 	if (config->sve_vl_in != config->sve_vl_expected)
1029 		return false;
1030 
1031 	if (config->sme_vl_in != config->sme_vl_expected)
1032 		return false;
1033 
1034 	if (config->svcr_in != config->svcr_expected)
1035 		return false;
1036 
1037 	return true;
1038 }
1039 
1040 static bool sve_write_supported(struct test_config *config)
1041 {
1042 	if (!sve_supported() && !sme_supported())
1043 		return false;
1044 
1045 	if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA))
1046 		return false;
1047 
1048 	if (config->svcr_expected & SVCR_SM) {
1049 		if (config->sve_vl_in != config->sve_vl_expected) {
1050 			return false;
1051 		}
1052 
1053 		/* Changing the SME VL disables ZA */
1054 		if ((config->svcr_expected & SVCR_ZA) &&
1055 		    (config->sme_vl_in != config->sme_vl_expected)) {
1056 			return false;
1057 		}
1058 	} else {
1059 		if (config->sme_vl_in != config->sme_vl_expected) {
1060 			return false;
1061 		}
1062 	}
1063 
1064 	return true;
1065 }
1066 
1067 static void fpsimd_write_expected(struct test_config *config)
1068 {
1069 	int vl;
1070 
1071 	fill_random(&v_expected, sizeof(v_expected));
1072 
1073 	/* The SVE registers are flushed by a FPSIMD write */
1074 	vl = vl_expected(config);
1075 
1076 	memset(z_expected, 0, __SVE_ZREGS_SIZE(__sve_vq_from_vl(vl)));
1077 	memset(p_expected, 0, __SVE_PREGS_SIZE(__sve_vq_from_vl(vl)));
1078 	memset(ffr_expected, 0, __SVE_PREG_SIZE(__sve_vq_from_vl(vl)));
1079 
1080 	fpsimd_to_sve(v_expected, z_expected, vl);
1081 }
1082 
1083 static void fpsimd_write(pid_t child, struct test_config *test_config)
1084 {
1085 	struct user_fpsimd_state fpsimd;
1086 	struct iovec iov;
1087 	int ret;
1088 
1089 	memset(&fpsimd, 0, sizeof(fpsimd));
1090 	memcpy(&fpsimd.vregs, v_expected, sizeof(v_expected));
1091 
1092 	iov.iov_base = &fpsimd;
1093 	iov.iov_len = sizeof(fpsimd);
1094 	ret = ptrace(PTRACE_SETREGSET, child, NT_PRFPREG, &iov);
1095 	if (ret == -1)
1096 		ksft_print_msg("FPSIMD set failed: (%s) %d\n",
1097 			       strerror(errno), errno);
1098 }
1099 
1100 static bool fpmr_write_supported(struct test_config *config)
1101 {
1102 	if (!fpmr_supported())
1103 		return false;
1104 
1105 	if (!sve_sme_same(config))
1106 		return false;
1107 
1108 	return true;
1109 }
1110 
1111 static void fpmr_write_expected(struct test_config *config)
1112 {
1113 	fill_random(&fpmr_expected, sizeof(fpmr_expected));
1114 	fpmr_expected &= FPMR_SAFE_BITS;
1115 }
1116 
1117 static void fpmr_write(pid_t child, struct test_config *config)
1118 {
1119 	struct iovec iov;
1120 	int ret;
1121 
1122 	iov.iov_len = sizeof(fpmr_expected);
1123 	iov.iov_base = &fpmr_expected;
1124 	ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_FPMR, &iov);
1125 	if (ret != 0)
1126 		ksft_print_msg("Failed to write FPMR: %s (%d)\n",
1127 			       strerror(errno), errno);
1128 }
1129 
1130 static void sve_write_expected(struct test_config *config)
1131 {
1132 	int vl = vl_expected(config);
1133 	int sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
1134 
1135 	fill_random(z_expected, __SVE_ZREGS_SIZE(__sve_vq_from_vl(vl)));
1136 	fill_random(p_expected, __SVE_PREGS_SIZE(__sve_vq_from_vl(vl)));
1137 
1138 	if ((svcr_expected & SVCR_SM) && !fa64_supported())
1139 		memset(ffr_expected, 0, __SVE_PREG_SIZE(sme_vq));
1140 	else
1141 		fill_random_ffr(ffr_expected, __sve_vq_from_vl(vl));
1142 
1143 	/* Share the low bits of Z with V */
1144 	fill_random(&v_expected, sizeof(v_expected));
1145 	fpsimd_to_sve(v_expected, z_expected, vl);
1146 
1147 	if (config->sme_vl_in != config->sme_vl_expected) {
1148 		memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq));
1149 		memset(zt_expected, 0, sizeof(zt_expected));
1150 	}
1151 }
1152 
1153 static void sve_write(pid_t child, struct test_config *config)
1154 {
1155 	struct user_sve_header *sve;
1156 	struct iovec iov;
1157 	int ret, vl, vq, regset;
1158 
1159 	vl = vl_expected(config);
1160 	vq = __sve_vq_from_vl(vl);
1161 
1162 	iov.iov_len = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
1163 	iov.iov_base = malloc(iov.iov_len);
1164 	if (!iov.iov_base) {
1165 		ksft_print_msg("Failed allocating %lu byte SVE write buffer\n",
1166 			       iov.iov_len);
1167 		return;
1168 	}
1169 	memset(iov.iov_base, 0, iov.iov_len);
1170 
1171 	sve = iov.iov_base;
1172 	sve->size = iov.iov_len;
1173 	sve->flags = SVE_PT_REGS_SVE;
1174 	sve->vl = vl;
1175 
1176 	memcpy(iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0),
1177 	       z_expected, SVE_PT_SVE_ZREGS_SIZE(vq));
1178 	memcpy(iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0),
1179 	       p_expected, SVE_PT_SVE_PREGS_SIZE(vq));
1180 	memcpy(iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq),
1181 	       ffr_expected, SVE_PT_SVE_PREG_SIZE(vq));
1182 
1183 	if (svcr_expected & SVCR_SM)
1184 		regset = NT_ARM_SSVE;
1185 	else
1186 		regset = NT_ARM_SVE;
1187 
1188 	ret = ptrace(PTRACE_SETREGSET, child, regset, &iov);
1189 	if (ret != 0)
1190 		ksft_print_msg("Failed to write SVE: %s (%d)\n",
1191 			       strerror(errno), errno);
1192 
1193 	free(iov.iov_base);
1194 }
1195 
1196 static bool za_write_supported(struct test_config *config)
1197 {
1198 	if (config->sme_vl_in != config->sme_vl_expected) {
1199 		/* Changing the SME VL exits streaming mode. */
1200 		if (config->svcr_expected & SVCR_SM) {
1201 			return false;
1202 		}
1203 	} else {
1204 		/* Otherwise we can't change streaming mode */
1205 		if ((config->svcr_in & SVCR_SM) !=
1206 		    (config->svcr_expected & SVCR_SM)) {
1207 			return false;
1208 		}
1209 	}
1210 
1211 	return true;
1212 }
1213 
1214 static void za_write_expected(struct test_config *config)
1215 {
1216 	int sme_vq, sve_vq;
1217 
1218 	sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
1219 
1220 	if (config->svcr_expected & SVCR_ZA) {
1221 		fill_random(za_expected, ZA_PT_ZA_SIZE(sme_vq));
1222 	} else {
1223 		memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq));
1224 		memset(zt_expected, 0, sizeof(zt_expected));
1225 	}
1226 
1227 	/* Changing the SME VL flushes ZT, SVE state and exits SM */
1228 	if (config->sme_vl_in != config->sme_vl_expected) {
1229 		svcr_expected &= ~SVCR_SM;
1230 
1231 		sve_vq = __sve_vq_from_vl(vl_expected(config));
1232 		memset(z_expected, 0, __SVE_ZREGS_SIZE(sve_vq));
1233 		memset(p_expected, 0, __SVE_PREGS_SIZE(sve_vq));
1234 		memset(ffr_expected, 0, __SVE_PREG_SIZE(sve_vq));
1235 		memset(zt_expected, 0, sizeof(zt_expected));
1236 
1237 		fpsimd_to_sve(v_expected, z_expected, vl_expected(config));
1238 	}
1239 }
1240 
1241 static void za_write(pid_t child, struct test_config *config)
1242 {
1243 	struct user_za_header *za;
1244 	struct iovec iov;
1245 	int ret, vq;
1246 
1247 	vq = __sve_vq_from_vl(config->sme_vl_expected);
1248 
1249 	if (config->svcr_expected & SVCR_ZA)
1250 		iov.iov_len = ZA_PT_SIZE(vq);
1251 	else
1252 		iov.iov_len = sizeof(*za);
1253 	iov.iov_base = malloc(iov.iov_len);
1254 	if (!iov.iov_base) {
1255 		ksft_print_msg("Failed allocating %lu byte ZA write buffer\n",
1256 			       iov.iov_len);
1257 		return;
1258 	}
1259 	memset(iov.iov_base, 0, iov.iov_len);
1260 
1261 	za = iov.iov_base;
1262 	za->size = iov.iov_len;
1263 	za->vl = config->sme_vl_expected;
1264 	if (config->svcr_expected & SVCR_ZA)
1265 		memcpy(iov.iov_base + ZA_PT_ZA_OFFSET, za_expected,
1266 		       ZA_PT_ZA_SIZE(vq));
1267 
1268 	ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_ZA, &iov);
1269 	if (ret != 0)
1270 		ksft_print_msg("Failed to write ZA: %s (%d)\n",
1271 			       strerror(errno), errno);
1272 
1273 	free(iov.iov_base);
1274 }
1275 
1276 static bool zt_write_supported(struct test_config *config)
1277 {
1278 	if (!sme2_supported())
1279 		return false;
1280 	if (config->sme_vl_in != config->sme_vl_expected)
1281 		return false;
1282 	if (!(config->svcr_expected & SVCR_ZA))
1283 		return false;
1284 	if ((config->svcr_in & SVCR_SM) != (config->svcr_expected & SVCR_SM))
1285 		return false;
1286 
1287 	return true;
1288 }
1289 
1290 static void zt_write_expected(struct test_config *config)
1291 {
1292 	int sme_vq;
1293 
1294 	sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
1295 
1296 	if (config->svcr_expected & SVCR_ZA) {
1297 		fill_random(zt_expected, sizeof(zt_expected));
1298 	} else {
1299 		memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq));
1300 		memset(zt_expected, 0, sizeof(zt_expected));
1301 	}
1302 }
1303 
1304 static void zt_write(pid_t child, struct test_config *config)
1305 {
1306 	struct iovec iov;
1307 	int ret;
1308 
1309 	iov.iov_len = ZT_SIG_REG_BYTES;
1310 	iov.iov_base = zt_expected;
1311 	ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_ZT, &iov);
1312 	if (ret != 0)
1313 		ksft_print_msg("Failed to write ZT: %s (%d)\n",
1314 			       strerror(errno), errno);
1315 }
1316 
1317 /* Actually run a test */
1318 static void run_test(struct test_definition *test, struct test_config *config)
1319 {
1320 	pid_t child;
1321 	char name[1024];
1322 	bool pass;
1323 
1324 	if (sve_supported() && sme_supported())
1325 		snprintf(name, sizeof(name), "%s, SVE %d->%d, SME %d/%x->%d/%x",
1326 			 test->name,
1327 			 config->sve_vl_in, config->sve_vl_expected,
1328 			 config->sme_vl_in, config->svcr_in,
1329 			 config->sme_vl_expected, config->svcr_expected);
1330 	else if (sve_supported())
1331 		snprintf(name, sizeof(name), "%s, SVE %d->%d", test->name,
1332 			 config->sve_vl_in, config->sve_vl_expected);
1333 	else if (sme_supported())
1334 		snprintf(name, sizeof(name), "%s, SME %d/%x->%d/%x",
1335 			 test->name,
1336 			 config->sme_vl_in, config->svcr_in,
1337 			 config->sme_vl_expected, config->svcr_expected);
1338 	else
1339 		snprintf(name, sizeof(name), "%s", test->name);
1340 
1341 	if (test->supported && !test->supported(config)) {
1342 		ksft_test_result_skip("%s\n", name);
1343 		return;
1344 	}
1345 
1346 	set_initial_values(config);
1347 
1348 	if (test->set_expected_values)
1349 		test->set_expected_values(config);
1350 
1351 	child = fork();
1352 	if (child < 0)
1353 		ksft_exit_fail_msg("fork() failed: %s (%d)\n",
1354 				   strerror(errno), errno);
1355 	/* run_child() never returns */
1356 	if (child == 0)
1357 		run_child(config);
1358 
1359 	pass = run_parent(child, test, config);
1360 	if (!check_memory_values(config))
1361 		pass = false;
1362 
1363 	ksft_test_result(pass, "%s\n", name);
1364 }
1365 
1366 static void run_tests(struct test_definition defs[], int count,
1367 		      struct test_config *config)
1368 {
1369 	int i;
1370 
1371 	for (i = 0; i < count; i++)
1372 		run_test(&defs[i], config);
1373 }
1374 
1375 static struct test_definition base_test_defs[] = {
1376 	{
1377 		.name = "No writes",
1378 		.supported = sve_sme_same,
1379 	},
1380 	{
1381 		.name = "FPSIMD write",
1382 		.supported = sve_sme_same,
1383 		.set_expected_values = fpsimd_write_expected,
1384 		.modify_values = fpsimd_write,
1385 	},
1386 	{
1387 		.name = "FPMR write",
1388 		.supported = fpmr_write_supported,
1389 		.set_expected_values = fpmr_write_expected,
1390 		.modify_values = fpmr_write,
1391 	},
1392 };
1393 
1394 static struct test_definition sve_test_defs[] = {
1395 	{
1396 		.name = "SVE write",
1397 		.supported = sve_write_supported,
1398 		.set_expected_values = sve_write_expected,
1399 		.modify_values = sve_write,
1400 	},
1401 };
1402 
1403 static struct test_definition za_test_defs[] = {
1404 	{
1405 		.name = "ZA write",
1406 		.supported = za_write_supported,
1407 		.set_expected_values = za_write_expected,
1408 		.modify_values = za_write,
1409 	},
1410 };
1411 
1412 static struct test_definition zt_test_defs[] = {
1413 	{
1414 		.name = "ZT write",
1415 		.supported = zt_write_supported,
1416 		.set_expected_values = zt_write_expected,
1417 		.modify_values = zt_write,
1418 	},
1419 };
1420 
1421 static int sve_vls[MAX_NUM_VLS], sme_vls[MAX_NUM_VLS];
1422 static int sve_vl_count, sme_vl_count;
1423 
1424 static void probe_vls(const char *name, int vls[], int *vl_count, int set_vl)
1425 {
1426 	unsigned int vq;
1427 	int vl;
1428 
1429 	*vl_count = 0;
1430 
1431 	for (vq = ARCH_VQ_MAX; vq > 0; vq /= 2) {
1432 		vl = prctl(set_vl, vq * 16);
1433 		if (vl == -1)
1434 			ksft_exit_fail_msg("SET_VL failed: %s (%d)\n",
1435 					   strerror(errno), errno);
1436 
1437 		vl &= PR_SVE_VL_LEN_MASK;
1438 
1439 		if (*vl_count && (vl == vls[*vl_count - 1]))
1440 			break;
1441 
1442 		vq = sve_vq_from_vl(vl);
1443 
1444 		vls[*vl_count] = vl;
1445 		*vl_count += 1;
1446 	}
1447 
1448 	if (*vl_count > 2) {
1449 		/* Just use the minimum and maximum */
1450 		vls[1] = vls[*vl_count - 1];
1451 		ksft_print_msg("%d %s VLs, using %d and %d\n",
1452 			       *vl_count, name, vls[0], vls[1]);
1453 		*vl_count = 2;
1454 	} else {
1455 		ksft_print_msg("%d %s VLs\n", *vl_count, name);
1456 	}
1457 }
1458 
1459 static struct {
1460 	int svcr_in, svcr_expected;
1461 } svcr_combinations[] = {
1462 	{ .svcr_in = 0, .svcr_expected = 0, },
1463 	{ .svcr_in = 0, .svcr_expected = SVCR_SM, },
1464 	{ .svcr_in = 0, .svcr_expected = SVCR_ZA, },
1465 	/* Can't enable both SM and ZA with a single ptrace write */
1466 
1467 	{ .svcr_in = SVCR_SM, .svcr_expected = 0, },
1468 	{ .svcr_in = SVCR_SM, .svcr_expected = SVCR_SM, },
1469 	{ .svcr_in = SVCR_SM, .svcr_expected = SVCR_ZA, },
1470 	{ .svcr_in = SVCR_SM, .svcr_expected = SVCR_SM | SVCR_ZA, },
1471 
1472 	{ .svcr_in = SVCR_ZA, .svcr_expected = 0, },
1473 	{ .svcr_in = SVCR_ZA, .svcr_expected = SVCR_SM, },
1474 	{ .svcr_in = SVCR_ZA, .svcr_expected = SVCR_ZA, },
1475 	{ .svcr_in = SVCR_ZA, .svcr_expected = SVCR_SM | SVCR_ZA, },
1476 
1477 	{ .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = 0, },
1478 	{ .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_SM, },
1479 	{ .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_ZA, },
1480 	{ .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_SM | SVCR_ZA, },
1481 };
1482 
1483 static void run_sve_tests(void)
1484 {
1485 	struct test_config test_config;
1486 	int i, j;
1487 
1488 	if (!sve_supported())
1489 		return;
1490 
1491 	test_config.sme_vl_in = sme_vls[0];
1492 	test_config.sme_vl_expected = sme_vls[0];
1493 	test_config.svcr_in = 0;
1494 	test_config.svcr_expected = 0;
1495 
1496 	for (i = 0; i < sve_vl_count; i++) {
1497 		test_config.sve_vl_in = sve_vls[i];
1498 
1499 		for (j = 0; j < sve_vl_count; j++) {
1500 			test_config.sve_vl_expected = sve_vls[j];
1501 
1502 			run_tests(base_test_defs,
1503 				  ARRAY_SIZE(base_test_defs),
1504 				  &test_config);
1505 			if (sve_supported())
1506 				run_tests(sve_test_defs,
1507 					  ARRAY_SIZE(sve_test_defs),
1508 					  &test_config);
1509 		}
1510 	}
1511 
1512 }
1513 
1514 static void run_sme_tests(void)
1515 {
1516 	struct test_config test_config;
1517 	int i, j, k;
1518 
1519 	if (!sme_supported())
1520 		return;
1521 
1522 	test_config.sve_vl_in = sve_vls[0];
1523 	test_config.sve_vl_expected = sve_vls[0];
1524 
1525 	/*
1526 	 * Every SME VL/SVCR combination
1527 	 */
1528 	for (i = 0; i < sme_vl_count; i++) {
1529 		test_config.sme_vl_in = sme_vls[i];
1530 
1531 		for (j = 0; j < sme_vl_count; j++) {
1532 			test_config.sme_vl_expected = sme_vls[j];
1533 
1534 			for (k = 0; k < ARRAY_SIZE(svcr_combinations); k++) {
1535 				test_config.svcr_in = svcr_combinations[k].svcr_in;
1536 				test_config.svcr_expected = svcr_combinations[k].svcr_expected;
1537 
1538 				run_tests(base_test_defs,
1539 					  ARRAY_SIZE(base_test_defs),
1540 					  &test_config);
1541 				run_tests(sve_test_defs,
1542 					  ARRAY_SIZE(sve_test_defs),
1543 					  &test_config);
1544 				run_tests(za_test_defs,
1545 					  ARRAY_SIZE(za_test_defs),
1546 					  &test_config);
1547 
1548 				if (sme2_supported())
1549 					run_tests(zt_test_defs,
1550 						  ARRAY_SIZE(zt_test_defs),
1551 						  &test_config);
1552 			}
1553 		}
1554 	}
1555 }
1556 
1557 int main(void)
1558 {
1559 	struct test_config test_config;
1560 	struct sigaction sa;
1561 	int tests, ret, tmp;
1562 
1563 	srandom(getpid());
1564 
1565 	ksft_print_header();
1566 
1567 	if (sve_supported()) {
1568 		probe_vls("SVE", sve_vls, &sve_vl_count, PR_SVE_SET_VL);
1569 
1570 		tests = ARRAY_SIZE(base_test_defs) +
1571 			ARRAY_SIZE(sve_test_defs);
1572 		tests *= sve_vl_count * sve_vl_count;
1573 	} else {
1574 		/* Only run the FPSIMD tests */
1575 		sve_vl_count = 1;
1576 		tests = ARRAY_SIZE(base_test_defs);
1577 	}
1578 
1579 	if (sme_supported()) {
1580 		probe_vls("SME", sme_vls, &sme_vl_count, PR_SME_SET_VL);
1581 
1582 		tmp = ARRAY_SIZE(base_test_defs) + ARRAY_SIZE(sve_test_defs)
1583 			+ ARRAY_SIZE(za_test_defs);
1584 
1585 		if (sme2_supported())
1586 			tmp += ARRAY_SIZE(zt_test_defs);
1587 
1588 		tmp *= sme_vl_count * sme_vl_count;
1589 		tmp *= ARRAY_SIZE(svcr_combinations);
1590 		tests += tmp;
1591 	} else {
1592 		sme_vl_count = 1;
1593 	}
1594 
1595 	if (sme2_supported())
1596 		ksft_print_msg("SME2 supported\n");
1597 
1598 	if (fa64_supported())
1599 		ksft_print_msg("FA64 supported\n");
1600 
1601 	if (fpmr_supported())
1602 		ksft_print_msg("FPMR supported\n");
1603 
1604 	ksft_set_plan(tests);
1605 
1606 	/* Get signal handers ready before we start any children */
1607 	memset(&sa, 0, sizeof(sa));
1608 	sa.sa_sigaction = handle_alarm;
1609 	sa.sa_flags = SA_RESTART | SA_SIGINFO;
1610 	sigemptyset(&sa.sa_mask);
1611 	ret = sigaction(SIGALRM, &sa, NULL);
1612 	if (ret < 0)
1613 		ksft_print_msg("Failed to install SIGALRM handler: %s (%d)\n",
1614 			       strerror(errno), errno);
1615 
1616 	/*
1617 	 * Run the test set if there is no SVE or SME, with those we
1618 	 * have to pick a VL for each run.
1619 	 */
1620 	if (!sve_supported()) {
1621 		test_config.sve_vl_in = 0;
1622 		test_config.sve_vl_expected = 0;
1623 		test_config.sme_vl_in = 0;
1624 		test_config.sme_vl_expected = 0;
1625 		test_config.svcr_in = 0;
1626 		test_config.svcr_expected = 0;
1627 
1628 		run_tests(base_test_defs, ARRAY_SIZE(base_test_defs),
1629 			  &test_config);
1630 	}
1631 
1632 	run_sve_tests();
1633 	run_sme_tests();
1634 
1635 	ksft_finished();
1636 }
1637