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