drm/atomic-helper: document drm_atomic_helper_check() restrictions
[drm/drm-misc.git] / tools / testing / selftests / arm64 / fp / sve-ptrace.c
blob577b6e05e860c9942004b19dbfb13f53cdcf3339
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2015-2021 ARM Limited.
4 * Original author: Dave Martin <Dave.Martin@arm.com>
5 */
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/auxv.h>
14 #include <sys/prctl.h>
15 #include <sys/ptrace.h>
16 #include <sys/types.h>
17 #include <sys/uio.h>
18 #include <sys/wait.h>
19 #include <asm/sigcontext.h>
20 #include <asm/ptrace.h>
22 #include "../../kselftest.h"
24 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
25 #ifndef NT_ARM_SVE
26 #define NT_ARM_SVE 0x405
27 #endif
29 #ifndef NT_ARM_SSVE
30 #define NT_ARM_SSVE 0x40b
31 #endif
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
39 * the VL as expected.
41 #define TEST_VQ_MAX 17
43 struct vec_type {
44 const char *name;
45 unsigned long hwcap_type;
46 unsigned long hwcap;
47 int regset;
48 int prctl_set;
51 static const struct vec_type vec_types[] = {
53 .name = "SVE",
54 .hwcap_type = AT_HWCAP,
55 .hwcap = HWCAP_SVE,
56 .regset = NT_ARM_SVE,
57 .prctl_set = PR_SVE_SET_VL,
60 .name = "Streaming SVE",
61 .hwcap_type = AT_HWCAP2,
62 .hwcap = HWCAP2_SME,
63 .regset = NT_ARM_SSVE,
64 .prctl_set = PR_SME_SET_VL,
68 #define VL_TESTS (((TEST_VQ_MAX - SVE_VQ_MIN) + 1) * 4)
69 #define FLAG_TESTS 2
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)
76 int i;
78 for (i = 0; i < size; i++)
79 buf[i] = random();
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);
88 if (raise(SIGSTOP))
89 ksft_exit_fail_msg("raise(SIGSTOP) failed: %s (%d)\n",
90 strerror(errno), errno);
92 return EXIT_SUCCESS;
95 static int get_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
97 struct iovec iov;
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)
106 struct iovec iov;
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;
117 void *p;
118 size_t sz = sizeof *sve;
119 struct iovec iov;
121 while (1) {
122 if (*size < sz) {
123 p = realloc(*buf, sz);
124 if (!p) {
125 errno = ENOMEM;
126 goto error;
129 *buf = p;
130 *size = sz;
133 iov.iov_base = *buf;
134 iov.iov_len = sz;
135 if (ptrace(PTRACE_GETREGSET, pid, type->regset, &iov))
136 goto error;
138 sve = *buf;
139 if (sve->size <= sz)
140 break;
142 sz = sve->size;
145 return sve;
147 error:
148 return NULL;
151 static int set_sve(pid_t pid, const struct vec_type *type,
152 const struct user_sve_header *sve)
154 struct iovec iov;
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;
167 int ret;
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);
175 if (ret != 0) {
176 ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
177 type->name);
178 return;
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",
187 type->name);
188 return;
191 ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT,
192 "%s SVE_PT_VL_INHERIT set\n", type->name);
194 /* Now clear */
195 sve.flags &= ~SVE_PT_VL_INHERIT;
196 ret = set_sve(child, type, &sve);
197 if (ret != 0) {
198 ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
199 type->name);
200 return;
203 if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
204 ksft_test_result_fail("Failed to read %s SVE flags\n",
205 type->name);
206 return;
209 ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT),
210 "%s SVE_PT_VL_INHERIT cleared\n", type->name);
212 free(new_sve);
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;
222 int ret, prctl_vl;
224 *supported = false;
226 /* Check if the VL is supported in this process */
227 prctl_vl = prctl(type->prctl_set, vl);
228 if (prctl_vl == -1)
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);
238 sve.vl = vl;
239 ret = set_sve(child, type, &sve);
240 if (ret != 0) {
241 ksft_test_result_fail("Failed to set %s VL %u\n",
242 type->name, vl);
243 return;
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",
252 type->name, vl);
253 return;
256 ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n",
257 type->name, vl);
259 free(new_sve);
262 static void check_u32(unsigned int vl, const char *reg,
263 uint32_t *in, uint32_t *out, int *errors)
265 if (*in != *out) {
266 printf("# VL %d %s wrote %x read %x\n",
267 vl, reg, *in, *out);
268 (*errors)++;
272 /* Access the FPSIMD registers via the SVE regset */
273 static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
275 void *svebuf;
276 struct user_sve_header *sve;
277 struct user_fpsimd_state *fpsimd, new_fpsimd;
278 unsigned int i, j;
279 unsigned char *p;
280 int ret;
282 svebuf = malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
283 if (!svebuf) {
284 ksft_test_result_fail("Failed to allocate FPSIMD buffer\n");
285 return;
288 memset(svebuf, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
289 sve = svebuf;
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)
301 p[j] = j;
304 ret = set_sve(child, type, sve);
305 ksft_test_result(ret == 0, "%s FPSIMD set via SVE: %d\n",
306 type->name, ret);
307 if (ret)
308 goto out;
310 /* Verify via the FPSIMD regset */
311 if (get_fpsimd(child, &new_fpsimd)) {
312 ksft_test_result_fail("get_fpsimd(): %s\n",
313 strerror(errno));
314 goto out;
316 if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0)
317 ksft_test_result_pass("%s get_fpsimd() gave same state\n",
318 type->name);
319 else
320 ksft_test_result_fail("%s get_fpsimd() gave different state\n",
321 type->name);
323 out:
324 free(svebuf);
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,
330 unsigned int vl)
332 void *write_buf;
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);
338 int ret, i;
339 size_t data_size;
340 int errors = 0;
342 data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
343 write_buf = malloc(data_size);
344 if (!write_buf) {
345 ksft_test_result_fail("Error allocating %ld byte buffer for %s VL %u\n",
346 data_size, type->name, vl);
347 return;
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;
354 write_sve->vl = vl;
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);
371 if (ret != 0) {
372 ksft_test_result_fail("Failed to set %s VL %u data\n",
373 type->name, vl);
374 goto out;
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",
380 type->name, vl);
381 goto out;
383 read_sve = read_buf;
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,
389 read_sve->size);
390 goto out_read;
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);
398 errors++;
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);
407 errors++;
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",
417 type->name, vl);
419 out_read:
420 free(read_buf);
421 out:
422 free(write_buf);
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,
428 unsigned int vl)
430 void *write_buf;
431 struct user_sve_header *write_sve;
432 unsigned int vq = sve_vq_from_vl(vl);
433 struct user_fpsimd_state fpsimd_state;
434 int ret, i;
435 size_t data_size;
436 int errors = 0;
438 if (__BYTE_ORDER == __BIG_ENDIAN) {
439 ksft_test_result_skip("Big endian not supported\n");
440 return;
443 data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
444 write_buf = malloc(data_size);
445 if (!write_buf) {
446 ksft_test_result_fail("Error allocating %ld byte buffer for %s VL %u\n",
447 data_size, type->name, vl);
448 return;
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;
455 write_sve->vl = vl;
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);
466 if (ret != 0) {
467 ksft_test_result_fail("Failed to set %s VL %u data\n",
468 type->name, vl);
469 goto out;
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",
475 type->name, vl);
476 goto out;
479 for (i = 0; i < __SVE_NUM_ZREGS; i++) {
480 __uint128_t tmp = 0;
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),
487 sizeof(tmp));
489 if (tmp != fpsimd_state.vregs[i]) {
490 printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
491 type->name, vl, i);
492 errors++;
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",
502 type->name, vl);
504 out:
505 free(write_buf);
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,
511 unsigned int vl)
513 void *read_buf = NULL;
514 unsigned char *p;
515 struct user_sve_header *read_sve;
516 unsigned int vq = sve_vq_from_vl(vl);
517 struct user_fpsimd_state write_fpsimd;
518 int ret, i, j;
519 size_t read_sve_size = 0;
520 size_t expected_size;
521 int errors = 0;
523 if (__BYTE_ORDER == __BIG_ENDIAN) {
524 ksft_test_result_skip("Big endian not supported\n");
525 return;
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)
532 p[j] = j;
535 ret = set_fpsimd(child, &write_fpsimd);
536 if (ret != 0) {
537 ksft_test_result_fail("Failed to set FPSIMD state: %d\n)",
538 ret);
539 return;
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",
544 type->name, vl);
545 return;
547 read_sve = read_buf;
549 if (read_sve->vl != vl) {
550 ksft_test_result_fail("Child VL != expected VL: %u != %u\n",
551 read_sve->vl, vl);
552 goto out;
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);
562 goto out;
565 ret = memcmp(&write_fpsimd, read_buf + SVE_PT_FPSIMD_OFFSET,
566 sizeof(write_fpsimd));
567 if (ret != 0) {
568 ksft_print_msg("Read FPSIMD data mismatch\n");
569 errors++;
571 break;
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);
578 goto out;
581 for (i = 0; i < __SVE_NUM_ZREGS; i++) {
582 __uint128_t tmp = 0;
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),
589 sizeof(tmp));
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);
594 errors++;
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);
602 break;
603 default:
604 ksft_print_msg("Unexpected regs type %d\n",
605 read_sve->flags & SVE_PT_REGS_MASK);
606 errors++;
607 break;
610 ksft_test_result(errors == 0, "Set FPSIMD, read via SVE for %s VL %u\n",
611 type->name, vl);
613 out:
614 free(read_buf);
617 static int do_parent(pid_t child)
619 int ret = EXIT_FAILURE;
620 pid_t pid;
621 int status, i;
622 siginfo_t si;
623 unsigned int vq, vl;
624 bool vl_supported;
626 ksft_print_msg("Parent is %d, child is %d\n", getpid(), child);
628 /* Attach to the child */
629 while (1) {
630 int sig;
632 pid = wait(&status);
633 if (pid == -1) {
634 perror("wait");
635 goto error;
639 * This should never happen but it's hard to flag in
640 * the framework.
642 if (pid != child)
643 continue;
645 if (WIFEXITED(status) || WIFSIGNALED(status))
646 ksft_exit_fail_msg("Child died unexpectedly\n");
648 if (!WIFSTOPPED(status))
649 goto error;
651 sig = WSTOPSIG(status);
653 if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &si)) {
654 if (errno == ESRCH)
655 goto disappeared;
657 if (errno == EINVAL) {
658 sig = 0; /* bust group-stop */
659 goto cont;
662 ksft_test_result_fail("PTRACE_GETSIGINFO: %s\n",
663 strerror(errno));
664 goto error;
667 if (sig == SIGSTOP && si.si_code == SI_TKILL &&
668 si.si_pid == pid)
669 break;
671 cont:
672 if (ptrace(PTRACE_CONT, pid, NULL, sig)) {
673 if (errno == ESRCH)
674 goto disappeared;
676 ksft_test_result_fail("PTRACE_CONT: %s\n",
677 strerror(errno));
678 goto error;
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]);
686 } else {
687 ksft_test_result_skip("%s FPSIMD set via SVE\n",
688 vec_types[i].name);
689 ksft_test_result_skip("%s FPSIMD read\n",
690 vec_types[i].name);
693 /* prctl() flags */
694 if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
695 ptrace_set_get_inherit(child, &vec_types[i]);
696 } else {
697 ksft_test_result_skip("%s SVE_PT_VL_INHERIT set\n",
698 vec_types[i].name);
699 ksft_test_result_skip("%s SVE_PT_VL_INHERIT cleared\n",
700 vec_types[i].name);
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,
711 &vl_supported);
712 } else {
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 */
719 if (vl_supported) {
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);
723 } else {
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);
734 ret = EXIT_SUCCESS;
736 error:
737 kill(child, SIGKILL);
739 disappeared:
740 return ret;
743 int main(void)
745 int ret = EXIT_SUCCESS;
746 pid_t child;
748 srandom(getpid());
750 ksft_print_header();
751 ksft_set_plan(EXPECTED_TESTS);
753 if (!(getauxval(AT_HWCAP) & HWCAP_SVE))
754 ksft_exit_skip("SVE not available\n");
756 child = fork();
757 if (!child)
758 return do_child();
760 if (do_parent(child))
761 ret = EXIT_FAILURE;
763 ksft_print_cnts();
765 return ret;