fp-stress.c 14 KB

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