xref: /linux/tools/testing/selftests/arm64/fp/fp-stress.c (revision 92145d88ce0b216c1b99aaac92fec1f6a7d6ddde)
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 struct child_data {
32 	char *name, *output;
33 	pid_t pid;
34 	int stdout;
35 	bool output_seen;
36 	bool exited;
37 	int exit_status;
38 };
39 
40 static int epoll_fd;
41 static struct child_data *children;
42 static int num_children;
43 static bool terminate;
44 
45 static int startup_pipe[2];
46 
47 static int num_processors(void)
48 {
49 	long nproc = sysconf(_SC_NPROCESSORS_CONF);
50 	if (nproc < 0) {
51 		perror("Unable to read number of processors\n");
52 		exit(EXIT_FAILURE);
53 	}
54 
55 	return nproc;
56 }
57 
58 static void child_start(struct child_data *child, const char *program)
59 {
60 	int ret, pipefd[2], i;
61 	struct epoll_event ev;
62 
63 	ret = pipe(pipefd);
64 	if (ret != 0)
65 		ksft_exit_fail_msg("Failed to create stdout pipe: %s (%d)\n",
66 				   strerror(errno), errno);
67 
68 	child->pid = fork();
69 	if (child->pid == -1)
70 		ksft_exit_fail_msg("fork() failed: %s (%d)\n",
71 				   strerror(errno), errno);
72 
73 	if (!child->pid) {
74 		/*
75 		 * In child, replace stdout with the pipe, errors to
76 		 * stderr from here as kselftest prints to stdout.
77 		 */
78 		ret = dup2(pipefd[1], 1);
79 		if (ret == -1) {
80 			fprintf(stderr, "dup2() %d\n", errno);
81 			exit(EXIT_FAILURE);
82 		}
83 
84 		/*
85 		 * Duplicate the read side of the startup pipe to
86 		 * FD 3 so we can close everything else.
87 		 */
88 		ret = dup2(startup_pipe[0], 3);
89 		if (ret == -1) {
90 			fprintf(stderr, "dup2() %d\n", errno);
91 			exit(EXIT_FAILURE);
92 		}
93 
94 		/*
95 		 * Very dumb mechanism to clean open FDs other than
96 		 * stdio. We don't want O_CLOEXEC for the pipes...
97 		 */
98 		for (i = 4; i < 8192; i++)
99 			close(i);
100 
101 		/*
102 		 * Read from the startup pipe, there should be no data
103 		 * and we should block until it is closed.  We just
104 		 * carry on on error since this isn't super critical.
105 		 */
106 		ret = read(3, &i, sizeof(i));
107 		if (ret < 0)
108 			fprintf(stderr, "read(startp pipe) failed: %s (%d)\n",
109 				strerror(errno), errno);
110 		if (ret > 0)
111 			fprintf(stderr, "%d bytes of data on startup pipe\n",
112 				ret);
113 		close(3);
114 
115 		ret = execl(program, program, NULL);
116 		fprintf(stderr, "execl(%s) failed: %d (%s)\n",
117 			program, errno, strerror(errno));
118 
119 		exit(EXIT_FAILURE);
120 	} else {
121 		/*
122 		 * In parent, remember the child and close our copy of the
123 		 * write side of stdout.
124 		 */
125 		close(pipefd[1]);
126 		child->stdout = pipefd[0];
127 		child->output = NULL;
128 		child->exited = false;
129 		child->output_seen = false;
130 
131 		ev.events = EPOLLIN | EPOLLHUP;
132 		ev.data.ptr = child;
133 
134 		ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, child->stdout, &ev);
135 		if (ret < 0) {
136 			ksft_exit_fail_msg("%s EPOLL_CTL_ADD failed: %s (%d)\n",
137 					   child->name, strerror(errno), errno);
138 		}
139 	}
140 }
141 
142 static bool child_output_read(struct child_data *child)
143 {
144 	char read_data[1024];
145 	char work[1024];
146 	int ret, len, cur_work, cur_read;
147 
148 	ret = read(child->stdout, read_data, sizeof(read_data));
149 	if (ret < 0) {
150 		if (errno == EINTR)
151 			return true;
152 
153 		ksft_print_msg("%s: read() failed: %s (%d)\n",
154 			       child->name, strerror(errno),
155 			       errno);
156 		return false;
157 	}
158 	len = ret;
159 
160 	child->output_seen = true;
161 
162 	/* Pick up any partial read */
163 	if (child->output) {
164 		strncpy(work, child->output, sizeof(work) - 1);
165 		cur_work = strnlen(work, sizeof(work));
166 		free(child->output);
167 		child->output = NULL;
168 	} else {
169 		cur_work = 0;
170 	}
171 
172 	cur_read = 0;
173 	while (cur_read < len) {
174 		work[cur_work] = read_data[cur_read++];
175 
176 		if (work[cur_work] == '\n') {
177 			work[cur_work] = '\0';
178 			ksft_print_msg("%s: %s\n", child->name, work);
179 			cur_work = 0;
180 		} else {
181 			cur_work++;
182 		}
183 	}
184 
185 	if (cur_work) {
186 		work[cur_work] = '\0';
187 		ret = asprintf(&child->output, "%s", work);
188 		if (ret == -1)
189 			ksft_exit_fail_msg("Out of memory\n");
190 	}
191 
192 	return false;
193 }
194 
195 static void child_output(struct child_data *child, uint32_t events,
196 			 bool flush)
197 {
198 	bool read_more;
199 
200 	if (events & EPOLLIN) {
201 		do {
202 			read_more = child_output_read(child);
203 		} while (read_more);
204 	}
205 
206 	if (events & EPOLLHUP) {
207 		close(child->stdout);
208 		child->stdout = -1;
209 		flush = true;
210 	}
211 
212 	if (flush && child->output) {
213 		ksft_print_msg("%s: %s<EOF>\n", child->name, child->output);
214 		free(child->output);
215 		child->output = NULL;
216 	}
217 }
218 
219 static void child_tickle(struct child_data *child)
220 {
221 	if (child->output_seen && !child->exited)
222 		kill(child->pid, SIGUSR2);
223 }
224 
225 static void child_stop(struct child_data *child)
226 {
227 	if (!child->exited)
228 		kill(child->pid, SIGTERM);
229 }
230 
231 static void child_cleanup(struct child_data *child)
232 {
233 	pid_t ret;
234 	int status;
235 	bool fail = false;
236 
237 	if (!child->exited) {
238 		do {
239 			ret = waitpid(child->pid, &status, 0);
240 			if (ret == -1 && errno == EINTR)
241 				continue;
242 
243 			if (ret == -1) {
244 				ksft_print_msg("waitpid(%d) failed: %s (%d)\n",
245 					       child->pid, strerror(errno),
246 					       errno);
247 				fail = true;
248 				break;
249 			}
250 		} while (!WIFEXITED(status));
251 		child->exit_status = WEXITSTATUS(status);
252 	}
253 
254 	if (!child->output_seen) {
255 		ksft_print_msg("%s no output seen\n", child->name);
256 		fail = true;
257 	}
258 
259 	if (child->exit_status != 0) {
260 		ksft_print_msg("%s exited with error code %d\n",
261 			       child->name, child->exit_status);
262 		fail = true;
263 	}
264 
265 	ksft_test_result(!fail, "%s\n", child->name);
266 }
267 
268 static void handle_child_signal(int sig, siginfo_t *info, void *context)
269 {
270 	int i;
271 	bool found = false;
272 
273 	for (i = 0; i < num_children; i++) {
274 		if (children[i].pid == info->si_pid) {
275 			children[i].exited = true;
276 			children[i].exit_status = info->si_status;
277 			found = true;
278 			break;
279 		}
280 	}
281 
282 	if (!found)
283 		ksft_print_msg("SIGCHLD for unknown PID %d with status %d\n",
284 			       info->si_pid, info->si_status);
285 }
286 
287 static void handle_exit_signal(int sig, siginfo_t *info, void *context)
288 {
289 	int i;
290 
291 	/* If we're already exiting then don't signal again */
292 	if (terminate)
293 		return;
294 
295 	ksft_print_msg("Got signal, exiting...\n");
296 
297 	terminate = true;
298 
299 	/*
300 	 * This should be redundant, the main loop should clean up
301 	 * after us, but for safety stop everything we can here.
302 	 */
303 	for (i = 0; i < num_children; i++)
304 		child_stop(&children[i]);
305 }
306 
307 static void start_fpsimd(struct child_data *child, int cpu, int copy)
308 {
309 	int ret;
310 
311 	ret = asprintf(&child->name, "FPSIMD-%d-%d", cpu, copy);
312 	if (ret == -1)
313 		ksft_exit_fail_msg("asprintf() failed\n");
314 
315 	child_start(child, "./fpsimd-test");
316 
317 	ksft_print_msg("Started %s\n", child->name);
318 }
319 
320 static void start_sve(struct child_data *child, int vl, int cpu)
321 {
322 	int ret;
323 
324 	ret = prctl(PR_SVE_SET_VL, vl | PR_SVE_VL_INHERIT);
325 	if (ret < 0)
326 		ksft_exit_fail_msg("Failed to set SVE VL %d\n", vl);
327 
328 	ret = asprintf(&child->name, "SVE-VL-%d-%d", vl, cpu);
329 	if (ret == -1)
330 		ksft_exit_fail_msg("asprintf() failed\n");
331 
332 	child_start(child, "./sve-test");
333 
334 	ksft_print_msg("Started %s\n", child->name);
335 }
336 
337 static void start_ssve(struct child_data *child, int vl, int cpu)
338 {
339 	int ret;
340 
341 	ret = asprintf(&child->name, "SSVE-VL-%d-%d", vl, cpu);
342 	if (ret == -1)
343 		ksft_exit_fail_msg("asprintf() failed\n");
344 
345 	ret = prctl(PR_SME_SET_VL, vl | PR_SME_VL_INHERIT);
346 	if (ret < 0)
347 		ksft_exit_fail_msg("Failed to set SME VL %d\n", ret);
348 
349 	child_start(child, "./ssve-test");
350 
351 	ksft_print_msg("Started %s\n", child->name);
352 }
353 
354 static void start_za(struct child_data *child, int vl, int cpu)
355 {
356 	int ret;
357 
358 	ret = prctl(PR_SME_SET_VL, vl | PR_SVE_VL_INHERIT);
359 	if (ret < 0)
360 		ksft_exit_fail_msg("Failed to set SME VL %d\n", ret);
361 
362 	ret = asprintf(&child->name, "ZA-VL-%d-%d", vl, cpu);
363 	if (ret == -1)
364 		ksft_exit_fail_msg("asprintf() failed\n");
365 
366 	child_start(child, "./za-test");
367 
368 	ksft_print_msg("Started %s\n", child->name);
369 }
370 
371 static void probe_vls(int vls[], int *vl_count, int set_vl)
372 {
373 	unsigned int vq;
374 	int vl;
375 
376 	*vl_count = 0;
377 
378 	for (vq = SVE_VQ_MAX; vq > 0; --vq) {
379 		vl = prctl(set_vl, vq * 16);
380 		if (vl == -1)
381 			ksft_exit_fail_msg("SET_VL failed: %s (%d)\n",
382 					   strerror(errno), errno);
383 
384 		vl &= PR_SVE_VL_LEN_MASK;
385 
386 		vq = sve_vq_from_vl(vl);
387 
388 		vls[*vl_count] = vl;
389 		*vl_count += 1;
390 	}
391 }
392 
393 /* Handle any pending output without blocking */
394 static void drain_output(bool flush)
395 {
396 	struct epoll_event ev;
397 	int ret = 1;
398 
399 	while (ret > 0) {
400 		ret = epoll_wait(epoll_fd, &ev, 1, 0);
401 		if (ret < 0) {
402 			if (errno == EINTR)
403 				continue;
404 			ksft_print_msg("epoll_wait() failed: %s (%d)\n",
405 				       strerror(errno), errno);
406 		}
407 
408 		if (ret == 1)
409 			child_output(ev.data.ptr, ev.events, flush);
410 	}
411 }
412 
413 static const struct option options[] = {
414 	{ "timeout",	required_argument, NULL, 't' },
415 	{ }
416 };
417 
418 int main(int argc, char **argv)
419 {
420 	int ret;
421 	int timeout = 10;
422 	int cpus, tests, i, j, c;
423 	int sve_vl_count, sme_vl_count, fpsimd_per_cpu;
424 	bool all_children_started = false;
425 	int seen_children;
426 	int sve_vls[MAX_VLS], sme_vls[MAX_VLS];
427 	struct epoll_event ev;
428 	struct sigaction sa;
429 
430 	while ((c = getopt_long(argc, argv, "t:", options, NULL)) != -1) {
431 		switch (c) {
432 		case 't':
433 			ret = sscanf(optarg, "%d", &timeout);
434 			if (ret != 1)
435 				ksft_exit_fail_msg("Failed to parse timeout %s\n",
436 						   optarg);
437 			break;
438 		default:
439 			ksft_exit_fail_msg("Unknown argument\n");
440 		}
441 	}
442 
443 	cpus = num_processors();
444 	tests = 0;
445 
446 	if (getauxval(AT_HWCAP) & HWCAP_SVE) {
447 		probe_vls(sve_vls, &sve_vl_count, PR_SVE_SET_VL);
448 		tests += sve_vl_count * cpus;
449 	} else {
450 		sve_vl_count = 0;
451 	}
452 
453 	if (getauxval(AT_HWCAP2) & HWCAP2_SME) {
454 		probe_vls(sme_vls, &sme_vl_count, PR_SME_SET_VL);
455 		tests += sme_vl_count * cpus * 2;
456 	} else {
457 		sme_vl_count = 0;
458 	}
459 
460 	/* Force context switching if we only have FPSIMD */
461 	if (!sve_vl_count && !sme_vl_count)
462 		fpsimd_per_cpu = 2;
463 	else
464 		fpsimd_per_cpu = 1;
465 	tests += cpus * fpsimd_per_cpu;
466 
467 	ksft_print_header();
468 	ksft_set_plan(tests);
469 
470 	ksft_print_msg("%d CPUs, %d SVE VLs, %d SME VLs\n",
471 		       cpus, sve_vl_count, sme_vl_count);
472 
473 	if (timeout > 0)
474 		ksft_print_msg("Will run for %ds\n", timeout);
475 	else
476 		ksft_print_msg("Will run until terminated\n");
477 
478 	children = calloc(sizeof(*children), tests);
479 	if (!children)
480 		ksft_exit_fail_msg("Unable to allocate child data\n");
481 
482 	ret = epoll_create1(EPOLL_CLOEXEC);
483 	if (ret < 0)
484 		ksft_exit_fail_msg("epoll_create1() failed: %s (%d)\n",
485 				   strerror(errno), ret);
486 	epoll_fd = ret;
487 
488 	/* Create a pipe which children will block on before execing */
489 	ret = pipe(startup_pipe);
490 	if (ret != 0)
491 		ksft_exit_fail_msg("Failed to create startup pipe: %s (%d)\n",
492 				   strerror(errno), errno);
493 
494 	/* Get signal handers ready before we start any children */
495 	memset(&sa, 0, sizeof(sa));
496 	sa.sa_sigaction = handle_exit_signal;
497 	sa.sa_flags = SA_RESTART | SA_SIGINFO;
498 	sigemptyset(&sa.sa_mask);
499 	ret = sigaction(SIGINT, &sa, NULL);
500 	if (ret < 0)
501 		ksft_print_msg("Failed to install SIGINT handler: %s (%d)\n",
502 			       strerror(errno), errno);
503 	ret = sigaction(SIGTERM, &sa, NULL);
504 	if (ret < 0)
505 		ksft_print_msg("Failed to install SIGTERM handler: %s (%d)\n",
506 			       strerror(errno), errno);
507 	sa.sa_sigaction = handle_child_signal;
508 	ret = sigaction(SIGCHLD, &sa, NULL);
509 	if (ret < 0)
510 		ksft_print_msg("Failed to install SIGCHLD handler: %s (%d)\n",
511 			       strerror(errno), errno);
512 
513 	for (i = 0; i < cpus; i++) {
514 		for (j = 0; j < fpsimd_per_cpu; j++)
515 			start_fpsimd(&children[num_children++], i, j);
516 
517 		for (j = 0; j < sve_vl_count; j++)
518 			start_sve(&children[num_children++], sve_vls[j], i);
519 
520 		for (j = 0; j < sme_vl_count; j++) {
521 			start_ssve(&children[num_children++], sme_vls[j], i);
522 			start_za(&children[num_children++], sme_vls[j], i);
523 		}
524 	}
525 
526 	/*
527 	 * All children started, close the startup pipe and let them
528 	 * run.
529 	 */
530 	close(startup_pipe[0]);
531 	close(startup_pipe[1]);
532 
533 	for (;;) {
534 		/* Did we get a signal asking us to exit? */
535 		if (terminate)
536 			break;
537 
538 		/*
539 		 * Timeout is counted in seconds with no output, the
540 		 * tests print during startup then are silent when
541 		 * running so this should ensure they all ran enough
542 		 * to install the signal handler, this is especially
543 		 * useful in emulation where we will both be slow and
544 		 * likely to have a large set of VLs.
545 		 */
546 		ret = epoll_wait(epoll_fd, &ev, 1, 1000);
547 		if (ret < 0) {
548 			if (errno == EINTR)
549 				continue;
550 			ksft_exit_fail_msg("epoll_wait() failed: %s (%d)\n",
551 					   strerror(errno), errno);
552 		}
553 
554 		/* Output? */
555 		if (ret == 1) {
556 			child_output(ev.data.ptr, ev.events, false);
557 			continue;
558 		}
559 
560 		/* Otherwise epoll_wait() timed out */
561 
562 		/*
563 		 * If the child processes have not produced output they
564 		 * aren't actually running the tests yet .
565 		 */
566 		if (!all_children_started) {
567 			seen_children = 0;
568 
569 			for (i = 0; i < num_children; i++)
570 				if (children[i].output_seen ||
571 				    children[i].exited)
572 					seen_children++;
573 
574 			if (seen_children != num_children) {
575 				ksft_print_msg("Waiting for %d children\n",
576 					       num_children - seen_children);
577 				continue;
578 			}
579 
580 			all_children_started = true;
581 		}
582 
583 		ksft_print_msg("Sending signals, timeout remaining: %d\n",
584 			       timeout);
585 
586 		for (i = 0; i < num_children; i++)
587 			child_tickle(&children[i]);
588 
589 		/* Negative timeout means run indefinitely */
590 		if (timeout < 0)
591 			continue;
592 		if (--timeout == 0)
593 			break;
594 	}
595 
596 	ksft_print_msg("Finishing up...\n");
597 	terminate = true;
598 
599 	for (i = 0; i < tests; i++)
600 		child_stop(&children[i]);
601 
602 	drain_output(false);
603 
604 	for (i = 0; i < tests; i++)
605 		child_cleanup(&children[i]);
606 
607 	drain_output(true);
608 
609 	ksft_print_cnts();
610 
611 	return 0;
612 }
613