xref: /linux/tools/testing/selftests/arm64/fp/fp-stress.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2022 ARM Limited.
4  */
5 
6 #define _GNU_SOURCE
7 #define _POSIX_C_SOURCE 199309L
8 
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>
26 
27 #include "../../kselftest.h"
28 
29 #define MAX_VLS 16
30 
31 #define SIGNAL_INTERVAL_MS 25
32 #define LOG_INTERVALS (1000 / SIGNAL_INTERVAL_MS)
33 
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;
41 };
42 
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;
49 
50 static int startup_pipe[2];
51 
52 static int num_processors(void)
53 {
54 	long nproc = sysconf(_SC_NPROCESSORS_CONF);
55 	if (nproc < 0) {
56 		perror("Unable to read number of processors\n");
57 		exit(EXIT_FAILURE);
58 	}
59 
60 	return nproc;
61 }
62 
63 static void child_start(struct child_data *child, const char *program)
64 {
65 	int ret, pipefd[2], i;
66 	struct epoll_event ev;
67 
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);
72 
73 	child->pid = fork();
74 	if (child->pid == -1)
75 		ksft_exit_fail_msg("fork() failed: %s (%d)\n",
76 				   strerror(errno), errno);
77 
78 	if (!child->pid) {
79 		/*
80 		 * In child, replace stdout with the pipe, errors to
81 		 * stderr from here as kselftest prints to stdout.
82 		 */
83 		ret = dup2(pipefd[1], 1);
84 		if (ret == -1) {
85 			printf("dup2() %d\n", errno);
86 			exit(EXIT_FAILURE);
87 		}
88 
89 		/*
90 		 * Duplicate the read side of the startup pipe to
91 		 * FD 3 so we can close everything else.
92 		 */
93 		ret = dup2(startup_pipe[0], 3);
94 		if (ret == -1) {
95 			printf("dup2() %d\n", errno);
96 			exit(EXIT_FAILURE);
97 		}
98 
99 		/*
100 		 * Very dumb mechanism to clean open FDs other than
101 		 * stdio. We don't want O_CLOEXEC for the pipes...
102 		 */
103 		for (i = 4; i < 8192; i++)
104 			close(i);
105 
106 		/*
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.
110 		 */
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);
118 
119 		ret = execl(program, program, NULL);
120 		printf("execl(%s) failed: %d (%s)\n",
121 		       program, errno, strerror(errno));
122 
123 		exit(EXIT_FAILURE);
124 	} else {
125 		/*
126 		 * In parent, remember the child and close our copy of the
127 		 * write side of stdout.
128 		 */
129 		close(pipefd[1]);
130 		child->stdout = pipefd[0];
131 		child->output = NULL;
132 		child->exited = false;
133 		child->output_seen = false;
134 
135 		ev.events = EPOLLIN | EPOLLHUP;
136 		ev.data.ptr = child;
137 
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);
142 		}
143 	}
144 }
145 
146 static bool child_output_read(struct child_data *child)
147 {
148 	char read_data[1024];
149 	char work[1024];
150 	int ret, len, cur_work, cur_read;
151 
152 	ret = read(child->stdout, read_data, sizeof(read_data));
153 	if (ret < 0) {
154 		if (errno == EINTR)
155 			return true;
156 
157 		ksft_print_msg("%s: read() failed: %s (%d)\n",
158 			       child->name, strerror(errno),
159 			       errno);
160 		return false;
161 	}
162 	len = ret;
163 
164 	child->output_seen = true;
165 
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;
174 	}
175 
176 	cur_read = 0;
177 	while (cur_read < len) {
178 		work[cur_work] = read_data[cur_read++];
179 
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++;
186 		}
187 	}
188 
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");
194 	}
195 
196 	return false;
197 }
198 
199 static void child_output(struct child_data *child, uint32_t events,
200 			 bool flush)
201 {
202 	bool read_more;
203 
204 	if (events & EPOLLIN) {
205 		do {
206 			read_more = child_output_read(child);
207 		} while (read_more);
208 	}
209 
210 	if (events & EPOLLHUP) {
211 		close(child->stdout);
212 		child->stdout = -1;
213 		flush = true;
214 	}
215 
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;
220 	}
221 }
222 
223 static void child_tickle(struct child_data *child)
224 {
225 	if (child->output_seen && !child->exited)
226 		kill(child->pid, SIGUSR1);
227 }
228 
229 static void child_stop(struct child_data *child)
230 {
231 	if (!child->exited)
232 		kill(child->pid, SIGTERM);
233 }
234 
235 static void child_cleanup(struct child_data *child)
236 {
237 	pid_t ret;
238 	int status;
239 	bool fail = false;
240 
241 	if (!child->exited) {
242 		do {
243 			ret = waitpid(child->pid, &status, 0);
244 			if (ret == -1 && errno == EINTR)
245 				continue;
246 
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;
253 			}
254 		} while (!WIFEXITED(status));
255 		child->exit_status = WEXITSTATUS(status);
256 	}
257 
258 	if (!child->output_seen) {
259 		ksft_print_msg("%s no output seen\n", child->name);
260 		fail = true;
261 	}
262 
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;
267 	}
268 
269 	ksft_test_result(!fail, "%s\n", child->name);
270 }
271 
272 static void handle_child_signal(int sig, siginfo_t *info, void *context)
273 {
274 	int i;
275 	bool found = false;
276 
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;
283 		}
284 	}
285 
286 	if (!found)
287 		ksft_print_msg("SIGCHLD for unknown PID %d with status %d\n",
288 			       info->si_pid, info->si_status);
289 }
290 
291 static void handle_exit_signal(int sig, siginfo_t *info, void *context)
292 {
293 	int i;
294 
295 	/* If we're already exiting then don't signal again */
296 	if (terminate)
297 		return;
298 
299 	ksft_print_msg("Got signal, exiting...\n");
300 
301 	terminate = true;
302 
303 	/*
304 	 * This should be redundant, the main loop should clean up
305 	 * after us, but for safety stop everything we can here.
306 	 */
307 	for (i = 0; i < num_children; i++)
308 		child_stop(&children[i]);
309 }
310 
311 static void start_fpsimd(struct child_data *child, int cpu, int copy)
312 {
313 	int ret;
314 
315 	ret = asprintf(&child->name, "FPSIMD-%d-%d", cpu, copy);
316 	if (ret == -1)
317 		ksft_exit_fail_msg("asprintf() failed\n");
318 
319 	child_start(child, "./fpsimd-test");
320 
321 	ksft_print_msg("Started %s\n", child->name);
322 }
323 
324 static void start_kernel(struct child_data *child, int cpu, int copy)
325 {
326 	int ret;
327 
328 	ret = asprintf(&child->name, "KERNEL-%d-%d", cpu, copy);
329 	if (ret == -1)
330 		ksft_exit_fail_msg("asprintf() failed\n");
331 
332 	child_start(child, "./kernel-test");
333 
334 	ksft_print_msg("Started %s\n", child->name);
335 }
336 
337 static void start_sve(struct child_data *child, int vl, int cpu)
338 {
339 	int ret;
340 
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);
344 
345 	ret = asprintf(&child->name, "SVE-VL-%d-%d", vl, cpu);
346 	if (ret == -1)
347 		ksft_exit_fail_msg("asprintf() failed\n");
348 
349 	child_start(child, "./sve-test");
350 
351 	ksft_print_msg("Started %s\n", child->name);
352 }
353 
354 static void start_ssve(struct child_data *child, int vl, int cpu)
355 {
356 	int ret;
357 
358 	ret = asprintf(&child->name, "SSVE-VL-%d-%d", vl, cpu);
359 	if (ret == -1)
360 		ksft_exit_fail_msg("asprintf() failed\n");
361 
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);
365 
366 	child_start(child, "./ssve-test");
367 
368 	ksft_print_msg("Started %s\n", child->name);
369 }
370 
371 static void start_za(struct child_data *child, int vl, int cpu)
372 {
373 	int ret;
374 
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);
378 
379 	ret = asprintf(&child->name, "ZA-VL-%d-%d", vl, cpu);
380 	if (ret == -1)
381 		ksft_exit_fail_msg("asprintf() failed\n");
382 
383 	child_start(child, "./za-test");
384 
385 	ksft_print_msg("Started %s\n", child->name);
386 }
387 
388 static void start_zt(struct child_data *child, int cpu)
389 {
390 	int ret;
391 
392 	ret = asprintf(&child->name, "ZT-%d", cpu);
393 	if (ret == -1)
394 		ksft_exit_fail_msg("asprintf() failed\n");
395 
396 	child_start(child, "./zt-test");
397 
398 	ksft_print_msg("Started %s\n", child->name);
399 }
400 
401 static void probe_vls(int vls[], int *vl_count, int set_vl)
402 {
403 	unsigned int vq;
404 	int vl;
405 
406 	*vl_count = 0;
407 
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);
413 
414 		vl &= PR_SVE_VL_LEN_MASK;
415 
416 		if (*vl_count && (vl == vls[*vl_count - 1]))
417 			break;
418 
419 		vq = sve_vq_from_vl(vl);
420 
421 		vls[*vl_count] = vl;
422 		*vl_count += 1;
423 	}
424 }
425 
426 /* Handle any pending output without blocking */
427 static void drain_output(bool flush)
428 {
429 	int ret = 1;
430 	int i;
431 
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);
439 		}
440 
441 		for (i = 0; i < ret; i++)
442 			child_output(evs[i].data.ptr, evs[i].events, flush);
443 	}
444 }
445 
446 static const struct option options[] = {
447 	{ "timeout",	required_argument, NULL, 't' },
448 	{ }
449 };
450 
451 int main(int argc, char **argv)
452 {
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;
463 
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");
474 		}
475 	}
476 
477 	cpus = num_processors();
478 	tests = 0;
479 
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;
485 	}
486 
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;
492 	}
493 
494 	if (getauxval(AT_HWCAP2) & HWCAP2_SME2) {
495 		tests += cpus;
496 		have_sme2 = true;
497 	} else {
498 		have_sme2 = false;
499 	}
500 
501 	tests += cpus * 2;
502 
503 	ksft_print_header();
504 	ksft_set_plan(tests);
505 
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");
509 
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");
514 
515 	children = calloc(sizeof(*children), tests);
516 	if (!children)
517 		ksft_exit_fail_msg("Unable to allocate child data\n");
518 
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;
524 
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);
530 
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);
549 
550 	evs = calloc(tests, sizeof(*evs));
551 	if (!evs)
552 		ksft_exit_fail_msg("Failed to allocated %d epoll events\n",
553 				   tests);
554 
555 	for (i = 0; i < cpus; i++) {
556 		start_fpsimd(&children[num_children++], i, 0);
557 		start_kernel(&children[num_children++], i, 0);
558 
559 		for (j = 0; j < sve_vl_count; j++)
560 			start_sve(&children[num_children++], sve_vls[j], i);
561 
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);
565 		}
566 
567 		if (have_sme2)
568 			start_zt(&children[num_children++], i);
569 	}
570 
571 	/*
572 	 * All children started, close the startup pipe and let them
573 	 * run.
574 	 */
575 	close(startup_pipe[0]);
576 	close(startup_pipe[1]);
577 
578 	for (;;) {
579 		/* Did we get a signal asking us to exit? */
580 		if (terminate)
581 			break;
582 
583 		/*
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.
590 		 */
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);
597 		}
598 
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);
604 			}
605 			continue;
606 		}
607 
608 		/* Otherwise epoll_wait() timed out */
609 
610 		/*
611 		 * If the child processes have not produced output they
612 		 * aren't actually running the tests yet .
613 		 */
614 		if (!all_children_started) {
615 			seen_children = 0;
616 
617 			for (i = 0; i < num_children; i++)
618 				if (children[i].output_seen ||
619 				    children[i].exited)
620 					seen_children++;
621 
622 			if (seen_children != num_children) {
623 				ksft_print_msg("Waiting for %d children\n",
624 					       num_children - seen_children);
625 				continue;
626 			}
627 
628 			all_children_started = true;
629 			poll_interval = SIGNAL_INTERVAL_MS;
630 		}
631 
632 		if ((timeout % LOG_INTERVALS) == 0)
633 			ksft_print_msg("Sending signals, timeout remaining: %d\n",
634 				       timeout);
635 
636 		for (i = 0; i < num_children; i++)
637 			child_tickle(&children[i]);
638 
639 		/* Negative timeout means run indefinitely */
640 		if (timeout < 0)
641 			continue;
642 		if (--timeout == 0)
643 			break;
644 	}
645 
646 	ksft_print_msg("Finishing up...\n");
647 	terminate = true;
648 
649 	for (i = 0; i < tests; i++)
650 		child_stop(&children[i]);
651 
652 	drain_output(false);
653 
654 	for (i = 0; i < tests; i++)
655 		child_cleanup(&children[i]);
656 
657 	drain_output(true);
658 
659 	ksft_finished();
660 }
661