1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2015-2021 ARM Limited.
4 * Original author: Dave Martin <Dave.Martin@arm.com>
14 #include <sys/prctl.h>
15 #include <sys/ptrace.h>
16 #include <sys/types.h>
19 #include <asm/sigcontext.h>
20 #include <asm/ptrace.h>
22 #include "../../kselftest.h"
24 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
26 #define NT_ARM_SVE 0x405
30 #define NT_ARM_SSVE 0x40b
34 * The architecture defines the maximum VQ as 16 but for extensibility
35 * the kernel specifies the SVE_VQ_MAX as 512 resulting in us running
36 * a *lot* more tests than are useful if we use it. Until the
37 * architecture is extended let's limit our coverage to what is
38 * currently allowed, plus one extra to ensure we cover constraining
41 #define TEST_VQ_MAX 17
45 unsigned long hwcap_type
;
51 static const struct vec_type vec_types
[] = {
54 .hwcap_type
= AT_HWCAP
,
57 .prctl_set
= PR_SVE_SET_VL
,
60 .name
= "Streaming SVE",
61 .hwcap_type
= AT_HWCAP2
,
63 .regset
= NT_ARM_SSVE
,
64 .prctl_set
= PR_SME_SET_VL
,
68 #define VL_TESTS (((TEST_VQ_MAX - SVE_VQ_MIN) + 1) * 4)
70 #define FPSIMD_TESTS 2
72 #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types))
74 static void fill_buf(char *buf
, size_t size
)
78 for (i
= 0; i
< size
; i
++)
82 static int do_child(void)
84 if (ptrace(PTRACE_TRACEME
, -1, NULL
, NULL
))
85 ksft_exit_fail_msg("ptrace(PTRACE_TRACEME) failed: %s (%d)\n",
86 strerror(errno
), errno
);
89 ksft_exit_fail_msg("raise(SIGSTOP) failed: %s (%d)\n",
90 strerror(errno
), errno
);
95 static int get_fpsimd(pid_t pid
, struct user_fpsimd_state
*fpsimd
)
99 iov
.iov_base
= fpsimd
;
100 iov
.iov_len
= sizeof(*fpsimd
);
101 return ptrace(PTRACE_GETREGSET
, pid
, NT_PRFPREG
, &iov
);
104 static int set_fpsimd(pid_t pid
, struct user_fpsimd_state
*fpsimd
)
108 iov
.iov_base
= fpsimd
;
109 iov
.iov_len
= sizeof(*fpsimd
);
110 return ptrace(PTRACE_SETREGSET
, pid
, NT_PRFPREG
, &iov
);
113 static struct user_sve_header
*get_sve(pid_t pid
, const struct vec_type
*type
,
114 void **buf
, size_t *size
)
116 struct user_sve_header
*sve
;
118 size_t sz
= sizeof *sve
;
123 p
= realloc(*buf
, sz
);
135 if (ptrace(PTRACE_GETREGSET
, pid
, type
->regset
, &iov
))
151 static int set_sve(pid_t pid
, const struct vec_type
*type
,
152 const struct user_sve_header
*sve
)
156 iov
.iov_base
= (void *)sve
;
157 iov
.iov_len
= sve
->size
;
158 return ptrace(PTRACE_SETREGSET
, pid
, type
->regset
, &iov
);
161 /* Validate setting and getting the inherit flag */
162 static void ptrace_set_get_inherit(pid_t child
, const struct vec_type
*type
)
164 struct user_sve_header sve
;
165 struct user_sve_header
*new_sve
= NULL
;
166 size_t new_sve_size
= 0;
169 /* First set the flag */
170 memset(&sve
, 0, sizeof(sve
));
171 sve
.size
= sizeof(sve
);
172 sve
.vl
= sve_vl_from_vq(SVE_VQ_MIN
);
173 sve
.flags
= SVE_PT_VL_INHERIT
;
174 ret
= set_sve(child
, type
, &sve
);
176 ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
182 * Read back the new register state and verify that we have
183 * set the flags we expected.
185 if (!get_sve(child
, type
, (void **)&new_sve
, &new_sve_size
)) {
186 ksft_test_result_fail("Failed to read %s SVE flags\n",
191 ksft_test_result(new_sve
->flags
& SVE_PT_VL_INHERIT
,
192 "%s SVE_PT_VL_INHERIT set\n", type
->name
);
195 sve
.flags
&= ~SVE_PT_VL_INHERIT
;
196 ret
= set_sve(child
, type
, &sve
);
198 ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
203 if (!get_sve(child
, type
, (void **)&new_sve
, &new_sve_size
)) {
204 ksft_test_result_fail("Failed to read %s SVE flags\n",
209 ksft_test_result(!(new_sve
->flags
& SVE_PT_VL_INHERIT
),
210 "%s SVE_PT_VL_INHERIT cleared\n", type
->name
);
215 /* Validate attempting to set the specfied VL via ptrace */
216 static void ptrace_set_get_vl(pid_t child
, const struct vec_type
*type
,
217 unsigned int vl
, bool *supported
)
219 struct user_sve_header sve
;
220 struct user_sve_header
*new_sve
= NULL
;
221 size_t new_sve_size
= 0;
226 /* Check if the VL is supported in this process */
227 prctl_vl
= prctl(type
->prctl_set
, vl
);
229 ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n",
230 type
->name
, strerror(errno
), errno
);
232 /* If the VL is not supported then a supported VL will be returned */
233 *supported
= (prctl_vl
== vl
);
235 /* Set the VL by doing a set with no register payload */
236 memset(&sve
, 0, sizeof(sve
));
237 sve
.size
= sizeof(sve
);
239 ret
= set_sve(child
, type
, &sve
);
241 ksft_test_result_fail("Failed to set %s VL %u\n",
247 * Read back the new register state and verify that we have the
248 * same VL that we got from prctl() on ourselves.
250 if (!get_sve(child
, type
, (void **)&new_sve
, &new_sve_size
)) {
251 ksft_test_result_fail("Failed to read %s VL %u\n",
256 ksft_test_result(new_sve
->vl
= prctl_vl
, "Set %s VL %u\n",
262 static void check_u32(unsigned int vl
, const char *reg
,
263 uint32_t *in
, uint32_t *out
, int *errors
)
266 printf("# VL %d %s wrote %x read %x\n",
272 /* Access the FPSIMD registers via the SVE regset */
273 static void ptrace_sve_fpsimd(pid_t child
, const struct vec_type
*type
)
276 struct user_sve_header
*sve
;
277 struct user_fpsimd_state
*fpsimd
, new_fpsimd
;
282 svebuf
= malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD
));
284 ksft_test_result_fail("Failed to allocate FPSIMD buffer\n");
288 memset(svebuf
, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD
));
290 sve
->flags
= SVE_PT_REGS_FPSIMD
;
291 sve
->size
= SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD
);
292 sve
->vl
= 16; /* We don't care what the VL is */
294 /* Try to set a known FPSIMD state via PT_REGS_SVE */
295 fpsimd
= (struct user_fpsimd_state
*)((char *)sve
+
296 SVE_PT_FPSIMD_OFFSET
);
297 for (i
= 0; i
< 32; ++i
) {
298 p
= (unsigned char *)&fpsimd
->vregs
[i
];
300 for (j
= 0; j
< sizeof(fpsimd
->vregs
[i
]); ++j
)
304 ret
= set_sve(child
, type
, sve
);
305 ksft_test_result(ret
== 0, "%s FPSIMD set via SVE: %d\n",
310 /* Verify via the FPSIMD regset */
311 if (get_fpsimd(child
, &new_fpsimd
)) {
312 ksft_test_result_fail("get_fpsimd(): %s\n",
316 if (memcmp(fpsimd
, &new_fpsimd
, sizeof(*fpsimd
)) == 0)
317 ksft_test_result_pass("%s get_fpsimd() gave same state\n",
320 ksft_test_result_fail("%s get_fpsimd() gave different state\n",
327 /* Validate attempting to set SVE data and read SVE data */
328 static void ptrace_set_sve_get_sve_data(pid_t child
,
329 const struct vec_type
*type
,
333 void *read_buf
= NULL
;
334 struct user_sve_header
*write_sve
;
335 struct user_sve_header
*read_sve
;
336 size_t read_sve_size
= 0;
337 unsigned int vq
= sve_vq_from_vl(vl
);
342 data_size
= SVE_PT_SVE_OFFSET
+ SVE_PT_SVE_SIZE(vq
, SVE_PT_REGS_SVE
);
343 write_buf
= malloc(data_size
);
345 ksft_test_result_fail("Error allocating %ld byte buffer for %s VL %u\n",
346 data_size
, type
->name
, vl
);
349 write_sve
= write_buf
;
351 /* Set up some data and write it out */
352 memset(write_sve
, 0, data_size
);
353 write_sve
->size
= data_size
;
355 write_sve
->flags
= SVE_PT_REGS_SVE
;
357 for (i
= 0; i
< __SVE_NUM_ZREGS
; i
++)
358 fill_buf(write_buf
+ SVE_PT_SVE_ZREG_OFFSET(vq
, i
),
359 SVE_PT_SVE_ZREG_SIZE(vq
));
361 for (i
= 0; i
< __SVE_NUM_PREGS
; i
++)
362 fill_buf(write_buf
+ SVE_PT_SVE_PREG_OFFSET(vq
, i
),
363 SVE_PT_SVE_PREG_SIZE(vq
));
365 fill_buf(write_buf
+ SVE_PT_SVE_FPSR_OFFSET(vq
), SVE_PT_SVE_FPSR_SIZE
);
366 fill_buf(write_buf
+ SVE_PT_SVE_FPCR_OFFSET(vq
), SVE_PT_SVE_FPCR_SIZE
);
368 /* TODO: Generate a valid FFR pattern */
370 ret
= set_sve(child
, type
, write_sve
);
372 ksft_test_result_fail("Failed to set %s VL %u data\n",
377 /* Read the data back */
378 if (!get_sve(child
, type
, (void **)&read_buf
, &read_sve_size
)) {
379 ksft_test_result_fail("Failed to read %s VL %u data\n",
385 /* We might read more data if there's extensions we don't know */
386 if (read_sve
->size
< write_sve
->size
) {
387 ksft_test_result_fail("%s wrote %d bytes, only read %d\n",
388 type
->name
, write_sve
->size
,
393 for (i
= 0; i
< __SVE_NUM_ZREGS
; i
++) {
394 if (memcmp(write_buf
+ SVE_PT_SVE_ZREG_OFFSET(vq
, i
),
395 read_buf
+ SVE_PT_SVE_ZREG_OFFSET(vq
, i
),
396 SVE_PT_SVE_ZREG_SIZE(vq
)) != 0) {
397 printf("# Mismatch in %u Z%d\n", vl
, i
);
402 for (i
= 0; i
< __SVE_NUM_PREGS
; i
++) {
403 if (memcmp(write_buf
+ SVE_PT_SVE_PREG_OFFSET(vq
, i
),
404 read_buf
+ SVE_PT_SVE_PREG_OFFSET(vq
, i
),
405 SVE_PT_SVE_PREG_SIZE(vq
)) != 0) {
406 printf("# Mismatch in %u P%d\n", vl
, i
);
411 check_u32(vl
, "FPSR", write_buf
+ SVE_PT_SVE_FPSR_OFFSET(vq
),
412 read_buf
+ SVE_PT_SVE_FPSR_OFFSET(vq
), &errors
);
413 check_u32(vl
, "FPCR", write_buf
+ SVE_PT_SVE_FPCR_OFFSET(vq
),
414 read_buf
+ SVE_PT_SVE_FPCR_OFFSET(vq
), &errors
);
416 ksft_test_result(errors
== 0, "Set and get %s data for VL %u\n",
425 /* Validate attempting to set SVE data and read it via the FPSIMD regset */
426 static void ptrace_set_sve_get_fpsimd_data(pid_t child
,
427 const struct vec_type
*type
,
431 struct user_sve_header
*write_sve
;
432 unsigned int vq
= sve_vq_from_vl(vl
);
433 struct user_fpsimd_state fpsimd_state
;
438 if (__BYTE_ORDER
== __BIG_ENDIAN
) {
439 ksft_test_result_skip("Big endian not supported\n");
443 data_size
= SVE_PT_SVE_OFFSET
+ SVE_PT_SVE_SIZE(vq
, SVE_PT_REGS_SVE
);
444 write_buf
= malloc(data_size
);
446 ksft_test_result_fail("Error allocating %ld byte buffer for %s VL %u\n",
447 data_size
, type
->name
, vl
);
450 write_sve
= write_buf
;
452 /* Set up some data and write it out */
453 memset(write_sve
, 0, data_size
);
454 write_sve
->size
= data_size
;
456 write_sve
->flags
= SVE_PT_REGS_SVE
;
458 for (i
= 0; i
< __SVE_NUM_ZREGS
; i
++)
459 fill_buf(write_buf
+ SVE_PT_SVE_ZREG_OFFSET(vq
, i
),
460 SVE_PT_SVE_ZREG_SIZE(vq
));
462 fill_buf(write_buf
+ SVE_PT_SVE_FPSR_OFFSET(vq
), SVE_PT_SVE_FPSR_SIZE
);
463 fill_buf(write_buf
+ SVE_PT_SVE_FPCR_OFFSET(vq
), SVE_PT_SVE_FPCR_SIZE
);
465 ret
= set_sve(child
, type
, write_sve
);
467 ksft_test_result_fail("Failed to set %s VL %u data\n",
472 /* Read the data back */
473 if (get_fpsimd(child
, &fpsimd_state
)) {
474 ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n",
479 for (i
= 0; i
< __SVE_NUM_ZREGS
; i
++) {
483 * Z regs are stored endianness invariant, this won't
484 * work for big endian
486 memcpy(&tmp
, write_buf
+ SVE_PT_SVE_ZREG_OFFSET(vq
, i
),
489 if (tmp
!= fpsimd_state
.vregs
[i
]) {
490 printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
496 check_u32(vl
, "FPSR", write_buf
+ SVE_PT_SVE_FPSR_OFFSET(vq
),
497 &fpsimd_state
.fpsr
, &errors
);
498 check_u32(vl
, "FPCR", write_buf
+ SVE_PT_SVE_FPCR_OFFSET(vq
),
499 &fpsimd_state
.fpcr
, &errors
);
501 ksft_test_result(errors
== 0, "Set and get FPSIMD data for %s VL %u\n",
508 /* Validate attempting to set FPSIMD data and read it via the SVE regset */
509 static void ptrace_set_fpsimd_get_sve_data(pid_t child
,
510 const struct vec_type
*type
,
513 void *read_buf
= NULL
;
515 struct user_sve_header
*read_sve
;
516 unsigned int vq
= sve_vq_from_vl(vl
);
517 struct user_fpsimd_state write_fpsimd
;
519 size_t read_sve_size
= 0;
520 size_t expected_size
;
523 if (__BYTE_ORDER
== __BIG_ENDIAN
) {
524 ksft_test_result_skip("Big endian not supported\n");
528 for (i
= 0; i
< 32; ++i
) {
529 p
= (unsigned char *)&write_fpsimd
.vregs
[i
];
531 for (j
= 0; j
< sizeof(write_fpsimd
.vregs
[i
]); ++j
)
535 ret
= set_fpsimd(child
, &write_fpsimd
);
537 ksft_test_result_fail("Failed to set FPSIMD state: %d\n)",
542 if (!get_sve(child
, type
, (void **)&read_buf
, &read_sve_size
)) {
543 ksft_test_result_fail("Failed to read %s VL %u data\n",
549 if (read_sve
->vl
!= vl
) {
550 ksft_test_result_fail("Child VL != expected VL: %u != %u\n",
555 /* The kernel may return either SVE or FPSIMD format */
556 switch (read_sve
->flags
& SVE_PT_REGS_MASK
) {
557 case SVE_PT_REGS_FPSIMD
:
558 expected_size
= SVE_PT_FPSIMD_SIZE(vq
, SVE_PT_REGS_FPSIMD
);
559 if (read_sve_size
< expected_size
) {
560 ksft_test_result_fail("Read %ld bytes, expected %ld\n",
561 read_sve_size
, expected_size
);
565 ret
= memcmp(&write_fpsimd
, read_buf
+ SVE_PT_FPSIMD_OFFSET
,
566 sizeof(write_fpsimd
));
568 ksft_print_msg("Read FPSIMD data mismatch\n");
573 case SVE_PT_REGS_SVE
:
574 expected_size
= SVE_PT_SVE_SIZE(vq
, SVE_PT_REGS_SVE
);
575 if (read_sve_size
< expected_size
) {
576 ksft_test_result_fail("Read %ld bytes, expected %ld\n",
577 read_sve_size
, expected_size
);
581 for (i
= 0; i
< __SVE_NUM_ZREGS
; i
++) {
585 * Z regs are stored endianness invariant, this won't
586 * work for big endian
588 memcpy(&tmp
, read_buf
+ SVE_PT_SVE_ZREG_OFFSET(vq
, i
),
591 if (tmp
!= write_fpsimd
.vregs
[i
]) {
592 ksft_print_msg("Mismatch in FPSIMD for %s VL %u Z%d/V%d\n",
593 type
->name
, vl
, i
, i
);
598 check_u32(vl
, "FPSR", &write_fpsimd
.fpsr
,
599 read_buf
+ SVE_PT_SVE_FPSR_OFFSET(vq
), &errors
);
600 check_u32(vl
, "FPCR", &write_fpsimd
.fpcr
,
601 read_buf
+ SVE_PT_SVE_FPCR_OFFSET(vq
), &errors
);
604 ksft_print_msg("Unexpected regs type %d\n",
605 read_sve
->flags
& SVE_PT_REGS_MASK
);
610 ksft_test_result(errors
== 0, "Set FPSIMD, read via SVE for %s VL %u\n",
617 static int do_parent(pid_t child
)
619 int ret
= EXIT_FAILURE
;
626 ksft_print_msg("Parent is %d, child is %d\n", getpid(), child
);
628 /* Attach to the child */
639 * This should never happen but it's hard to flag in
645 if (WIFEXITED(status
) || WIFSIGNALED(status
))
646 ksft_exit_fail_msg("Child died unexpectedly\n");
648 if (!WIFSTOPPED(status
))
651 sig
= WSTOPSIG(status
);
653 if (ptrace(PTRACE_GETSIGINFO
, pid
, NULL
, &si
)) {
657 if (errno
== EINVAL
) {
658 sig
= 0; /* bust group-stop */
662 ksft_test_result_fail("PTRACE_GETSIGINFO: %s\n",
667 if (sig
== SIGSTOP
&& si
.si_code
== SI_TKILL
&&
672 if (ptrace(PTRACE_CONT
, pid
, NULL
, sig
)) {
676 ksft_test_result_fail("PTRACE_CONT: %s\n",
682 for (i
= 0; i
< ARRAY_SIZE(vec_types
); i
++) {
683 /* FPSIMD via SVE regset */
684 if (getauxval(vec_types
[i
].hwcap_type
) & vec_types
[i
].hwcap
) {
685 ptrace_sve_fpsimd(child
, &vec_types
[i
]);
687 ksft_test_result_skip("%s FPSIMD set via SVE\n",
689 ksft_test_result_skip("%s FPSIMD read\n",
694 if (getauxval(vec_types
[i
].hwcap_type
) & vec_types
[i
].hwcap
) {
695 ptrace_set_get_inherit(child
, &vec_types
[i
]);
697 ksft_test_result_skip("%s SVE_PT_VL_INHERIT set\n",
699 ksft_test_result_skip("%s SVE_PT_VL_INHERIT cleared\n",
703 /* Step through every possible VQ */
704 for (vq
= SVE_VQ_MIN
; vq
<= TEST_VQ_MAX
; vq
++) {
705 vl
= sve_vl_from_vq(vq
);
707 /* First, try to set this vector length */
708 if (getauxval(vec_types
[i
].hwcap_type
) &
709 vec_types
[i
].hwcap
) {
710 ptrace_set_get_vl(child
, &vec_types
[i
], vl
,
713 ksft_test_result_skip("%s get/set VL %d\n",
714 vec_types
[i
].name
, vl
);
715 vl_supported
= false;
718 /* If the VL is supported validate data set/get */
720 ptrace_set_sve_get_sve_data(child
, &vec_types
[i
], vl
);
721 ptrace_set_sve_get_fpsimd_data(child
, &vec_types
[i
], vl
);
722 ptrace_set_fpsimd_get_sve_data(child
, &vec_types
[i
], vl
);
724 ksft_test_result_skip("%s set SVE get SVE for VL %d\n",
725 vec_types
[i
].name
, vl
);
726 ksft_test_result_skip("%s set SVE get FPSIMD for VL %d\n",
727 vec_types
[i
].name
, vl
);
728 ksft_test_result_skip("%s set FPSIMD get SVE for VL %d\n",
729 vec_types
[i
].name
, vl
);
737 kill(child
, SIGKILL
);
745 int ret
= EXIT_SUCCESS
;
751 ksft_set_plan(EXPECTED_TESTS
);
753 if (!(getauxval(AT_HWCAP
) & HWCAP_SVE
))
754 ksft_exit_skip("SVE not available\n");
760 if (do_parent(child
))