1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2023 ARM Limited.
4 * Original author: Mark Brown <broonie@kernel.org>
18 #include <sys/prctl.h>
19 #include <sys/ptrace.h>
20 #include <sys/types.h>
24 #include <linux/kernel.h>
26 #include <asm/sigcontext.h>
27 #include <asm/sve_context.h>
28 #include <asm/ptrace.h>
30 #include "../../kselftest.h"
32 #include "fp-ptrace.h"
34 #include <linux/bits.h>
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)
42 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
44 #define NT_ARM_SVE 0x405
48 #define NT_ARM_SSVE 0x40b
52 #define NT_ARM_ZA 0x40c
56 #define NT_ARM_ZT 0x40d
60 #define NT_ARM_FPMR 0x40e
63 #define ARCH_VQ_MAX 256
65 /* VL 128..2048 in powers of 2 */
69 * FPMR bits we can set without doing feature checks to see if values
72 #define FPMR_SAFE_BITS (FPMR_LSCALE2_MASK | FPMR_NSCALE_MASK | \
73 FPMR_LSCALE_MASK | FPMR_OSC_MASK | FPMR_OSM_MASK)
76 __uint128_t v_in
[NUM_FPR
];
77 __uint128_t v_expected
[NUM_FPR
];
78 __uint128_t v_out
[NUM_FPR
];
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
)];
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
)];
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
)];
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
)];
96 char zt_in
[ZT_SIG_REG_BYTES
];
97 char zt_expected
[ZT_SIG_REG_BYTES
];
98 char zt_out
[ZT_SIG_REG_BYTES
];
100 uint64_t fpmr_in
, fpmr_expected
, fpmr_out
;
104 uint64_t svcr_in
, svcr_expected
, svcr_out
;
106 void load_and_save(int flags
);
108 static bool got_alarm
;
110 static void handle_alarm(int sig
, siginfo_t
*info
, void *context
)
115 #ifdef CONFIG_CPU_BIG_ENDIAN
116 static __uint128_t
arm64_cpu_to_le128(__uint128_t x
)
119 u64 b
= swab64(x
>> 64);
121 return ((__uint128_t
)a
<< 64) | b
;
124 static __uint128_t
arm64_cpu_to_le128(__uint128_t x
)
130 #define arm64_le128_to_cpu(x) arm64_cpu_to_le128(x)
132 static bool sve_supported(void)
134 return getauxval(AT_HWCAP
) & HWCAP_SVE
;
137 static bool sme_supported(void)
139 return getauxval(AT_HWCAP2
) & HWCAP2_SME
;
142 static bool sme2_supported(void)
144 return getauxval(AT_HWCAP2
) & HWCAP2_SME2
;
147 static bool fa64_supported(void)
149 return getauxval(AT_HWCAP2
) & HWCAP2_SME_FA64
;
152 static bool fpmr_supported(void)
154 return getauxval(AT_HWCAP2
) & HWCAP2_FPMR
;
157 static bool compare_buffer(const char *name
, void *out
,
158 void *expected
, size_t size
)
162 if (memcmp(out
, expected
, size
) == 0)
165 ksft_print_msg("Mismatch in %s\n", name
);
167 /* Did we just get zeros back? */
170 ksft_print_msg("OOM allocating %lu bytes for %s\n",
174 memset(tmp
, 0, size
);
176 if (memcmp(out
, tmp
, size
) == 0)
177 ksft_print_msg("%s is zero\n", name
);
193 struct test_definition
{
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
);
201 static int vl_in(struct test_config
*config
)
205 if (config
->svcr_in
& SVCR_SM
)
206 vl
= config
->sme_vl_in
;
208 vl
= config
->sve_vl_in
;
213 static int vl_expected(struct test_config
*config
)
217 if (config
->svcr_expected
& SVCR_SM
)
218 vl
= config
->sme_vl_expected
;
220 vl
= config
->sve_vl_expected
;
225 static void run_child(struct test_config
*config
)
229 /* Let the parent attach to us */
230 ret
= ptrace(PTRACE_TRACEME
, 0, 0, 0);
232 ksft_exit_fail_msg("PTRACE_TRACEME failed: %s (%d)\n",
233 strerror(errno
), errno
);
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
);
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
);
252 /* Load values and wait for the parent */
258 if (sme2_supported())
260 if (fa64_supported())
262 if (fpmr_supported())
265 load_and_save(flags
);
270 static void read_one_child_regs(pid_t child
, char *name
,
271 struct iovec
*iov_parent
,
272 struct iovec
*iov_child
)
274 int len
= iov_parent
->iov_len
;
277 ret
= process_vm_readv(child
, iov_parent
, 1, iov_child
, 1, 0);
279 ksft_print_msg("%s read failed: %s (%d)\n",
280 name
, strerror(errno
), errno
);
282 ksft_print_msg("Short read of %s: %d\n", name
, ret
);
285 static void read_child_regs(pid_t child
)
287 struct iovec iov_parent
, iov_child
;
290 * Since the child fork()ed from us the buffer addresses are
291 * the same in parent and child.
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
362 static bool continue_breakpoint(pid_t child
,
363 enum __ptrace_request restart_type
)
365 struct user_pt_regs pt_regs
;
370 iov
.iov_base
= &pt_regs
;
371 iov
.iov_len
= sizeof(pt_regs
);
372 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_PRSTATUS
, &iov
);
374 ksft_print_msg("Failed to get PC: %s (%d)\n",
375 strerror(errno
), errno
);
379 /* Skip over the BRK */
381 ret
= ptrace(PTRACE_SETREGSET
, child
, NT_PRSTATUS
, &iov
);
383 ksft_print_msg("Failed to skip BRK: %s (%d)\n",
384 strerror(errno
), errno
);
389 ret
= ptrace(restart_type
, child
, 0, 0);
391 ksft_print_msg("Failed to restart child: %s (%d)\n",
392 strerror(errno
), errno
);
399 static bool check_ptrace_values_sve(pid_t child
, struct test_config
*config
)
401 struct user_sve_header
*sve
;
402 struct user_fpsimd_state
*fpsimd
;
407 if (!sve_supported())
410 vq
= __sve_vq_from_vl(config
->sve_vl_in
);
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
);
415 ksft_print_msg("OOM allocating %lu byte SVE buffer\n",
420 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_ARM_SVE
, &iov
);
422 ksft_print_msg("Failed to read initial SVE: %s (%d)\n",
423 strerror(errno
), errno
);
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
);
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");
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
));
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
)))
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
)))
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
)))
465 fpsimd
= iov
.iov_base
+ SVE_PT_FPSIMD_OFFSET
;
466 if (!compare_buffer("initial V via SVE", &fpsimd
->vregs
[0],
476 static bool check_ptrace_values_ssve(pid_t child
, struct test_config
*config
)
478 struct user_sve_header
*sve
;
479 struct user_fpsimd_state
*fpsimd
;
484 if (!sme_supported())
487 vq
= __sve_vq_from_vl(config
->sme_vl_in
);
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
);
492 ksft_print_msg("OOM allocating %lu byte SSVE buffer\n",
497 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_ARM_SSVE
, &iov
);
499 ksft_print_msg("Failed to read initial SSVE: %s (%d)\n",
500 strerror(errno
), errno
);
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
);
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");
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
));
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
)))
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
)))
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
)))
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
)))
552 static bool check_ptrace_values_za(pid_t child
, struct test_config
*config
)
554 struct user_za_header
*za
;
559 if (!sme_supported())
562 vq
= __sve_vq_from_vl(config
->sme_vl_in
);
564 iov
.iov_len
= ZA_SIG_CONTEXT_SIZE(vq
);
565 iov
.iov_base
= malloc(iov
.iov_len
);
567 ksft_print_msg("OOM allocating %lu byte ZA buffer\n",
572 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_ARM_ZA
, &iov
);
574 ksft_print_msg("Failed to read initial ZA: %s (%d)\n",
575 strerror(errno
), errno
);
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
);
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
));
596 if (!compare_buffer("initial ZA",
597 iov
.iov_base
+ ZA_PT_ZA_OFFSET
,
598 za_in
, ZA_PT_ZA_SIZE(vq
)))
601 if (za
->size
!= sizeof(*za
)) {
602 ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n",
603 za
->size
, sizeof(*za
));
613 static bool check_ptrace_values_zt(pid_t child
, struct test_config
*config
)
619 if (!sme2_supported())
623 iov
.iov_len
= ZT_SIG_REG_BYTES
;
624 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_ARM_ZT
, &iov
);
626 ksft_print_msg("Failed to read initial ZT: %s (%d)\n",
627 strerror(errno
), errno
);
631 return compare_buffer("initial ZT", buf
, zt_in
, ZT_SIG_REG_BYTES
);
634 static bool check_ptrace_values_fpmr(pid_t child
, struct test_config
*config
)
640 if (!fpmr_supported())
644 iov
.iov_len
= sizeof(val
);
645 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_ARM_FPMR
, &iov
);
647 ksft_print_msg("Failed to read initial FPMR: %s (%d)\n",
648 strerror(errno
), errno
);
652 return compare_buffer("initial FPMR", &val
, &fpmr_in
, sizeof(val
));
655 static bool check_ptrace_values(pid_t child
, struct test_config
*config
)
658 struct user_fpsimd_state fpsimd
;
662 iov
.iov_base
= &fpsimd
;
663 iov
.iov_len
= sizeof(fpsimd
);
664 ret
= ptrace(PTRACE_GETREGSET
, child
, NT_PRFPREG
, &iov
);
666 if (!compare_buffer("initial V", &fpsimd
.vregs
, v_in
,
671 ksft_print_msg("Failed to read initial V: %s (%d)\n",
672 strerror(errno
), errno
);
676 if (!check_ptrace_values_sve(child
, config
))
679 if (!check_ptrace_values_ssve(child
, config
))
682 if (!check_ptrace_values_za(child
, config
))
685 if (!check_ptrace_values_zt(child
, config
))
688 if (!check_ptrace_values_fpmr(child
, config
))
694 static bool run_parent(pid_t child
, struct test_definition
*test
,
695 struct test_config
*config
)
697 int wait_status
, ret
;
703 pid
= waitpid(child
, &wait_status
, 0);
707 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
708 strerror(errno
), errno
);
715 if (WIFEXITED(wait_status
)) {
716 ksft_print_msg("Child exited loading values with status %d\n",
717 WEXITSTATUS(wait_status
));
722 if (WIFSIGNALED(wait_status
)) {
723 ksft_print_msg("Child died from signal %d loading values\n",
724 WTERMSIG(wait_status
));
729 /* Read initial values via ptrace */
730 pass
= check_ptrace_values(child
, config
);
732 /* Do whatever writes we want to do */
733 if (test
->modify_values
)
734 test
->modify_values(child
, config
);
736 if (!continue_breakpoint(child
, PTRACE_CONT
))
740 pid
= waitpid(child
, &wait_status
, 0);
744 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
745 strerror(errno
), errno
);
752 if (WIFEXITED(wait_status
)) {
753 ksft_print_msg("Child exited saving values with status %d\n",
754 WEXITSTATUS(wait_status
));
759 if (WIFSIGNALED(wait_status
)) {
760 ksft_print_msg("Child died from signal %d saving values\n",
761 WTERMSIG(wait_status
));
766 /* See what happened as a result */
767 read_child_regs(child
);
769 if (!continue_breakpoint(child
, PTRACE_DETACH
))
772 /* The child should exit cleanly */
777 ksft_print_msg("Wait for child timed out\n");
781 pid
= waitpid(child
, &wait_status
, 0);
785 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
786 strerror(errno
), errno
);
795 ksft_print_msg("Timed out waiting for child\n");
800 if (pid
== child
&& WIFSIGNALED(wait_status
)) {
801 ksft_print_msg("Child died from signal %d cleaning up\n",
802 WTERMSIG(wait_status
));
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
));
814 ksft_print_msg("Child did not exit cleanly\n");
822 ret
= kill(child
, SIGKILL
);
824 ksft_print_msg("kill() failed: %s (%d)\n",
825 strerror(errno
), errno
);
830 pid
= waitpid(child
, &wait_status
, 0);
834 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n",
835 strerror(errno
), errno
);
846 static void fill_random(void *buf
, size_t size
)
849 uint32_t *lbuf
= buf
;
851 /* random() returns a 32 bit number regardless of the size of long */
852 for (i
= 0; i
< size
/ sizeof(uint32_t); i
++)
856 static void fill_random_ffr(void *buf
, size_t vq
)
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
866 memset(buf
, 0, __SVE_FFR_SIZE(vq
));
868 bits
= random() % (__SVE_FFR_SIZE(vq
) * 8);
869 for (i
= 0; i
< bits
/ 8; i
++)
871 if (bits
/ 8 != __SVE_FFR_SIZE(vq
))
872 lbuf
[i
] = (1 << (bits
% 8)) - 1;
875 static void fpsimd_to_sve(__uint128_t
*v
, char *z
, int vl
)
877 int vq
= __sve_vq_from_vl(vl
);
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
]);
890 static void set_initial_values(struct test_config
*config
)
892 int vq
= __sve_vq_from_vl(vl_in(config
));
893 int sme_vq
= __sve_vq_from_vl(config
->sme_vl_in
);
896 svcr_in
= config
->svcr_in
;
897 svcr_expected
= config
->svcr_expected
;
900 if (sme_supported() &&
901 (svcr_in
& SVCR_SM
) != (svcr_expected
& SVCR_SM
))
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
));
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
));
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
));
922 if ((config
->svcr_in
& SVCR_SM
) && !fa64_supported())
923 memset(ffr_in
, 0, __SVE_PREG_SIZE(vq
));
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
));
930 if (config
->svcr_in
& SVCR_ZA
)
931 fill_random(za_in
, ZA_SIG_REGS_SIZE(sme_vq
));
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
));
937 memset(za_expected
, 0, ZA_SIG_REGS_SIZE(sme_vq
));
939 memset(za_out
, 0, sizeof(za_out
));
941 if (sme2_supported()) {
942 if (config
->svcr_in
& SVCR_ZA
)
943 fill_random(zt_in
, ZT_SIG_REG_BYTES
);
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
);
949 memset(zt_expected
, 0, ZT_SIG_REG_BYTES
);
950 memset(zt_out
, 0, sizeof(zt_out
));
953 if (fpmr_supported()) {
954 fill_random(&fpmr_in
, sizeof(fpmr_in
));
955 fpmr_in
&= FPMR_SAFE_BITS
;
957 /* Entering or exiting streaming mode clears FPMR */
961 fpmr_expected
= fpmr_in
;
969 static bool check_memory_values(struct test_config
*config
)
974 if (!compare_buffer("saved V", v_out
, v_expected
, sizeof(v_out
)))
977 vq
= __sve_vq_from_vl(vl_expected(config
));
978 sme_vq
= __sve_vq_from_vl(config
->sme_vl_expected
);
980 if (svcr_out
!= svcr_expected
) {
981 ksft_print_msg("Mismatch in saved SVCR %lx != %lx\n",
982 svcr_out
, svcr_expected
);
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
);
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
);
998 if (!compare_buffer("saved Z", z_out
, z_expected
,
999 __SVE_ZREGS_SIZE(vq
)))
1002 if (!compare_buffer("saved P", p_out
, p_expected
,
1003 __SVE_PREGS_SIZE(vq
)))
1006 if (!compare_buffer("saved FFR", ffr_out
, ffr_expected
,
1007 __SVE_PREG_SIZE(vq
)))
1010 if (!compare_buffer("saved ZA", za_out
, za_expected
,
1011 ZA_PT_ZA_SIZE(sme_vq
)))
1014 if (!compare_buffer("saved ZT", zt_out
, zt_expected
, ZT_SIG_REG_BYTES
))
1017 if (fpmr_out
!= fpmr_expected
) {
1018 ksft_print_msg("Mismatch in saved FPMR: %lx != %lx\n",
1019 fpmr_out
, fpmr_expected
);
1026 static bool sve_sme_same(struct test_config
*config
)
1028 if (config
->sve_vl_in
!= config
->sve_vl_expected
)
1031 if (config
->sme_vl_in
!= config
->sme_vl_expected
)
1034 if (config
->svcr_in
!= config
->svcr_expected
)
1040 static bool sve_write_supported(struct test_config
*config
)
1042 if (!sve_supported() && !sme_supported())
1045 if ((config
->svcr_in
& SVCR_ZA
) != (config
->svcr_expected
& SVCR_ZA
))
1048 if (config
->svcr_expected
& SVCR_SM
) {
1049 if (config
->sve_vl_in
!= config
->sve_vl_expected
) {
1053 /* Changing the SME VL disables ZA */
1054 if ((config
->svcr_expected
& SVCR_ZA
) &&
1055 (config
->sme_vl_in
!= config
->sme_vl_expected
)) {
1059 if (config
->sme_vl_in
!= config
->sme_vl_expected
) {
1067 static void fpsimd_write_expected(struct test_config
*config
)
1071 fill_random(&v_expected
, sizeof(v_expected
));
1073 /* The SVE registers are flushed by a FPSIMD write */
1074 vl
= vl_expected(config
);
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
)));
1080 fpsimd_to_sve(v_expected
, z_expected
, vl
);
1083 static void fpsimd_write(pid_t child
, struct test_config
*test_config
)
1085 struct user_fpsimd_state fpsimd
;
1089 memset(&fpsimd
, 0, sizeof(fpsimd
));
1090 memcpy(&fpsimd
.vregs
, v_expected
, sizeof(v_expected
));
1092 iov
.iov_base
= &fpsimd
;
1093 iov
.iov_len
= sizeof(fpsimd
);
1094 ret
= ptrace(PTRACE_SETREGSET
, child
, NT_PRFPREG
, &iov
);
1096 ksft_print_msg("FPSIMD set failed: (%s) %d\n",
1097 strerror(errno
), errno
);
1100 static bool fpmr_write_supported(struct test_config
*config
)
1102 if (!fpmr_supported())
1105 if (!sve_sme_same(config
))
1111 static void fpmr_write_expected(struct test_config
*config
)
1113 fill_random(&fpmr_expected
, sizeof(fpmr_expected
));
1114 fpmr_expected
&= FPMR_SAFE_BITS
;
1117 static void fpmr_write(pid_t child
, struct test_config
*config
)
1122 iov
.iov_len
= sizeof(fpmr_expected
);
1123 iov
.iov_base
= &fpmr_expected
;
1124 ret
= ptrace(PTRACE_SETREGSET
, child
, NT_ARM_FPMR
, &iov
);
1126 ksft_print_msg("Failed to write FPMR: %s (%d)\n",
1127 strerror(errno
), errno
);
1130 static void sve_write_expected(struct test_config
*config
)
1132 int vl
= vl_expected(config
);
1133 int sme_vq
= __sve_vq_from_vl(config
->sme_vl_expected
);
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
)));
1138 if ((svcr_expected
& SVCR_SM
) && !fa64_supported())
1139 memset(ffr_expected
, 0, __SVE_PREG_SIZE(sme_vq
));
1141 fill_random_ffr(ffr_expected
, __sve_vq_from_vl(vl
));
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
);
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
));
1153 static void sve_write(pid_t child
, struct test_config
*config
)
1155 struct user_sve_header
*sve
;
1157 int ret
, vl
, vq
, regset
;
1159 vl
= vl_expected(config
);
1160 vq
= __sve_vq_from_vl(vl
);
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",
1169 memset(iov
.iov_base
, 0, iov
.iov_len
);
1172 sve
->size
= iov
.iov_len
;
1173 sve
->flags
= SVE_PT_REGS_SVE
;
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
));
1183 if (svcr_expected
& SVCR_SM
)
1184 regset
= NT_ARM_SSVE
;
1186 regset
= NT_ARM_SVE
;
1188 ret
= ptrace(PTRACE_SETREGSET
, child
, regset
, &iov
);
1190 ksft_print_msg("Failed to write SVE: %s (%d)\n",
1191 strerror(errno
), errno
);
1196 static bool za_write_supported(struct test_config
*config
)
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
) {
1204 /* Otherwise we can't change streaming mode */
1205 if ((config
->svcr_in
& SVCR_SM
) !=
1206 (config
->svcr_expected
& SVCR_SM
)) {
1214 static void za_write_expected(struct test_config
*config
)
1218 sme_vq
= __sve_vq_from_vl(config
->sme_vl_expected
);
1220 if (config
->svcr_expected
& SVCR_ZA
) {
1221 fill_random(za_expected
, ZA_PT_ZA_SIZE(sme_vq
));
1223 memset(za_expected
, 0, ZA_PT_ZA_SIZE(sme_vq
));
1224 memset(zt_expected
, 0, sizeof(zt_expected
));
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
;
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
));
1237 fpsimd_to_sve(v_expected
, z_expected
, vl_expected(config
));
1241 static void za_write(pid_t child
, struct test_config
*config
)
1243 struct user_za_header
*za
;
1247 vq
= __sve_vq_from_vl(config
->sme_vl_expected
);
1249 if (config
->svcr_expected
& SVCR_ZA
)
1250 iov
.iov_len
= ZA_PT_SIZE(vq
);
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",
1259 memset(iov
.iov_base
, 0, iov
.iov_len
);
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
,
1268 ret
= ptrace(PTRACE_SETREGSET
, child
, NT_ARM_ZA
, &iov
);
1270 ksft_print_msg("Failed to write ZA: %s (%d)\n",
1271 strerror(errno
), errno
);
1276 static bool zt_write_supported(struct test_config
*config
)
1278 if (!sme2_supported())
1280 if (config
->sme_vl_in
!= config
->sme_vl_expected
)
1282 if (!(config
->svcr_expected
& SVCR_ZA
))
1284 if ((config
->svcr_in
& SVCR_SM
) != (config
->svcr_expected
& SVCR_SM
))
1290 static void zt_write_expected(struct test_config
*config
)
1294 sme_vq
= __sve_vq_from_vl(config
->sme_vl_expected
);
1296 if (config
->svcr_expected
& SVCR_ZA
) {
1297 fill_random(zt_expected
, sizeof(zt_expected
));
1299 memset(za_expected
, 0, ZA_PT_ZA_SIZE(sme_vq
));
1300 memset(zt_expected
, 0, sizeof(zt_expected
));
1304 static void zt_write(pid_t child
, struct test_config
*config
)
1309 iov
.iov_len
= ZT_SIG_REG_BYTES
;
1310 iov
.iov_base
= zt_expected
;
1311 ret
= ptrace(PTRACE_SETREGSET
, child
, NT_ARM_ZT
, &iov
);
1313 ksft_print_msg("Failed to write ZT: %s (%d)\n",
1314 strerror(errno
), errno
);
1317 /* Actually run a test */
1318 static void run_test(struct test_definition
*test
, struct test_config
*config
)
1324 if (sve_supported() && sme_supported())
1325 snprintf(name
, sizeof(name
), "%s, SVE %d->%d, SME %d/%x->%d/%x",
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",
1336 config
->sme_vl_in
, config
->svcr_in
,
1337 config
->sme_vl_expected
, config
->svcr_expected
);
1339 snprintf(name
, sizeof(name
), "%s", test
->name
);
1341 if (test
->supported
&& !test
->supported(config
)) {
1342 ksft_test_result_skip("%s\n", name
);
1346 set_initial_values(config
);
1348 if (test
->set_expected_values
)
1349 test
->set_expected_values(config
);
1353 ksft_exit_fail_msg("fork() failed: %s (%d)\n",
1354 strerror(errno
), errno
);
1355 /* run_child() never returns */
1359 pass
= run_parent(child
, test
, config
);
1360 if (!check_memory_values(config
))
1363 ksft_test_result(pass
, "%s\n", name
);
1366 static void run_tests(struct test_definition defs
[], int count
,
1367 struct test_config
*config
)
1371 for (i
= 0; i
< count
; i
++)
1372 run_test(&defs
[i
], config
);
1375 static struct test_definition base_test_defs
[] = {
1377 .name
= "No writes",
1378 .supported
= sve_sme_same
,
1381 .name
= "FPSIMD write",
1382 .supported
= sve_sme_same
,
1383 .set_expected_values
= fpsimd_write_expected
,
1384 .modify_values
= fpsimd_write
,
1387 .name
= "FPMR write",
1388 .supported
= fpmr_write_supported
,
1389 .set_expected_values
= fpmr_write_expected
,
1390 .modify_values
= fpmr_write
,
1394 static struct test_definition sve_test_defs
[] = {
1396 .name
= "SVE write",
1397 .supported
= sve_write_supported
,
1398 .set_expected_values
= sve_write_expected
,
1399 .modify_values
= sve_write
,
1403 static struct test_definition za_test_defs
[] = {
1406 .supported
= za_write_supported
,
1407 .set_expected_values
= za_write_expected
,
1408 .modify_values
= za_write
,
1412 static struct test_definition zt_test_defs
[] = {
1415 .supported
= zt_write_supported
,
1416 .set_expected_values
= zt_write_expected
,
1417 .modify_values
= zt_write
,
1421 static int sve_vls
[MAX_NUM_VLS
], sme_vls
[MAX_NUM_VLS
];
1422 static int sve_vl_count
, sme_vl_count
;
1424 static void probe_vls(const char *name
, int vls
[], int *vl_count
, int set_vl
)
1431 for (vq
= ARCH_VQ_MAX
; vq
> 0; vq
/= 2) {
1432 vl
= prctl(set_vl
, vq
* 16);
1434 ksft_exit_fail_msg("SET_VL failed: %s (%d)\n",
1435 strerror(errno
), errno
);
1437 vl
&= PR_SVE_VL_LEN_MASK
;
1439 if (*vl_count
&& (vl
== vls
[*vl_count
- 1]))
1442 vq
= sve_vq_from_vl(vl
);
1444 vls
[*vl_count
] = vl
;
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]);
1455 ksft_print_msg("%d %s VLs\n", *vl_count
, name
);
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 */
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
, },
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
, },
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
, },
1483 static void run_sve_tests(void)
1485 struct test_config test_config
;
1488 if (!sve_supported())
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;
1496 for (i
= 0; i
< sve_vl_count
; i
++) {
1497 test_config
.sve_vl_in
= sve_vls
[i
];
1499 for (j
= 0; j
< sve_vl_count
; j
++) {
1500 test_config
.sve_vl_expected
= sve_vls
[j
];
1502 run_tests(base_test_defs
,
1503 ARRAY_SIZE(base_test_defs
),
1505 if (sve_supported())
1506 run_tests(sve_test_defs
,
1507 ARRAY_SIZE(sve_test_defs
),
1514 static void run_sme_tests(void)
1516 struct test_config test_config
;
1519 if (!sme_supported())
1522 test_config
.sve_vl_in
= sve_vls
[0];
1523 test_config
.sve_vl_expected
= sve_vls
[0];
1526 * Every SME VL/SVCR combination
1528 for (i
= 0; i
< sme_vl_count
; i
++) {
1529 test_config
.sme_vl_in
= sme_vls
[i
];
1531 for (j
= 0; j
< sme_vl_count
; j
++) {
1532 test_config
.sme_vl_expected
= sme_vls
[j
];
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
;
1538 run_tests(base_test_defs
,
1539 ARRAY_SIZE(base_test_defs
),
1541 run_tests(sve_test_defs
,
1542 ARRAY_SIZE(sve_test_defs
),
1544 run_tests(za_test_defs
,
1545 ARRAY_SIZE(za_test_defs
),
1548 if (sme2_supported())
1549 run_tests(zt_test_defs
,
1550 ARRAY_SIZE(zt_test_defs
),
1559 struct test_config test_config
;
1560 struct sigaction sa
;
1561 int tests
, ret
, tmp
;
1565 ksft_print_header();
1567 if (sve_supported()) {
1568 probe_vls("SVE", sve_vls
, &sve_vl_count
, PR_SVE_SET_VL
);
1570 tests
= ARRAY_SIZE(base_test_defs
) +
1571 ARRAY_SIZE(sve_test_defs
);
1572 tests
*= sve_vl_count
* sve_vl_count
;
1574 /* Only run the FPSIMD tests */
1576 tests
= ARRAY_SIZE(base_test_defs
);
1579 if (sme_supported()) {
1580 probe_vls("SME", sme_vls
, &sme_vl_count
, PR_SME_SET_VL
);
1582 tmp
= ARRAY_SIZE(base_test_defs
) + ARRAY_SIZE(sve_test_defs
)
1583 + ARRAY_SIZE(za_test_defs
);
1585 if (sme2_supported())
1586 tmp
+= ARRAY_SIZE(zt_test_defs
);
1588 tmp
*= sme_vl_count
* sme_vl_count
;
1589 tmp
*= ARRAY_SIZE(svcr_combinations
);
1595 if (sme2_supported())
1596 ksft_print_msg("SME2 supported\n");
1598 if (fa64_supported())
1599 ksft_print_msg("FA64 supported\n");
1601 if (fpmr_supported())
1602 ksft_print_msg("FPMR supported\n");
1604 ksft_set_plan(tests
);
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
);
1613 ksft_print_msg("Failed to install SIGALRM handler: %s (%d)\n",
1614 strerror(errno
), errno
);
1617 * Run the test set if there is no SVE or SME, with those we
1618 * have to pick a VL for each run.
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;
1628 run_tests(base_test_defs
, ARRAY_SIZE(base_test_defs
),