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 /* Sentinel for detecting buffer bytes the kernel did not write */
69 #define REGSET_SENTINEL 0xa5
70
71 /*
72 * FPMR bits we can set without doing feature checks to see if values
73 * are valid.
74 */
75 #define FPMR_SAFE_BITS (FPMR_LSCALE2_MASK | FPMR_NSCALE_MASK | \
76 FPMR_LSCALE_MASK | FPMR_OSC_MASK | FPMR_OSM_MASK)
77
78 #define NUM_FPR 32
79 __uint128_t v_in[NUM_FPR];
80 __uint128_t v_expected[NUM_FPR];
81 __uint128_t v_out[NUM_FPR];
82
83 char z_in[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)];
84 char z_expected[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)];
85 char z_out[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)];
86
87 char p_in[__SVE_PREGS_SIZE(ARCH_VQ_MAX)];
88 char p_expected[__SVE_PREGS_SIZE(ARCH_VQ_MAX)];
89 char p_out[__SVE_PREGS_SIZE(ARCH_VQ_MAX)];
90
91 char ffr_in[__SVE_PREG_SIZE(ARCH_VQ_MAX)];
92 char ffr_expected[__SVE_PREG_SIZE(ARCH_VQ_MAX)];
93 char ffr_out[__SVE_PREG_SIZE(ARCH_VQ_MAX)];
94
95 char za_in[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)];
96 char za_expected[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)];
97 char za_out[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)];
98
99 char zt_in[ZT_SIG_REG_BYTES];
100 char zt_expected[ZT_SIG_REG_BYTES];
101 char zt_out[ZT_SIG_REG_BYTES];
102
103 uint64_t fpmr_in, fpmr_expected, fpmr_out;
104
105 uint64_t sve_vl_out;
106 uint64_t sme_vl_out;
107 uint64_t svcr_in, svcr_expected, svcr_out;
108
109 void load_and_save(int flags);
110
111 static bool got_alarm;
112
handle_alarm(int sig,siginfo_t * info,void * context)113 static void handle_alarm(int sig, siginfo_t *info, void *context)
114 {
115 got_alarm = true;
116 }
117
sve_supported(void)118 static bool sve_supported(void)
119 {
120 return getauxval(AT_HWCAP) & HWCAP_SVE;
121 }
122
sme_supported(void)123 static bool sme_supported(void)
124 {
125 return getauxval(AT_HWCAP2) & HWCAP2_SME;
126 }
127
sme2_supported(void)128 static bool sme2_supported(void)
129 {
130 return getauxval(AT_HWCAP2) & HWCAP2_SME2;
131 }
132
fa64_supported(void)133 static bool fa64_supported(void)
134 {
135 return getauxval(AT_HWCAP2) & HWCAP2_SME_FA64;
136 }
137
fpmr_supported(void)138 static bool fpmr_supported(void)
139 {
140 return getauxval(AT_HWCAP2) & HWCAP2_FPMR;
141 }
142
compare_buffer(const char * name,void * out,void * expected,size_t size)143 static bool compare_buffer(const char *name, void *out,
144 void *expected, size_t size)
145 {
146 void *tmp;
147
148 if (memcmp(out, expected, size) == 0)
149 return true;
150
151 ksft_print_msg("Mismatch in %s\n", name);
152
153 /* Did we just get zeros back? */
154 tmp = malloc(size);
155 if (!tmp) {
156 ksft_print_msg("OOM allocating %lu bytes for %s\n",
157 size, name);
158 ksft_exit_fail();
159 }
160 memset(tmp, 0, size);
161
162 if (memcmp(out, tmp, size) == 0)
163 ksft_print_msg("%s is zero\n", name);
164
165 free(tmp);
166
167 return false;
168 }
169
buffer_is_filled(const void * buffer,size_t size,unsigned char value)170 static bool buffer_is_filled(const void *buffer, size_t size,
171 unsigned char value)
172 {
173 const unsigned char *bytes = buffer;
174 size_t i;
175
176 for (i = 0; i < size; i++) {
177 if (bytes[i] != value)
178 return false;
179 }
180
181 return true;
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
vl_in(struct test_config * config)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
vl_expected(struct test_config * config)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
run_child(struct test_config * config)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
read_one_child_regs(pid_t child,char * name,struct iovec * iov_parent,struct iovec * iov_child)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
read_child_regs(pid_t child)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
continue_breakpoint(pid_t child,enum __ptrace_request restart_type)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
check_ptrace_values_sve(pid_t child,struct test_config * config)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 size_t buf_size;
405 int ret, vq;
406 bool pass = true;
407
408 if (!sve_supported())
409 return true;
410
411 vq = __sve_vq_from_vl(config->sve_vl_in);
412
413 buf_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
414 iov.iov_len = buf_size;
415 iov.iov_base = malloc(buf_size);
416 if (!iov.iov_base) {
417 ksft_print_msg("OOM allocating %lu byte SVE buffer\n",
418 iov.iov_len);
419 return false;
420 }
421
422 memset(iov.iov_base, REGSET_SENTINEL, buf_size);
423 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_SVE, &iov);
424 if (ret != 0) {
425 ksft_print_msg("Failed to read initial SVE: %s (%d)\n",
426 strerror(errno), errno);
427 pass = false;
428 goto out;
429 }
430
431 sve = iov.iov_base;
432
433 if (sve->vl != config->sve_vl_in) {
434 ksft_print_msg("Mismatch in initial SVE VL: %d != %d\n",
435 sve->vl, config->sve_vl_in);
436 pass = false;
437 }
438
439 /* If we are in streaming mode we should just read FPSIMD */
440 if ((config->svcr_in & SVCR_SM) && (sve->flags & SVE_PT_REGS_SVE)) {
441 ksft_print_msg("NT_ARM_SVE reports SVE with PSTATE.SM\n");
442 pass = false;
443 }
444
445 if (svcr_in & SVCR_SM) {
446 if (sve->size != sizeof(*sve)) {
447 ksft_print_msg("NT_ARM_SVE reports data with PSTATE.SM\n");
448 pass = false;
449 }
450 if (!buffer_is_filled(iov.iov_base + sizeof(*sve),
451 buf_size - sizeof(*sve), REGSET_SENTINEL)) {
452 ksft_print_msg("NT_ARM_SVE wrote beyond its header with PSTATE.SM\n");
453 pass = false;
454 }
455 goto out;
456 } else {
457 if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
458 ksft_print_msg("Mismatch in SVE header size: %d != %lu\n",
459 sve->size, SVE_PT_SIZE(vq, sve->flags));
460 pass = false;
461 }
462 }
463
464 /* The registers might be in completely different formats! */
465 if (sve->flags & SVE_PT_REGS_SVE) {
466 if (!compare_buffer("initial SVE Z",
467 iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0),
468 z_in, SVE_PT_SVE_ZREGS_SIZE(vq)))
469 pass = false;
470
471 if (!compare_buffer("initial SVE P",
472 iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0),
473 p_in, SVE_PT_SVE_PREGS_SIZE(vq)))
474 pass = false;
475
476 if (!compare_buffer("initial SVE FFR",
477 iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq),
478 ffr_in, SVE_PT_SVE_PREG_SIZE(vq)))
479 pass = false;
480 } else {
481 fpsimd = iov.iov_base + SVE_PT_FPSIMD_OFFSET;
482 if (!compare_buffer("initial V via SVE", &fpsimd->vregs[0],
483 v_in, sizeof(v_in)))
484 pass = false;
485 }
486
487 out:
488 free(iov.iov_base);
489 return pass;
490 }
491
check_ptrace_values_ssve(pid_t child,struct test_config * config)492 static bool check_ptrace_values_ssve(pid_t child, struct test_config *config)
493 {
494 struct user_sve_header *sve;
495 struct user_fpsimd_state *fpsimd;
496 struct iovec iov;
497 size_t buf_size;
498 int ret, vq;
499 bool pass = true;
500
501 if (!sme_supported())
502 return true;
503
504 vq = __sve_vq_from_vl(config->sme_vl_in);
505
506 buf_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
507 iov.iov_len = buf_size;
508 iov.iov_base = malloc(buf_size);
509 if (!iov.iov_base) {
510 ksft_print_msg("OOM allocating %lu byte SSVE buffer\n",
511 iov.iov_len);
512 return false;
513 }
514
515 memset(iov.iov_base, REGSET_SENTINEL, buf_size);
516 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_SSVE, &iov);
517 if (ret != 0) {
518 ksft_print_msg("Failed to read initial SSVE: %s (%d)\n",
519 strerror(errno), errno);
520 pass = false;
521 goto out;
522 }
523
524 sve = iov.iov_base;
525
526 if (sve->vl != config->sme_vl_in) {
527 ksft_print_msg("Mismatch in initial SSVE VL: %d != %d\n",
528 sve->vl, config->sme_vl_in);
529 pass = false;
530 }
531
532 if ((config->svcr_in & SVCR_SM) && !(sve->flags & SVE_PT_REGS_SVE)) {
533 ksft_print_msg("NT_ARM_SSVE reports FPSIMD with PSTATE.SM\n");
534 pass = false;
535 }
536
537 if (!(svcr_in & SVCR_SM)) {
538 if (sve->size != sizeof(*sve)) {
539 ksft_print_msg("NT_ARM_SSVE reports data without PSTATE.SM\n");
540 pass = false;
541 }
542 if (!buffer_is_filled(iov.iov_base + sizeof(*sve),
543 buf_size - sizeof(*sve), REGSET_SENTINEL)) {
544 ksft_print_msg("NT_ARM_SSVE wrote beyond its header without PSTATE.SM\n");
545 pass = false;
546 }
547 goto out;
548 } else {
549 if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
550 ksft_print_msg("Mismatch in SSVE header size: %d != %lu\n",
551 sve->size, SVE_PT_SIZE(vq, sve->flags));
552 pass = false;
553 }
554 }
555
556 /* The registers might be in completely different formats! */
557 if (sve->flags & SVE_PT_REGS_SVE) {
558 if (!compare_buffer("initial SSVE Z",
559 iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0),
560 z_in, SVE_PT_SVE_ZREGS_SIZE(vq)))
561 pass = false;
562
563 if (!compare_buffer("initial SSVE P",
564 iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0),
565 p_in, SVE_PT_SVE_PREGS_SIZE(vq)))
566 pass = false;
567
568 if (!compare_buffer("initial SSVE FFR",
569 iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq),
570 ffr_in, SVE_PT_SVE_PREG_SIZE(vq)))
571 pass = false;
572 } else {
573 fpsimd = iov.iov_base + SVE_PT_FPSIMD_OFFSET;
574 if (!compare_buffer("initial V via SSVE",
575 &fpsimd->vregs[0], v_in, sizeof(v_in)))
576 pass = false;
577 }
578
579 out:
580 free(iov.iov_base);
581 return pass;
582 }
583
check_ptrace_values_za(pid_t child,struct test_config * config)584 static bool check_ptrace_values_za(pid_t child, struct test_config *config)
585 {
586 struct user_za_header *za;
587 struct iovec iov;
588 int ret, vq;
589 bool pass = true;
590
591 if (!sme_supported())
592 return true;
593
594 vq = __sve_vq_from_vl(config->sme_vl_in);
595
596 iov.iov_len = ZA_SIG_CONTEXT_SIZE(vq);
597 iov.iov_base = malloc(iov.iov_len);
598 if (!iov.iov_base) {
599 ksft_print_msg("OOM allocating %lu byte ZA buffer\n",
600 iov.iov_len);
601 return false;
602 }
603
604 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_ZA, &iov);
605 if (ret != 0) {
606 ksft_print_msg("Failed to read initial ZA: %s (%d)\n",
607 strerror(errno), errno);
608 pass = false;
609 goto out;
610 }
611
612 za = iov.iov_base;
613
614 if (za->vl != config->sme_vl_in) {
615 ksft_print_msg("Mismatch in initial SME VL: %d != %d\n",
616 za->vl, config->sme_vl_in);
617 pass = false;
618 }
619
620 /* If PSTATE.ZA is not set we should just read the header */
621 if (config->svcr_in & SVCR_ZA) {
622 if (za->size != ZA_PT_SIZE(vq)) {
623 ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n",
624 za->size, ZA_PT_SIZE(vq));
625 pass = false;
626 }
627
628 if (!compare_buffer("initial ZA",
629 iov.iov_base + ZA_PT_ZA_OFFSET,
630 za_in, ZA_PT_ZA_SIZE(vq)))
631 pass = false;
632 } else {
633 if (za->size != sizeof(*za)) {
634 ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n",
635 za->size, sizeof(*za));
636 pass = false;
637 }
638 }
639
640 out:
641 free(iov.iov_base);
642 return pass;
643 }
644
check_ptrace_values_zt(pid_t child,struct test_config * config)645 static bool check_ptrace_values_zt(pid_t child, struct test_config *config)
646 {
647 uint8_t buf[512];
648 struct iovec iov;
649 int ret;
650
651 if (!sme2_supported())
652 return true;
653
654 iov.iov_base = &buf;
655 iov.iov_len = ZT_SIG_REG_BYTES;
656 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_ZT, &iov);
657 if (ret != 0) {
658 ksft_print_msg("Failed to read initial ZT: %s (%d)\n",
659 strerror(errno), errno);
660 return false;
661 }
662
663 return compare_buffer("initial ZT", buf, zt_in, ZT_SIG_REG_BYTES);
664 }
665
check_ptrace_values_fpmr(pid_t child,struct test_config * config)666 static bool check_ptrace_values_fpmr(pid_t child, struct test_config *config)
667 {
668 uint64_t val;
669 struct iovec iov;
670 int ret;
671
672 if (!fpmr_supported())
673 return true;
674
675 iov.iov_base = &val;
676 iov.iov_len = sizeof(val);
677 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_FPMR, &iov);
678 if (ret != 0) {
679 ksft_print_msg("Failed to read initial FPMR: %s (%d)\n",
680 strerror(errno), errno);
681 return false;
682 }
683
684 return compare_buffer("initial FPMR", &val, &fpmr_in, sizeof(val));
685 }
686
check_ptrace_values(pid_t child,struct test_config * config)687 static bool check_ptrace_values(pid_t child, struct test_config *config)
688 {
689 bool pass = true;
690 struct user_fpsimd_state fpsimd;
691 struct iovec iov;
692 int ret;
693
694 iov.iov_base = &fpsimd;
695 iov.iov_len = sizeof(fpsimd);
696 ret = ptrace(PTRACE_GETREGSET, child, NT_PRFPREG, &iov);
697 if (ret == 0) {
698 if (!compare_buffer("initial V", &fpsimd.vregs, v_in,
699 sizeof(v_in))) {
700 pass = false;
701 }
702 } else {
703 ksft_print_msg("Failed to read initial V: %s (%d)\n",
704 strerror(errno), errno);
705 pass = false;
706 }
707
708 if (!check_ptrace_values_sve(child, config))
709 pass = false;
710
711 if (!check_ptrace_values_ssve(child, config))
712 pass = false;
713
714 if (!check_ptrace_values_za(child, config))
715 pass = false;
716
717 if (!check_ptrace_values_zt(child, config))
718 pass = false;
719
720 if (!check_ptrace_values_fpmr(child, config))
721 pass = false;
722
723 return pass;
724 }
725
run_parent(pid_t child,struct test_definition * test,struct test_config * config)726 static bool run_parent(pid_t child, struct test_definition *test,
727 struct test_config *config)
728 {
729 int wait_status, ret;
730 pid_t pid;
731 bool pass;
732
733 /* Initial attach */
734 while (1) {
735 pid = waitpid(child, &wait_status, 0);
736 if (pid < 0) {
737 if (errno == EINTR)
738 continue;
739 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
740 strerror(errno), errno);
741 }
742
743 if (pid == child)
744 break;
745 }
746
747 if (WIFEXITED(wait_status)) {
748 ksft_print_msg("Child exited loading values with status %d\n",
749 WEXITSTATUS(wait_status));
750 pass = false;
751 goto out;
752 }
753
754 if (WIFSIGNALED(wait_status)) {
755 ksft_print_msg("Child died from signal %d loading values\n",
756 WTERMSIG(wait_status));
757 pass = false;
758 goto out;
759 }
760
761 /* Read initial values via ptrace */
762 pass = check_ptrace_values(child, config);
763
764 /* Do whatever writes we want to do */
765 if (test->modify_values)
766 test->modify_values(child, config);
767
768 if (!continue_breakpoint(child, PTRACE_CONT))
769 goto cleanup;
770
771 while (1) {
772 pid = waitpid(child, &wait_status, 0);
773 if (pid < 0) {
774 if (errno == EINTR)
775 continue;
776 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
777 strerror(errno), errno);
778 }
779
780 if (pid == child)
781 break;
782 }
783
784 if (WIFEXITED(wait_status)) {
785 ksft_print_msg("Child exited saving values with status %d\n",
786 WEXITSTATUS(wait_status));
787 pass = false;
788 goto out;
789 }
790
791 if (WIFSIGNALED(wait_status)) {
792 ksft_print_msg("Child died from signal %d saving values\n",
793 WTERMSIG(wait_status));
794 pass = false;
795 goto out;
796 }
797
798 /* See what happened as a result */
799 read_child_regs(child);
800
801 if (!continue_breakpoint(child, PTRACE_DETACH))
802 goto cleanup;
803
804 /* The child should exit cleanly */
805 got_alarm = false;
806 alarm(1);
807 while (1) {
808 if (got_alarm) {
809 ksft_print_msg("Wait for child timed out\n");
810 goto cleanup;
811 }
812
813 pid = waitpid(child, &wait_status, 0);
814 if (pid < 0) {
815 if (errno == EINTR)
816 continue;
817 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
818 strerror(errno), errno);
819 }
820
821 if (pid == child)
822 break;
823 }
824 alarm(0);
825
826 if (got_alarm) {
827 ksft_print_msg("Timed out waiting for child\n");
828 pass = false;
829 goto cleanup;
830 }
831
832 if (pid == child && WIFSIGNALED(wait_status)) {
833 ksft_print_msg("Child died from signal %d cleaning up\n",
834 WTERMSIG(wait_status));
835 pass = false;
836 goto out;
837 }
838
839 if (pid == child && WIFEXITED(wait_status)) {
840 if (WEXITSTATUS(wait_status) != 0) {
841 ksft_print_msg("Child exited with error %d\n",
842 WEXITSTATUS(wait_status));
843 pass = false;
844 }
845 } else {
846 ksft_print_msg("Child did not exit cleanly\n");
847 pass = false;
848 goto cleanup;
849 }
850
851 goto out;
852
853 cleanup:
854 ret = kill(child, SIGKILL);
855 if (ret != 0) {
856 ksft_print_msg("kill() failed: %s (%d)\n",
857 strerror(errno), errno);
858 return false;
859 }
860
861 while (1) {
862 pid = waitpid(child, &wait_status, 0);
863 if (pid < 0) {
864 if (errno == EINTR)
865 continue;
866 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
867 strerror(errno), errno);
868 }
869
870 if (pid == child)
871 break;
872 }
873
874 out:
875 return pass;
876 }
877
fill_random(void * buf,size_t size)878 static void fill_random(void *buf, size_t size)
879 {
880 int i;
881 uint32_t *lbuf = buf;
882
883 /* random() returns a 32 bit number regardless of the size of long */
884 for (i = 0; i < size / sizeof(uint32_t); i++)
885 lbuf[i] = random();
886 }
887
fill_random_ffr(void * buf,size_t vq)888 static void fill_random_ffr(void *buf, size_t vq)
889 {
890 uint8_t *lbuf = buf;
891 int bits, i;
892
893 /*
894 * Only values with a continuous set of 0..n bits set are
895 * valid for FFR, set all bits then clear a random number of
896 * high bits.
897 */
898 memset(buf, 0, __SVE_FFR_SIZE(vq));
899
900 bits = random() % (__SVE_FFR_SIZE(vq) * 8);
901 for (i = 0; i < bits / 8; i++)
902 lbuf[i] = 0xff;
903 if (bits / 8 != __SVE_FFR_SIZE(vq))
904 lbuf[i] = (1 << (bits % 8)) - 1;
905 }
906
fpsimd_to_sve(__uint128_t * v,char * z,int vl)907 static void fpsimd_to_sve(__uint128_t *v, char *z, int vl)
908 {
909 int vq = __sve_vq_from_vl(vl);
910 int i;
911 __uint128_t *p;
912
913 if (!vl)
914 return;
915
916 for (i = 0; i < __SVE_NUM_ZREGS; i++) {
917 p = (__uint128_t *)&z[__SVE_ZREG_OFFSET(vq, i)];
918 *p = v[i];
919 }
920 }
921
set_initial_values(struct test_config * config)922 static void set_initial_values(struct test_config *config)
923 {
924 int vq = __sve_vq_from_vl(vl_in(config));
925 int sme_vq = __sve_vq_from_vl(config->sme_vl_in);
926
927 svcr_in = config->svcr_in;
928 svcr_expected = config->svcr_expected;
929 svcr_out = 0;
930
931 fill_random(&v_in, sizeof(v_in));
932 memcpy(v_expected, v_in, sizeof(v_in));
933 memset(v_out, 0, sizeof(v_out));
934
935 /* Changes will be handled in the test case */
936 if (sve_supported() || (config->svcr_in & SVCR_SM)) {
937 /* The low 128 bits of Z are shared with the V registers */
938 fill_random(&z_in, __SVE_ZREGS_SIZE(vq));
939 fpsimd_to_sve(v_in, z_in, vl_in(config));
940 memcpy(z_expected, z_in, __SVE_ZREGS_SIZE(vq));
941 memset(z_out, 0, sizeof(z_out));
942
943 fill_random(&p_in, __SVE_PREGS_SIZE(vq));
944 memcpy(p_expected, p_in, __SVE_PREGS_SIZE(vq));
945 memset(p_out, 0, sizeof(p_out));
946
947 if ((config->svcr_in & SVCR_SM) && !fa64_supported())
948 memset(ffr_in, 0, __SVE_PREG_SIZE(vq));
949 else
950 fill_random_ffr(&ffr_in, vq);
951 memcpy(ffr_expected, ffr_in, __SVE_PREG_SIZE(vq));
952 memset(ffr_out, 0, __SVE_PREG_SIZE(vq));
953 }
954
955 if (config->svcr_in & SVCR_ZA)
956 fill_random(za_in, ZA_SIG_REGS_SIZE(sme_vq));
957 else
958 memset(za_in, 0, ZA_SIG_REGS_SIZE(sme_vq));
959 if (config->svcr_expected & SVCR_ZA)
960 memcpy(za_expected, za_in, ZA_SIG_REGS_SIZE(sme_vq));
961 else
962 memset(za_expected, 0, ZA_SIG_REGS_SIZE(sme_vq));
963 if (sme_supported())
964 memset(za_out, 0, sizeof(za_out));
965
966 if (sme2_supported()) {
967 if (config->svcr_in & SVCR_ZA)
968 fill_random(zt_in, ZT_SIG_REG_BYTES);
969 else
970 memset(zt_in, 0, ZT_SIG_REG_BYTES);
971 if (config->svcr_expected & SVCR_ZA)
972 memcpy(zt_expected, zt_in, ZT_SIG_REG_BYTES);
973 else
974 memset(zt_expected, 0, ZT_SIG_REG_BYTES);
975 memset(zt_out, 0, sizeof(zt_out));
976 }
977
978 if (fpmr_supported()) {
979 fill_random(&fpmr_in, sizeof(fpmr_in));
980 fpmr_in &= FPMR_SAFE_BITS;
981 fpmr_expected = fpmr_in;
982 } else {
983 fpmr_in = 0;
984 fpmr_expected = 0;
985 fpmr_out = 0;
986 }
987 }
988
check_memory_values(struct test_config * config)989 static bool check_memory_values(struct test_config *config)
990 {
991 bool pass = true;
992 int vq, sme_vq;
993
994 if (!compare_buffer("saved V", v_out, v_expected, sizeof(v_out)))
995 pass = false;
996
997 vq = __sve_vq_from_vl(vl_expected(config));
998 sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
999
1000 if (svcr_out != svcr_expected) {
1001 ksft_print_msg("Mismatch in saved SVCR %lx != %lx\n",
1002 svcr_out, svcr_expected);
1003 pass = false;
1004 }
1005
1006 if (sve_vl_out != config->sve_vl_expected) {
1007 ksft_print_msg("Mismatch in SVE VL: %ld != %d\n",
1008 sve_vl_out, config->sve_vl_expected);
1009 pass = false;
1010 }
1011
1012 if (sme_vl_out != config->sme_vl_expected) {
1013 ksft_print_msg("Mismatch in SME VL: %ld != %d\n",
1014 sme_vl_out, config->sme_vl_expected);
1015 pass = false;
1016 }
1017
1018 if (!compare_buffer("saved Z", z_out, z_expected,
1019 __SVE_ZREGS_SIZE(vq)))
1020 pass = false;
1021
1022 if (!compare_buffer("saved P", p_out, p_expected,
1023 __SVE_PREGS_SIZE(vq)))
1024 pass = false;
1025
1026 if (!compare_buffer("saved FFR", ffr_out, ffr_expected,
1027 __SVE_PREG_SIZE(vq)))
1028 pass = false;
1029
1030 if (!compare_buffer("saved ZA", za_out, za_expected,
1031 ZA_PT_ZA_SIZE(sme_vq)))
1032 pass = false;
1033
1034 if (!compare_buffer("saved ZT", zt_out, zt_expected, ZT_SIG_REG_BYTES))
1035 pass = false;
1036
1037 if (fpmr_out != fpmr_expected) {
1038 ksft_print_msg("Mismatch in saved FPMR: %lx != %lx\n",
1039 fpmr_out, fpmr_expected);
1040 pass = false;
1041 }
1042
1043 return pass;
1044 }
1045
sve_sme_same(struct test_config * config)1046 static bool sve_sme_same(struct test_config *config)
1047 {
1048 if (config->sve_vl_in != config->sve_vl_expected)
1049 return false;
1050
1051 if (config->sme_vl_in != config->sme_vl_expected)
1052 return false;
1053
1054 if (config->svcr_in != config->svcr_expected)
1055 return false;
1056
1057 return true;
1058 }
1059
sve_write_supported(struct test_config * config)1060 static bool sve_write_supported(struct test_config *config)
1061 {
1062 if (!sve_supported() && !sme_supported())
1063 return false;
1064
1065 if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA))
1066 return false;
1067
1068 if (config->svcr_expected & SVCR_SM) {
1069 if (config->sve_vl_in != config->sve_vl_expected) {
1070 return false;
1071 }
1072
1073 /* Changing the SME VL disables ZA */
1074 if ((config->svcr_expected & SVCR_ZA) &&
1075 (config->sme_vl_in != config->sme_vl_expected)) {
1076 return false;
1077 }
1078 } else {
1079 if (config->sme_vl_in != config->sme_vl_expected) {
1080 return false;
1081 }
1082
1083 if (!sve_supported())
1084 return false;
1085 }
1086
1087 return true;
1088 }
1089
sve_write_fpsimd_supported(struct test_config * config)1090 static bool sve_write_fpsimd_supported(struct test_config *config)
1091 {
1092 if (!sve_supported() && !sme_supported())
1093 return false;
1094
1095 if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA))
1096 return false;
1097
1098 if (config->svcr_expected & SVCR_SM)
1099 return false;
1100
1101 if (config->sme_vl_in != config->sme_vl_expected)
1102 return false;
1103
1104 return true;
1105 }
1106
fpsimd_write_expected(struct test_config * config)1107 static void fpsimd_write_expected(struct test_config *config)
1108 {
1109 int vl;
1110
1111 fill_random(&v_expected, sizeof(v_expected));
1112
1113 /* The SVE registers are flushed by a FPSIMD write */
1114 vl = vl_expected(config);
1115
1116 memset(z_expected, 0, __SVE_ZREGS_SIZE(__sve_vq_from_vl(vl)));
1117 memset(p_expected, 0, __SVE_PREGS_SIZE(__sve_vq_from_vl(vl)));
1118 memset(ffr_expected, 0, __SVE_PREG_SIZE(__sve_vq_from_vl(vl)));
1119
1120 fpsimd_to_sve(v_expected, z_expected, vl);
1121 }
1122
fpsimd_write(pid_t child,struct test_config * test_config)1123 static void fpsimd_write(pid_t child, struct test_config *test_config)
1124 {
1125 struct user_fpsimd_state fpsimd;
1126 struct iovec iov;
1127 int ret;
1128
1129 memset(&fpsimd, 0, sizeof(fpsimd));
1130 memcpy(&fpsimd.vregs, v_expected, sizeof(v_expected));
1131
1132 iov.iov_base = &fpsimd;
1133 iov.iov_len = sizeof(fpsimd);
1134 ret = ptrace(PTRACE_SETREGSET, child, NT_PRFPREG, &iov);
1135 if (ret == -1)
1136 ksft_print_msg("FPSIMD set failed: (%s) %d\n",
1137 strerror(errno), errno);
1138 }
1139
fpmr_write_supported(struct test_config * config)1140 static bool fpmr_write_supported(struct test_config *config)
1141 {
1142 if (!fpmr_supported())
1143 return false;
1144
1145 if (!sve_sme_same(config))
1146 return false;
1147
1148 return true;
1149 }
1150
fpmr_write_expected(struct test_config * config)1151 static void fpmr_write_expected(struct test_config *config)
1152 {
1153 fill_random(&fpmr_expected, sizeof(fpmr_expected));
1154 fpmr_expected &= FPMR_SAFE_BITS;
1155 }
1156
fpmr_write(pid_t child,struct test_config * config)1157 static void fpmr_write(pid_t child, struct test_config *config)
1158 {
1159 struct iovec iov;
1160 int ret;
1161
1162 iov.iov_len = sizeof(fpmr_expected);
1163 iov.iov_base = &fpmr_expected;
1164 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_FPMR, &iov);
1165 if (ret != 0)
1166 ksft_print_msg("Failed to write FPMR: %s (%d)\n",
1167 strerror(errno), errno);
1168 }
1169
sve_write_expected(struct test_config * config)1170 static void sve_write_expected(struct test_config *config)
1171 {
1172 int vl = vl_expected(config);
1173 int sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
1174
1175 if (!vl)
1176 return;
1177
1178 fill_random(z_expected, __SVE_ZREGS_SIZE(__sve_vq_from_vl(vl)));
1179 fill_random(p_expected, __SVE_PREGS_SIZE(__sve_vq_from_vl(vl)));
1180
1181 if ((svcr_expected & SVCR_SM) && !fa64_supported())
1182 memset(ffr_expected, 0, __SVE_PREG_SIZE(sme_vq));
1183 else
1184 fill_random_ffr(ffr_expected, __sve_vq_from_vl(vl));
1185
1186 /* Share the low bits of Z with V */
1187 fill_random(&v_expected, sizeof(v_expected));
1188 fpsimd_to_sve(v_expected, z_expected, vl);
1189
1190 if (config->sme_vl_in != config->sme_vl_expected) {
1191 memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq));
1192 memset(zt_expected, 0, sizeof(zt_expected));
1193 }
1194 }
1195
sve_write_sve(pid_t child,struct test_config * config)1196 static void sve_write_sve(pid_t child, struct test_config *config)
1197 {
1198 struct user_sve_header *sve;
1199 struct iovec iov;
1200 int ret, vl, vq, regset;
1201
1202 vl = vl_expected(config);
1203 vq = __sve_vq_from_vl(vl);
1204
1205 if (!vl)
1206 return;
1207
1208 iov.iov_len = SVE_PT_SIZE(vq, SVE_PT_REGS_SVE);
1209 iov.iov_base = malloc(iov.iov_len);
1210 if (!iov.iov_base) {
1211 ksft_print_msg("Failed allocating %lu byte SVE write buffer\n",
1212 iov.iov_len);
1213 return;
1214 }
1215 memset(iov.iov_base, 0, iov.iov_len);
1216
1217 sve = iov.iov_base;
1218 sve->size = iov.iov_len;
1219 sve->flags = SVE_PT_REGS_SVE;
1220 sve->vl = vl;
1221
1222 memcpy(iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0),
1223 z_expected, SVE_PT_SVE_ZREGS_SIZE(vq));
1224 memcpy(iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0),
1225 p_expected, SVE_PT_SVE_PREGS_SIZE(vq));
1226 memcpy(iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq),
1227 ffr_expected, SVE_PT_SVE_PREG_SIZE(vq));
1228
1229 if (svcr_expected & SVCR_SM)
1230 regset = NT_ARM_SSVE;
1231 else
1232 regset = NT_ARM_SVE;
1233
1234 ret = ptrace(PTRACE_SETREGSET, child, regset, &iov);
1235 if (ret != 0)
1236 ksft_print_msg("Failed to write SVE: %s (%d)\n",
1237 strerror(errno), errno);
1238
1239 free(iov.iov_base);
1240 }
1241
sve_write_fpsimd(pid_t child,struct test_config * config)1242 static void sve_write_fpsimd(pid_t child, struct test_config *config)
1243 {
1244 struct user_sve_header *sve;
1245 struct user_fpsimd_state *fpsimd;
1246 struct iovec iov;
1247 int ret, vl, vq;
1248
1249 vl = vl_expected(config);
1250 vq = __sve_vq_from_vl(vl);
1251
1252 iov.iov_len = SVE_PT_SIZE(vq, SVE_PT_REGS_FPSIMD);
1253 iov.iov_base = malloc(iov.iov_len);
1254 if (!iov.iov_base) {
1255 ksft_print_msg("Failed allocating %lu byte SVE write buffer\n",
1256 iov.iov_len);
1257 return;
1258 }
1259 memset(iov.iov_base, 0, iov.iov_len);
1260
1261 sve = iov.iov_base;
1262 sve->size = iov.iov_len;
1263 sve->flags = SVE_PT_REGS_FPSIMD;
1264 sve->vl = vl;
1265
1266 fpsimd = iov.iov_base + SVE_PT_REGS_OFFSET;
1267 memcpy(&fpsimd->vregs, v_expected, sizeof(v_expected));
1268
1269 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_SVE, &iov);
1270 if (ret != 0)
1271 ksft_print_msg("Failed to write SVE: %s (%d)\n",
1272 strerror(errno), errno);
1273
1274 free(iov.iov_base);
1275 }
1276
za_write_supported(struct test_config * config)1277 static bool za_write_supported(struct test_config *config)
1278 {
1279 if ((config->svcr_in & SVCR_SM) != (config->svcr_expected & SVCR_SM))
1280 return false;
1281
1282 return true;
1283 }
1284
za_write_expected(struct test_config * config)1285 static void za_write_expected(struct test_config *config)
1286 {
1287 int sme_vq, sve_vq;
1288
1289 sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
1290
1291 if (config->svcr_expected & SVCR_ZA) {
1292 fill_random(za_expected, ZA_PT_ZA_SIZE(sme_vq));
1293 } else {
1294 memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq));
1295 memset(zt_expected, 0, sizeof(zt_expected));
1296 }
1297
1298 /* Changing the SME VL flushes ZT, SVE state */
1299 if (config->sme_vl_in != config->sme_vl_expected) {
1300 sve_vq = __sve_vq_from_vl(vl_expected(config));
1301 memset(z_expected, 0, __SVE_ZREGS_SIZE(sve_vq));
1302 memset(p_expected, 0, __SVE_PREGS_SIZE(sve_vq));
1303 memset(ffr_expected, 0, __SVE_PREG_SIZE(sve_vq));
1304 memset(zt_expected, 0, sizeof(zt_expected));
1305
1306 fpsimd_to_sve(v_expected, z_expected, vl_expected(config));
1307 }
1308 }
1309
za_write(pid_t child,struct test_config * config)1310 static void za_write(pid_t child, struct test_config *config)
1311 {
1312 struct user_za_header *za;
1313 struct iovec iov;
1314 int ret, vq;
1315
1316 vq = __sve_vq_from_vl(config->sme_vl_expected);
1317
1318 if (config->svcr_expected & SVCR_ZA)
1319 iov.iov_len = ZA_PT_SIZE(vq);
1320 else
1321 iov.iov_len = sizeof(*za);
1322 iov.iov_base = malloc(iov.iov_len);
1323 if (!iov.iov_base) {
1324 ksft_print_msg("Failed allocating %lu byte ZA write buffer\n",
1325 iov.iov_len);
1326 return;
1327 }
1328 memset(iov.iov_base, 0, iov.iov_len);
1329
1330 za = iov.iov_base;
1331 za->size = iov.iov_len;
1332 za->vl = config->sme_vl_expected;
1333 if (config->svcr_expected & SVCR_ZA)
1334 memcpy(iov.iov_base + ZA_PT_ZA_OFFSET, za_expected,
1335 ZA_PT_ZA_SIZE(vq));
1336
1337 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_ZA, &iov);
1338 if (ret != 0)
1339 ksft_print_msg("Failed to write ZA: %s (%d)\n",
1340 strerror(errno), errno);
1341
1342 free(iov.iov_base);
1343 }
1344
zt_write_supported(struct test_config * config)1345 static bool zt_write_supported(struct test_config *config)
1346 {
1347 if (!sme2_supported())
1348 return false;
1349 if (config->sme_vl_in != config->sme_vl_expected)
1350 return false;
1351 if (!(config->svcr_expected & SVCR_ZA))
1352 return false;
1353 if ((config->svcr_in & SVCR_SM) != (config->svcr_expected & SVCR_SM))
1354 return false;
1355
1356 return true;
1357 }
1358
zt_write_expected(struct test_config * config)1359 static void zt_write_expected(struct test_config *config)
1360 {
1361 int sme_vq;
1362
1363 sme_vq = __sve_vq_from_vl(config->sme_vl_expected);
1364
1365 if (config->svcr_expected & SVCR_ZA) {
1366 fill_random(zt_expected, sizeof(zt_expected));
1367 } else {
1368 memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq));
1369 memset(zt_expected, 0, sizeof(zt_expected));
1370 }
1371 }
1372
zt_write(pid_t child,struct test_config * config)1373 static void zt_write(pid_t child, struct test_config *config)
1374 {
1375 struct iovec iov;
1376 int ret;
1377
1378 iov.iov_len = ZT_SIG_REG_BYTES;
1379 iov.iov_base = zt_expected;
1380 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_ZT, &iov);
1381 if (ret != 0)
1382 ksft_print_msg("Failed to write ZT: %s (%d)\n",
1383 strerror(errno), errno);
1384 }
1385
1386 /* Actually run a test */
run_test(struct test_definition * test,struct test_config * config)1387 static void run_test(struct test_definition *test, struct test_config *config)
1388 {
1389 pid_t child;
1390 char name[1024];
1391 bool pass;
1392
1393 if (sve_supported() && sme_supported())
1394 snprintf(name, sizeof(name), "%s, SVE %d->%d, SME %d/%x->%d/%x",
1395 test->name,
1396 config->sve_vl_in, config->sve_vl_expected,
1397 config->sme_vl_in, config->svcr_in,
1398 config->sme_vl_expected, config->svcr_expected);
1399 else if (sve_supported())
1400 snprintf(name, sizeof(name), "%s, SVE %d->%d", test->name,
1401 config->sve_vl_in, config->sve_vl_expected);
1402 else if (sme_supported())
1403 snprintf(name, sizeof(name), "%s, SME %d/%x->%d/%x",
1404 test->name,
1405 config->sme_vl_in, config->svcr_in,
1406 config->sme_vl_expected, config->svcr_expected);
1407 else
1408 snprintf(name, sizeof(name), "%s", test->name);
1409
1410 if (test->supported && !test->supported(config)) {
1411 ksft_test_result_skip("%s\n", name);
1412 return;
1413 }
1414
1415 set_initial_values(config);
1416
1417 if (test->set_expected_values)
1418 test->set_expected_values(config);
1419
1420 child = fork();
1421 if (child < 0)
1422 ksft_exit_fail_msg("fork() failed: %s (%d)\n",
1423 strerror(errno), errno);
1424 /* run_child() never returns */
1425 if (child == 0)
1426 run_child(config);
1427
1428 pass = run_parent(child, test, config);
1429 if (!check_memory_values(config))
1430 pass = false;
1431
1432 ksft_test_result(pass, "%s\n", name);
1433 }
1434
run_tests(struct test_definition defs[],int count,struct test_config * config)1435 static void run_tests(struct test_definition defs[], int count,
1436 struct test_config *config)
1437 {
1438 int i;
1439
1440 for (i = 0; i < count; i++)
1441 run_test(&defs[i], config);
1442 }
1443
1444 static struct test_definition base_test_defs[] = {
1445 {
1446 .name = "No writes",
1447 .supported = sve_sme_same,
1448 },
1449 {
1450 .name = "FPSIMD write",
1451 .supported = sve_sme_same,
1452 .set_expected_values = fpsimd_write_expected,
1453 .modify_values = fpsimd_write,
1454 },
1455 {
1456 .name = "FPMR write",
1457 .supported = fpmr_write_supported,
1458 .set_expected_values = fpmr_write_expected,
1459 .modify_values = fpmr_write,
1460 },
1461 };
1462
1463 static struct test_definition sve_test_defs[] = {
1464 {
1465 .name = "SVE write",
1466 .supported = sve_write_supported,
1467 .set_expected_values = sve_write_expected,
1468 .modify_values = sve_write_sve,
1469 },
1470 {
1471 .name = "SVE write FPSIMD format",
1472 .supported = sve_write_fpsimd_supported,
1473 .set_expected_values = fpsimd_write_expected,
1474 .modify_values = sve_write_fpsimd,
1475 },
1476 };
1477
1478 static struct test_definition za_test_defs[] = {
1479 {
1480 .name = "ZA write",
1481 .supported = za_write_supported,
1482 .set_expected_values = za_write_expected,
1483 .modify_values = za_write,
1484 },
1485 };
1486
1487 static struct test_definition zt_test_defs[] = {
1488 {
1489 .name = "ZT write",
1490 .supported = zt_write_supported,
1491 .set_expected_values = zt_write_expected,
1492 .modify_values = zt_write,
1493 },
1494 };
1495
1496 static int sve_vls[MAX_NUM_VLS], sme_vls[MAX_NUM_VLS];
1497 static int sve_vl_count, sme_vl_count;
1498
probe_vls(const char * name,int vls[],int * vl_count,int set_vl)1499 static void probe_vls(const char *name, int vls[], int *vl_count, int set_vl)
1500 {
1501 unsigned int vq;
1502 int vl;
1503
1504 *vl_count = 0;
1505
1506 for (vq = ARCH_VQ_MAX; vq > 0; vq /= 2) {
1507 vl = prctl(set_vl, vq * 16);
1508 if (vl == -1)
1509 ksft_exit_fail_msg("SET_VL failed: %s (%d)\n",
1510 strerror(errno), errno);
1511
1512 vl &= PR_SVE_VL_LEN_MASK;
1513
1514 if (*vl_count && (vl == vls[*vl_count - 1]))
1515 break;
1516
1517 vq = sve_vq_from_vl(vl);
1518
1519 vls[*vl_count] = vl;
1520 *vl_count += 1;
1521 }
1522
1523 if (*vl_count > 2) {
1524 /* Just use the minimum and maximum */
1525 vls[1] = vls[*vl_count - 1];
1526 ksft_print_msg("%d %s VLs, using %d and %d\n",
1527 *vl_count, name, vls[0], vls[1]);
1528 *vl_count = 2;
1529 } else {
1530 ksft_print_msg("%d %s VLs\n", *vl_count, name);
1531 }
1532 }
1533
1534 static struct {
1535 int svcr_in, svcr_expected;
1536 } svcr_combinations[] = {
1537 { .svcr_in = 0, .svcr_expected = 0, },
1538 { .svcr_in = 0, .svcr_expected = SVCR_SM, },
1539 { .svcr_in = 0, .svcr_expected = SVCR_ZA, },
1540 /* Can't enable both SM and ZA with a single ptrace write */
1541
1542 { .svcr_in = SVCR_SM, .svcr_expected = 0, },
1543 { .svcr_in = SVCR_SM, .svcr_expected = SVCR_SM, },
1544 { .svcr_in = SVCR_SM, .svcr_expected = SVCR_ZA, },
1545 { .svcr_in = SVCR_SM, .svcr_expected = SVCR_SM | SVCR_ZA, },
1546
1547 { .svcr_in = SVCR_ZA, .svcr_expected = 0, },
1548 { .svcr_in = SVCR_ZA, .svcr_expected = SVCR_SM, },
1549 { .svcr_in = SVCR_ZA, .svcr_expected = SVCR_ZA, },
1550 { .svcr_in = SVCR_ZA, .svcr_expected = SVCR_SM | SVCR_ZA, },
1551
1552 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = 0, },
1553 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_SM, },
1554 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_ZA, },
1555 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_SM | SVCR_ZA, },
1556 };
1557
run_sve_tests(void)1558 static void run_sve_tests(void)
1559 {
1560 struct test_config test_config;
1561 int i, j;
1562
1563 if (!sve_supported())
1564 return;
1565
1566 test_config.sme_vl_in = sme_vls[0];
1567 test_config.sme_vl_expected = sme_vls[0];
1568 test_config.svcr_in = 0;
1569 test_config.svcr_expected = 0;
1570
1571 for (i = 0; i < sve_vl_count; i++) {
1572 test_config.sve_vl_in = sve_vls[i];
1573
1574 for (j = 0; j < sve_vl_count; j++) {
1575 test_config.sve_vl_expected = sve_vls[j];
1576
1577 run_tests(base_test_defs,
1578 ARRAY_SIZE(base_test_defs),
1579 &test_config);
1580 if (sve_supported())
1581 run_tests(sve_test_defs,
1582 ARRAY_SIZE(sve_test_defs),
1583 &test_config);
1584 }
1585 }
1586 }
1587
run_sme_tests(void)1588 static void run_sme_tests(void)
1589 {
1590 struct test_config test_config;
1591 int i, j, k;
1592
1593 if (!sme_supported())
1594 return;
1595
1596 test_config.sve_vl_in = sve_vls[0];
1597 test_config.sve_vl_expected = sve_vls[0];
1598
1599 /*
1600 * Every SME VL/SVCR combination
1601 */
1602 for (i = 0; i < sme_vl_count; i++) {
1603 test_config.sme_vl_in = sme_vls[i];
1604
1605 for (j = 0; j < sme_vl_count; j++) {
1606 test_config.sme_vl_expected = sme_vls[j];
1607
1608 for (k = 0; k < ARRAY_SIZE(svcr_combinations); k++) {
1609 test_config.svcr_in = svcr_combinations[k].svcr_in;
1610 test_config.svcr_expected = svcr_combinations[k].svcr_expected;
1611
1612 run_tests(base_test_defs,
1613 ARRAY_SIZE(base_test_defs),
1614 &test_config);
1615 run_tests(sve_test_defs,
1616 ARRAY_SIZE(sve_test_defs),
1617 &test_config);
1618 run_tests(za_test_defs,
1619 ARRAY_SIZE(za_test_defs),
1620 &test_config);
1621
1622 if (sme2_supported())
1623 run_tests(zt_test_defs,
1624 ARRAY_SIZE(zt_test_defs),
1625 &test_config);
1626 }
1627 }
1628 }
1629 }
1630
main(void)1631 int main(void)
1632 {
1633 struct test_config test_config;
1634 struct sigaction sa;
1635 int tests, ret, tmp;
1636
1637 srandom(getpid());
1638
1639 ksft_print_header();
1640
1641 if (sve_supported()) {
1642 probe_vls("SVE", sve_vls, &sve_vl_count, PR_SVE_SET_VL);
1643
1644 tests = ARRAY_SIZE(base_test_defs) +
1645 ARRAY_SIZE(sve_test_defs);
1646 tests *= sve_vl_count * sve_vl_count;
1647 } else {
1648 /* Only run the FPSIMD tests */
1649 sve_vl_count = 1;
1650 tests = ARRAY_SIZE(base_test_defs);
1651 }
1652
1653 if (sme_supported()) {
1654 probe_vls("SME", sme_vls, &sme_vl_count, PR_SME_SET_VL);
1655
1656 tmp = ARRAY_SIZE(base_test_defs) + ARRAY_SIZE(sve_test_defs)
1657 + ARRAY_SIZE(za_test_defs);
1658
1659 if (sme2_supported())
1660 tmp += ARRAY_SIZE(zt_test_defs);
1661
1662 tmp *= sme_vl_count * sme_vl_count;
1663 tmp *= ARRAY_SIZE(svcr_combinations);
1664 tests += tmp;
1665 } else {
1666 sme_vl_count = 1;
1667 }
1668
1669 if (sme2_supported())
1670 ksft_print_msg("SME2 supported\n");
1671
1672 if (fa64_supported())
1673 ksft_print_msg("FA64 supported\n");
1674
1675 if (fpmr_supported())
1676 ksft_print_msg("FPMR supported\n");
1677
1678 ksft_set_plan(tests);
1679
1680 /* Get signal handers ready before we start any children */
1681 memset(&sa, 0, sizeof(sa));
1682 sa.sa_sigaction = handle_alarm;
1683 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1684 sigemptyset(&sa.sa_mask);
1685 ret = sigaction(SIGALRM, &sa, NULL);
1686 if (ret < 0)
1687 ksft_print_msg("Failed to install SIGALRM handler: %s (%d)\n",
1688 strerror(errno), errno);
1689
1690 /*
1691 * Run the test set if there is no SVE or SME, with those we
1692 * have to pick a VL for each run.
1693 */
1694 if (!sve_supported() && !sme_supported()) {
1695 test_config.sve_vl_in = 0;
1696 test_config.sve_vl_expected = 0;
1697 test_config.sme_vl_in = 0;
1698 test_config.sme_vl_expected = 0;
1699 test_config.svcr_in = 0;
1700 test_config.svcr_expected = 0;
1701
1702 run_tests(base_test_defs, ARRAY_SIZE(base_test_defs),
1703 &test_config);
1704 }
1705
1706 run_sve_tests();
1707 run_sme_tests();
1708
1709 ksft_finished();
1710 }
1711