fp-stress.c 14 KB

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