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 void drain_output(bool flush); 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 * Very dumb mechanism to clean open FDs other than 86 * stdio. We don't want O_CLOEXEC for the pipes... 87 */ 88 for (i = 3; i < 8192; i++) 89 close(i); 90 91 ret = execl(program, program, NULL); 92 fprintf(stderr, "execl(%s) failed: %d (%s)\n", 93 program, errno, strerror(errno)); 94 95 exit(EXIT_FAILURE); 96 } else { 97 /* 98 * In parent, remember the child and close our copy of the 99 * write side of stdout. 100 */ 101 close(pipefd[1]); 102 child->stdout = pipefd[0]; 103 child->output = NULL; 104 child->exited = false; 105 child->output_seen = false; 106 107 ev.events = EPOLLIN | EPOLLHUP; 108 ev.data.ptr = child; 109 110 ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, child->stdout, &ev); 111 if (ret < 0) { 112 ksft_exit_fail_msg("%s EPOLL_CTL_ADD failed: %s (%d)\n", 113 child->name, strerror(errno), errno); 114 } 115 116 /* 117 * Keep output flowing during child startup so logs 118 * are more timely, can help debugging. 119 */ 120 drain_output(false); 121 } 122 } 123 124 static void child_output(struct child_data *child, uint32_t events, 125 bool flush) 126 { 127 char read_data[1024]; 128 char work[1024]; 129 int ret, len, cur_work, cur_read; 130 131 if (events & EPOLLIN) { 132 ret = read(child->stdout, read_data, sizeof(read_data)); 133 if (ret < 0) { 134 ksft_print_msg("%s: read() failed: %s (%d)\n", 135 child->name, strerror(errno), errno); 136 return; 137 } 138 len = ret; 139 140 child->output_seen = true; 141 142 /* Pick up any partial read */ 143 if (child->output) { 144 strncpy(work, child->output, sizeof(work) - 1); 145 cur_work = strnlen(work, sizeof(work)); 146 free(child->output); 147 child->output = NULL; 148 } else { 149 cur_work = 0; 150 } 151 152 cur_read = 0; 153 while (cur_read < len) { 154 work[cur_work] = read_data[cur_read++]; 155 156 if (work[cur_work] == '\n') { 157 work[cur_work] = '\0'; 158 ksft_print_msg("%s: %s\n", child->name, work); 159 cur_work = 0; 160 } else { 161 cur_work++; 162 } 163 } 164 165 if (cur_work) { 166 work[cur_work] = '\0'; 167 ret = asprintf(&child->output, "%s", work); 168 if (ret == -1) 169 ksft_exit_fail_msg("Out of memory\n"); 170 } 171 } 172 173 if (events & EPOLLHUP) { 174 close(child->stdout); 175 child->stdout = -1; 176 flush = true; 177 } 178 179 if (flush && child->output) { 180 ksft_print_msg("%s: %s<EOF>\n", child->name, child->output); 181 free(child->output); 182 child->output = NULL; 183 } 184 } 185 186 static void child_tickle(struct child_data *child) 187 { 188 if (child->output_seen && !child->exited) 189 kill(child->pid, SIGUSR2); 190 } 191 192 static void child_stop(struct child_data *child) 193 { 194 if (!child->exited) 195 kill(child->pid, SIGTERM); 196 } 197 198 static void child_cleanup(struct child_data *child) 199 { 200 pid_t ret; 201 int status; 202 bool fail = false; 203 204 if (!child->exited) { 205 do { 206 ret = waitpid(child->pid, &status, 0); 207 if (ret == -1 && errno == EINTR) 208 continue; 209 210 if (ret == -1) { 211 ksft_print_msg("waitpid(%d) failed: %s (%d)\n", 212 child->pid, strerror(errno), 213 errno); 214 fail = true; 215 break; 216 } 217 } while (!WIFEXITED(status)); 218 child->exit_status = WEXITSTATUS(status); 219 } 220 221 if (!child->output_seen) { 222 ksft_print_msg("%s no output seen\n", child->name); 223 fail = true; 224 } 225 226 if (child->exit_status != 0) { 227 ksft_print_msg("%s exited with error code %d\n", 228 child->name, child->exit_status); 229 fail = true; 230 } 231 232 ksft_test_result(!fail, "%s\n", child->name); 233 } 234 235 static void handle_child_signal(int sig, siginfo_t *info, void *context) 236 { 237 int i; 238 bool found = false; 239 240 for (i = 0; i < num_children; i++) { 241 if (children[i].pid == info->si_pid) { 242 children[i].exited = true; 243 children[i].exit_status = info->si_status; 244 found = true; 245 break; 246 } 247 } 248 249 if (!found) 250 ksft_print_msg("SIGCHLD for unknown PID %d with status %d\n", 251 info->si_pid, info->si_status); 252 } 253 254 static void handle_exit_signal(int sig, siginfo_t *info, void *context) 255 { 256 int i; 257 258 /* If we're already exiting then don't signal again */ 259 if (terminate) 260 return; 261 262 ksft_print_msg("Got signal, exiting...\n"); 263 264 terminate = true; 265 266 /* 267 * This should be redundant, the main loop should clean up 268 * after us, but for safety stop everything we can here. 269 */ 270 for (i = 0; i < num_children; i++) 271 child_stop(&children[i]); 272 } 273 274 static void start_fpsimd(struct child_data *child, int cpu, int copy) 275 { 276 int ret; 277 278 child_start(child, "./fpsimd-test"); 279 280 ret = asprintf(&child->name, "FPSIMD-%d-%d", cpu, copy); 281 if (ret == -1) 282 ksft_exit_fail_msg("asprintf() failed\n"); 283 284 ksft_print_msg("Started %s\n", child->name); 285 } 286 287 static void start_sve(struct child_data *child, int vl, int cpu) 288 { 289 int ret; 290 291 ret = prctl(PR_SVE_SET_VL, vl | PR_SVE_VL_INHERIT); 292 if (ret < 0) 293 ksft_exit_fail_msg("Failed to set SVE VL %d\n", vl); 294 295 child_start(child, "./sve-test"); 296 297 ret = asprintf(&child->name, "SVE-VL-%d-%d", vl, cpu); 298 if (ret == -1) 299 ksft_exit_fail_msg("asprintf() failed\n"); 300 301 ksft_print_msg("Started %s\n", child->name); 302 } 303 304 static void start_ssve(struct child_data *child, int vl, int cpu) 305 { 306 int ret; 307 308 ret = prctl(PR_SME_SET_VL, vl | PR_SME_VL_INHERIT); 309 if (ret < 0) 310 ksft_exit_fail_msg("Failed to set SME VL %d\n", ret); 311 312 child_start(child, "./ssve-test"); 313 314 ret = asprintf(&child->name, "SSVE-VL-%d-%d", vl, cpu); 315 if (ret == -1) 316 ksft_exit_fail_msg("asprintf() failed\n"); 317 318 ksft_print_msg("Started %s\n", child->name); 319 } 320 321 static void start_za(struct child_data *child, int vl, int cpu) 322 { 323 int ret; 324 325 ret = prctl(PR_SME_SET_VL, vl | PR_SVE_VL_INHERIT); 326 if (ret < 0) 327 ksft_exit_fail_msg("Failed to set SME VL %d\n", ret); 328 329 child_start(child, "./za-test"); 330 331 ret = asprintf(&child->name, "ZA-VL-%d-%d", vl, cpu); 332 if (ret == -1) 333 ksft_exit_fail_msg("asprintf() failed\n"); 334 335 ksft_print_msg("Started %s\n", child->name); 336 } 337 338 static void probe_vls(int vls[], int *vl_count, int set_vl) 339 { 340 unsigned int vq; 341 int vl; 342 343 *vl_count = 0; 344 345 for (vq = SVE_VQ_MAX; vq > 0; --vq) { 346 vl = prctl(set_vl, vq * 16); 347 if (vl == -1) 348 ksft_exit_fail_msg("SET_VL failed: %s (%d)\n", 349 strerror(errno), errno); 350 351 vl &= PR_SVE_VL_LEN_MASK; 352 353 vq = sve_vq_from_vl(vl); 354 355 vls[*vl_count] = vl; 356 *vl_count += 1; 357 } 358 } 359 360 /* Handle any pending output without blocking */ 361 static void drain_output(bool flush) 362 { 363 struct epoll_event ev; 364 int ret = 1; 365 366 while (ret > 0) { 367 ret = epoll_wait(epoll_fd, &ev, 1, 0); 368 if (ret < 0) { 369 if (errno == EINTR) 370 continue; 371 ksft_print_msg("epoll_wait() failed: %s (%d)\n", 372 strerror(errno), errno); 373 } 374 375 if (ret == 1) 376 child_output(ev.data.ptr, ev.events, flush); 377 } 378 } 379 380 static const struct option options[] = { 381 { "timeout", required_argument, NULL, 't' }, 382 { } 383 }; 384 385 int main(int argc, char **argv) 386 { 387 int ret; 388 int timeout = 10; 389 int cpus, tests, i, j, c; 390 int sve_vl_count, sme_vl_count, fpsimd_per_cpu; 391 int sve_vls[MAX_VLS], sme_vls[MAX_VLS]; 392 struct epoll_event ev; 393 struct sigaction sa; 394 395 while ((c = getopt_long(argc, argv, "t:", options, NULL)) != -1) { 396 switch (c) { 397 case 't': 398 ret = sscanf(optarg, "%d", &timeout); 399 if (ret != 1) 400 ksft_exit_fail_msg("Failed to parse timeout %s\n", 401 optarg); 402 break; 403 default: 404 ksft_exit_fail_msg("Unknown argument\n"); 405 } 406 } 407 408 cpus = num_processors(); 409 tests = 0; 410 411 if (getauxval(AT_HWCAP) & HWCAP_SVE) { 412 probe_vls(sve_vls, &sve_vl_count, PR_SVE_SET_VL); 413 tests += sve_vl_count * cpus; 414 } else { 415 sve_vl_count = 0; 416 } 417 418 if (getauxval(AT_HWCAP2) & HWCAP2_SME) { 419 probe_vls(sme_vls, &sme_vl_count, PR_SME_SET_VL); 420 tests += sme_vl_count * cpus * 2; 421 } else { 422 sme_vl_count = 0; 423 } 424 425 /* Force context switching if we only have FPSIMD */ 426 if (!sve_vl_count && !sme_vl_count) 427 fpsimd_per_cpu = 2; 428 else 429 fpsimd_per_cpu = 1; 430 tests += cpus * fpsimd_per_cpu; 431 432 ksft_print_header(); 433 ksft_set_plan(tests); 434 435 ksft_print_msg("%d CPUs, %d SVE VLs, %d SME VLs\n", 436 cpus, sve_vl_count, sme_vl_count); 437 438 if (timeout > 0) 439 ksft_print_msg("Will run for %ds\n", timeout); 440 else 441 ksft_print_msg("Will run until terminated\n"); 442 443 children = calloc(sizeof(*children), tests); 444 if (!children) 445 ksft_exit_fail_msg("Unable to allocate child data\n"); 446 447 ret = epoll_create1(EPOLL_CLOEXEC); 448 if (ret < 0) 449 ksft_exit_fail_msg("epoll_create1() failed: %s (%d)\n", 450 strerror(errno), ret); 451 epoll_fd = ret; 452 453 /* Get signal handers ready before we start any children */ 454 memset(&sa, 0, sizeof(sa)); 455 sa.sa_sigaction = handle_exit_signal; 456 sa.sa_flags = SA_RESTART | SA_SIGINFO; 457 sigemptyset(&sa.sa_mask); 458 ret = sigaction(SIGINT, &sa, NULL); 459 if (ret < 0) 460 ksft_print_msg("Failed to install SIGINT handler: %s (%d)\n", 461 strerror(errno), errno); 462 ret = sigaction(SIGTERM, &sa, NULL); 463 if (ret < 0) 464 ksft_print_msg("Failed to install SIGTERM handler: %s (%d)\n", 465 strerror(errno), errno); 466 sa.sa_sigaction = handle_child_signal; 467 ret = sigaction(SIGCHLD, &sa, NULL); 468 if (ret < 0) 469 ksft_print_msg("Failed to install SIGCHLD handler: %s (%d)\n", 470 strerror(errno), errno); 471 472 for (i = 0; i < cpus; i++) { 473 for (j = 0; j < fpsimd_per_cpu; j++) 474 start_fpsimd(&children[num_children++], i, j); 475 476 for (j = 0; j < sve_vl_count; j++) 477 start_sve(&children[num_children++], sve_vls[j], i); 478 479 for (j = 0; j < sme_vl_count; j++) { 480 start_ssve(&children[num_children++], sme_vls[j], i); 481 start_za(&children[num_children++], sme_vls[j], i); 482 } 483 } 484 485 for (;;) { 486 /* Did we get a signal asking us to exit? */ 487 if (terminate) 488 break; 489 490 /* 491 * Timeout is counted in seconds with no output, the 492 * tests print during startup then are silent when 493 * running so this should ensure they all ran enough 494 * to install the signal handler, this is especially 495 * useful in emulation where we will both be slow and 496 * likely to have a large set of VLs. 497 */ 498 ret = epoll_wait(epoll_fd, &ev, 1, 1000); 499 if (ret < 0) { 500 if (errno == EINTR) 501 continue; 502 ksft_exit_fail_msg("epoll_wait() failed: %s (%d)\n", 503 strerror(errno), errno); 504 } 505 506 /* Output? */ 507 if (ret == 1) { 508 child_output(ev.data.ptr, ev.events, false); 509 continue; 510 } 511 512 /* Otherwise epoll_wait() timed out */ 513 514 for (i = 0; i < num_children; i++) 515 child_tickle(&children[i]); 516 517 /* Negative timeout means run indefinitely */ 518 if (timeout < 0) 519 continue; 520 if (--timeout == 0) 521 break; 522 } 523 524 ksft_print_msg("Finishing up...\n"); 525 526 for (i = 0; i < tests; i++) 527 child_stop(&children[i]); 528 529 drain_output(false); 530 531 for (i = 0; i < tests; i++) 532 child_cleanup(&children[i]); 533 534 drain_output(true); 535 536 ksft_print_cnts(); 537 538 return 0; 539 } 540