Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / tools / testing / selftests / arm64 / fp / fp-stress.c
blob74e23208b94cabad165819ffa35733374649d8aa
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2022 ARM Limited.
4 */
6 #define _GNU_SOURCE
7 #define _POSIX_C_SOURCE 199309L
9 #include <errno.h>
10 #include <getopt.h>
11 #include <poll.h>
12 #include <signal.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/auxv.h>
20 #include <sys/epoll.h>
21 #include <sys/prctl.h>
22 #include <sys/types.h>
23 #include <sys/uio.h>
24 #include <sys/wait.h>
25 #include <asm/hwcap.h>
27 #include "../../kselftest.h"
29 #define MAX_VLS 16
31 #define SIGNAL_INTERVAL_MS 25
32 #define LOG_INTERVALS (1000 / SIGNAL_INTERVAL_MS)
34 struct child_data {
35 char *name, *output;
36 pid_t pid;
37 int stdout;
38 bool output_seen;
39 bool exited;
40 int exit_status;
43 static int epoll_fd;
44 static struct child_data *children;
45 static struct epoll_event *evs;
46 static int tests;
47 static int num_children;
48 static bool terminate;
50 static int startup_pipe[2];
52 static int num_processors(void)
54 long nproc = sysconf(_SC_NPROCESSORS_CONF);
55 if (nproc < 0) {
56 perror("Unable to read number of processors\n");
57 exit(EXIT_FAILURE);
60 return nproc;
63 static void child_start(struct child_data *child, const char *program)
65 int ret, pipefd[2], i;
66 struct epoll_event ev;
68 ret = pipe(pipefd);
69 if (ret != 0)
70 ksft_exit_fail_msg("Failed to create stdout pipe: %s (%d)\n",
71 strerror(errno), errno);
73 child->pid = fork();
74 if (child->pid == -1)
75 ksft_exit_fail_msg("fork() failed: %s (%d)\n",
76 strerror(errno), errno);
78 if (!child->pid) {
80 * In child, replace stdout with the pipe, errors to
81 * stderr from here as kselftest prints to stdout.
83 ret = dup2(pipefd[1], 1);
84 if (ret == -1) {
85 printf("dup2() %d\n", errno);
86 exit(EXIT_FAILURE);
90 * Duplicate the read side of the startup pipe to
91 * FD 3 so we can close everything else.
93 ret = dup2(startup_pipe[0], 3);
94 if (ret == -1) {
95 printf("dup2() %d\n", errno);
96 exit(EXIT_FAILURE);
100 * Very dumb mechanism to clean open FDs other than
101 * stdio. We don't want O_CLOEXEC for the pipes...
103 for (i = 4; i < 8192; i++)
104 close(i);
107 * Read from the startup pipe, there should be no data
108 * and we should block until it is closed. We just
109 * carry on on error since this isn't super critical.
111 ret = read(3, &i, sizeof(i));
112 if (ret < 0)
113 printf("read(startp pipe) failed: %s (%d)\n",
114 strerror(errno), errno);
115 if (ret > 0)
116 printf("%d bytes of data on startup pipe\n", ret);
117 close(3);
119 ret = execl(program, program, NULL);
120 printf("execl(%s) failed: %d (%s)\n",
121 program, errno, strerror(errno));
123 exit(EXIT_FAILURE);
124 } else {
126 * In parent, remember the child and close our copy of the
127 * write side of stdout.
129 close(pipefd[1]);
130 child->stdout = pipefd[0];
131 child->output = NULL;
132 child->exited = false;
133 child->output_seen = false;
135 ev.events = EPOLLIN | EPOLLHUP;
136 ev.data.ptr = child;
138 ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, child->stdout, &ev);
139 if (ret < 0) {
140 ksft_exit_fail_msg("%s EPOLL_CTL_ADD failed: %s (%d)\n",
141 child->name, strerror(errno), errno);
146 static bool child_output_read(struct child_data *child)
148 char read_data[1024];
149 char work[1024];
150 int ret, len, cur_work, cur_read;
152 ret = read(child->stdout, read_data, sizeof(read_data));
153 if (ret < 0) {
154 if (errno == EINTR)
155 return true;
157 ksft_print_msg("%s: read() failed: %s (%d)\n",
158 child->name, strerror(errno),
159 errno);
160 return false;
162 len = ret;
164 child->output_seen = true;
166 /* Pick up any partial read */
167 if (child->output) {
168 strncpy(work, child->output, sizeof(work) - 1);
169 cur_work = strnlen(work, sizeof(work));
170 free(child->output);
171 child->output = NULL;
172 } else {
173 cur_work = 0;
176 cur_read = 0;
177 while (cur_read < len) {
178 work[cur_work] = read_data[cur_read++];
180 if (work[cur_work] == '\n') {
181 work[cur_work] = '\0';
182 ksft_print_msg("%s: %s\n", child->name, work);
183 cur_work = 0;
184 } else {
185 cur_work++;
189 if (cur_work) {
190 work[cur_work] = '\0';
191 ret = asprintf(&child->output, "%s", work);
192 if (ret == -1)
193 ksft_exit_fail_msg("Out of memory\n");
196 return false;
199 static void child_output(struct child_data *child, uint32_t events,
200 bool flush)
202 bool read_more;
204 if (events & EPOLLIN) {
205 do {
206 read_more = child_output_read(child);
207 } while (read_more);
210 if (events & EPOLLHUP) {
211 close(child->stdout);
212 child->stdout = -1;
213 flush = true;
216 if (flush && child->output) {
217 ksft_print_msg("%s: %s<EOF>\n", child->name, child->output);
218 free(child->output);
219 child->output = NULL;
223 static void child_tickle(struct child_data *child)
225 if (child->output_seen && !child->exited)
226 kill(child->pid, SIGUSR1);
229 static void child_stop(struct child_data *child)
231 if (!child->exited)
232 kill(child->pid, SIGTERM);
235 static void child_cleanup(struct child_data *child)
237 pid_t ret;
238 int status;
239 bool fail = false;
241 if (!child->exited) {
242 do {
243 ret = waitpid(child->pid, &status, 0);
244 if (ret == -1 && errno == EINTR)
245 continue;
247 if (ret == -1) {
248 ksft_print_msg("waitpid(%d) failed: %s (%d)\n",
249 child->pid, strerror(errno),
250 errno);
251 fail = true;
252 break;
254 } while (!WIFEXITED(status));
255 child->exit_status = WEXITSTATUS(status);
258 if (!child->output_seen) {
259 ksft_print_msg("%s no output seen\n", child->name);
260 fail = true;
263 if (child->exit_status != 0) {
264 ksft_print_msg("%s exited with error code %d\n",
265 child->name, child->exit_status);
266 fail = true;
269 ksft_test_result(!fail, "%s\n", child->name);
272 static void handle_child_signal(int sig, siginfo_t *info, void *context)
274 int i;
275 bool found = false;
277 for (i = 0; i < num_children; i++) {
278 if (children[i].pid == info->si_pid) {
279 children[i].exited = true;
280 children[i].exit_status = info->si_status;
281 found = true;
282 break;
286 if (!found)
287 ksft_print_msg("SIGCHLD for unknown PID %d with status %d\n",
288 info->si_pid, info->si_status);
291 static void handle_exit_signal(int sig, siginfo_t *info, void *context)
293 int i;
295 /* If we're already exiting then don't signal again */
296 if (terminate)
297 return;
299 ksft_print_msg("Got signal, exiting...\n");
301 terminate = true;
304 * This should be redundant, the main loop should clean up
305 * after us, but for safety stop everything we can here.
307 for (i = 0; i < num_children; i++)
308 child_stop(&children[i]);
311 static void start_fpsimd(struct child_data *child, int cpu, int copy)
313 int ret;
315 ret = asprintf(&child->name, "FPSIMD-%d-%d", cpu, copy);
316 if (ret == -1)
317 ksft_exit_fail_msg("asprintf() failed\n");
319 child_start(child, "./fpsimd-test");
321 ksft_print_msg("Started %s\n", child->name);
324 static void start_kernel(struct child_data *child, int cpu, int copy)
326 int ret;
328 ret = asprintf(&child->name, "KERNEL-%d-%d", cpu, copy);
329 if (ret == -1)
330 ksft_exit_fail_msg("asprintf() failed\n");
332 child_start(child, "./kernel-test");
334 ksft_print_msg("Started %s\n", child->name);
337 static void start_sve(struct child_data *child, int vl, int cpu)
339 int ret;
341 ret = prctl(PR_SVE_SET_VL, vl | PR_SVE_VL_INHERIT);
342 if (ret < 0)
343 ksft_exit_fail_msg("Failed to set SVE VL %d\n", vl);
345 ret = asprintf(&child->name, "SVE-VL-%d-%d", vl, cpu);
346 if (ret == -1)
347 ksft_exit_fail_msg("asprintf() failed\n");
349 child_start(child, "./sve-test");
351 ksft_print_msg("Started %s\n", child->name);
354 static void start_ssve(struct child_data *child, int vl, int cpu)
356 int ret;
358 ret = asprintf(&child->name, "SSVE-VL-%d-%d", vl, cpu);
359 if (ret == -1)
360 ksft_exit_fail_msg("asprintf() failed\n");
362 ret = prctl(PR_SME_SET_VL, vl | PR_SME_VL_INHERIT);
363 if (ret < 0)
364 ksft_exit_fail_msg("Failed to set SME VL %d\n", ret);
366 child_start(child, "./ssve-test");
368 ksft_print_msg("Started %s\n", child->name);
371 static void start_za(struct child_data *child, int vl, int cpu)
373 int ret;
375 ret = prctl(PR_SME_SET_VL, vl | PR_SVE_VL_INHERIT);
376 if (ret < 0)
377 ksft_exit_fail_msg("Failed to set SME VL %d\n", ret);
379 ret = asprintf(&child->name, "ZA-VL-%d-%d", vl, cpu);
380 if (ret == -1)
381 ksft_exit_fail_msg("asprintf() failed\n");
383 child_start(child, "./za-test");
385 ksft_print_msg("Started %s\n", child->name);
388 static void start_zt(struct child_data *child, int cpu)
390 int ret;
392 ret = asprintf(&child->name, "ZT-%d", cpu);
393 if (ret == -1)
394 ksft_exit_fail_msg("asprintf() failed\n");
396 child_start(child, "./zt-test");
398 ksft_print_msg("Started %s\n", child->name);
401 static void probe_vls(int vls[], int *vl_count, int set_vl)
403 unsigned int vq;
404 int vl;
406 *vl_count = 0;
408 for (vq = SVE_VQ_MAX; vq > 0; vq /= 2) {
409 vl = prctl(set_vl, vq * 16);
410 if (vl == -1)
411 ksft_exit_fail_msg("SET_VL failed: %s (%d)\n",
412 strerror(errno), errno);
414 vl &= PR_SVE_VL_LEN_MASK;
416 if (*vl_count && (vl == vls[*vl_count - 1]))
417 break;
419 vq = sve_vq_from_vl(vl);
421 vls[*vl_count] = vl;
422 *vl_count += 1;
426 /* Handle any pending output without blocking */
427 static void drain_output(bool flush)
429 int ret = 1;
430 int i;
432 while (ret > 0) {
433 ret = epoll_wait(epoll_fd, evs, tests, 0);
434 if (ret < 0) {
435 if (errno == EINTR)
436 continue;
437 ksft_print_msg("epoll_wait() failed: %s (%d)\n",
438 strerror(errno), errno);
441 for (i = 0; i < ret; i++)
442 child_output(evs[i].data.ptr, evs[i].events, flush);
446 static const struct option options[] = {
447 { "timeout", required_argument, NULL, 't' },
451 int main(int argc, char **argv)
453 int ret;
454 int timeout = 10 * (1000 / SIGNAL_INTERVAL_MS);
455 int poll_interval = 5000;
456 int cpus, i, j, c;
457 int sve_vl_count, sme_vl_count;
458 bool all_children_started = false;
459 int seen_children;
460 int sve_vls[MAX_VLS], sme_vls[MAX_VLS];
461 bool have_sme2;
462 struct sigaction sa;
464 while ((c = getopt_long(argc, argv, "t:", options, NULL)) != -1) {
465 switch (c) {
466 case 't':
467 ret = sscanf(optarg, "%d", &timeout);
468 if (ret != 1)
469 ksft_exit_fail_msg("Failed to parse timeout %s\n",
470 optarg);
471 break;
472 default:
473 ksft_exit_fail_msg("Unknown argument\n");
477 cpus = num_processors();
478 tests = 0;
480 if (getauxval(AT_HWCAP) & HWCAP_SVE) {
481 probe_vls(sve_vls, &sve_vl_count, PR_SVE_SET_VL);
482 tests += sve_vl_count * cpus;
483 } else {
484 sve_vl_count = 0;
487 if (getauxval(AT_HWCAP2) & HWCAP2_SME) {
488 probe_vls(sme_vls, &sme_vl_count, PR_SME_SET_VL);
489 tests += sme_vl_count * cpus * 2;
490 } else {
491 sme_vl_count = 0;
494 if (getauxval(AT_HWCAP2) & HWCAP2_SME2) {
495 tests += cpus;
496 have_sme2 = true;
497 } else {
498 have_sme2 = false;
501 tests += cpus * 2;
503 ksft_print_header();
504 ksft_set_plan(tests);
506 ksft_print_msg("%d CPUs, %d SVE VLs, %d SME VLs, SME2 %s\n",
507 cpus, sve_vl_count, sme_vl_count,
508 have_sme2 ? "present" : "absent");
510 if (timeout > 0)
511 ksft_print_msg("Will run for %d\n", timeout);
512 else
513 ksft_print_msg("Will run until terminated\n");
515 children = calloc(sizeof(*children), tests);
516 if (!children)
517 ksft_exit_fail_msg("Unable to allocate child data\n");
519 ret = epoll_create1(EPOLL_CLOEXEC);
520 if (ret < 0)
521 ksft_exit_fail_msg("epoll_create1() failed: %s (%d)\n",
522 strerror(errno), ret);
523 epoll_fd = ret;
525 /* Create a pipe which children will block on before execing */
526 ret = pipe(startup_pipe);
527 if (ret != 0)
528 ksft_exit_fail_msg("Failed to create startup pipe: %s (%d)\n",
529 strerror(errno), errno);
531 /* Get signal handers ready before we start any children */
532 memset(&sa, 0, sizeof(sa));
533 sa.sa_sigaction = handle_exit_signal;
534 sa.sa_flags = SA_RESTART | SA_SIGINFO;
535 sigemptyset(&sa.sa_mask);
536 ret = sigaction(SIGINT, &sa, NULL);
537 if (ret < 0)
538 ksft_print_msg("Failed to install SIGINT handler: %s (%d)\n",
539 strerror(errno), errno);
540 ret = sigaction(SIGTERM, &sa, NULL);
541 if (ret < 0)
542 ksft_print_msg("Failed to install SIGTERM handler: %s (%d)\n",
543 strerror(errno), errno);
544 sa.sa_sigaction = handle_child_signal;
545 ret = sigaction(SIGCHLD, &sa, NULL);
546 if (ret < 0)
547 ksft_print_msg("Failed to install SIGCHLD handler: %s (%d)\n",
548 strerror(errno), errno);
550 evs = calloc(tests, sizeof(*evs));
551 if (!evs)
552 ksft_exit_fail_msg("Failed to allocated %d epoll events\n",
553 tests);
555 for (i = 0; i < cpus; i++) {
556 start_fpsimd(&children[num_children++], i, 0);
557 start_kernel(&children[num_children++], i, 0);
559 for (j = 0; j < sve_vl_count; j++)
560 start_sve(&children[num_children++], sve_vls[j], i);
562 for (j = 0; j < sme_vl_count; j++) {
563 start_ssve(&children[num_children++], sme_vls[j], i);
564 start_za(&children[num_children++], sme_vls[j], i);
567 if (have_sme2)
568 start_zt(&children[num_children++], i);
572 * All children started, close the startup pipe and let them
573 * run.
575 close(startup_pipe[0]);
576 close(startup_pipe[1]);
578 for (;;) {
579 /* Did we get a signal asking us to exit? */
580 if (terminate)
581 break;
584 * Timeout is counted in poll intervals with no
585 * output, the tests print during startup then are
586 * silent when running so this should ensure they all
587 * ran enough to install the signal handler, this is
588 * especially useful in emulation where we will both
589 * be slow and likely to have a large set of VLs.
591 ret = epoll_wait(epoll_fd, evs, tests, poll_interval);
592 if (ret < 0) {
593 if (errno == EINTR)
594 continue;
595 ksft_exit_fail_msg("epoll_wait() failed: %s (%d)\n",
596 strerror(errno), errno);
599 /* Output? */
600 if (ret > 0) {
601 for (i = 0; i < ret; i++) {
602 child_output(evs[i].data.ptr, evs[i].events,
603 false);
605 continue;
608 /* Otherwise epoll_wait() timed out */
611 * If the child processes have not produced output they
612 * aren't actually running the tests yet .
614 if (!all_children_started) {
615 seen_children = 0;
617 for (i = 0; i < num_children; i++)
618 if (children[i].output_seen ||
619 children[i].exited)
620 seen_children++;
622 if (seen_children != num_children) {
623 ksft_print_msg("Waiting for %d children\n",
624 num_children - seen_children);
625 continue;
628 all_children_started = true;
629 poll_interval = SIGNAL_INTERVAL_MS;
632 if ((timeout % LOG_INTERVALS) == 0)
633 ksft_print_msg("Sending signals, timeout remaining: %d\n",
634 timeout);
636 for (i = 0; i < num_children; i++)
637 child_tickle(&children[i]);
639 /* Negative timeout means run indefinitely */
640 if (timeout < 0)
641 continue;
642 if (--timeout == 0)
643 break;
646 ksft_print_msg("Finishing up...\n");
647 terminate = true;
649 for (i = 0; i < tests; i++)
650 child_stop(&children[i]);
652 drain_output(false);
654 for (i = 0; i < tests; i++)
655 child_cleanup(&children[i]);
657 drain_output(true);
659 ksft_finished();