vec-syscfg.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2021 ARM Limited.
  4. * Original author: Mark Brown <[email protected]>
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <stddef.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <sys/auxv.h>
  15. #include <sys/prctl.h>
  16. #include <sys/types.h>
  17. #include <sys/wait.h>
  18. #include <asm/sigcontext.h>
  19. #include <asm/hwcap.h>
  20. #include "../../kselftest.h"
  21. #include "rdvl.h"
  22. #define ARCH_MIN_VL SVE_VL_MIN
  23. struct vec_data {
  24. const char *name;
  25. unsigned long hwcap_type;
  26. unsigned long hwcap;
  27. const char *rdvl_binary;
  28. int (*rdvl)(void);
  29. int prctl_get;
  30. int prctl_set;
  31. const char *default_vl_file;
  32. int default_vl;
  33. int min_vl;
  34. int max_vl;
  35. };
  36. static struct vec_data vec_data[] = {
  37. {
  38. .name = "SVE",
  39. .hwcap_type = AT_HWCAP,
  40. .hwcap = HWCAP_SVE,
  41. .rdvl = rdvl_sve,
  42. .rdvl_binary = "./rdvl-sve",
  43. .prctl_get = PR_SVE_GET_VL,
  44. .prctl_set = PR_SVE_SET_VL,
  45. .default_vl_file = "/proc/sys/abi/sve_default_vector_length",
  46. },
  47. {
  48. .name = "SME",
  49. .hwcap_type = AT_HWCAP2,
  50. .hwcap = HWCAP2_SME,
  51. .rdvl = rdvl_sme,
  52. .rdvl_binary = "./rdvl-sme",
  53. .prctl_get = PR_SME_GET_VL,
  54. .prctl_set = PR_SME_SET_VL,
  55. .default_vl_file = "/proc/sys/abi/sme_default_vector_length",
  56. },
  57. };
  58. static int stdio_read_integer(FILE *f, const char *what, int *val)
  59. {
  60. int n = 0;
  61. int ret;
  62. ret = fscanf(f, "%d%*1[\n]%n", val, &n);
  63. if (ret < 1 || n < 1) {
  64. ksft_print_msg("failed to parse integer from %s\n", what);
  65. return -1;
  66. }
  67. return 0;
  68. }
  69. /* Start a new process and return the vector length it sees */
  70. static int get_child_rdvl(struct vec_data *data)
  71. {
  72. FILE *out;
  73. int pipefd[2];
  74. pid_t pid, child;
  75. int read_vl, ret;
  76. ret = pipe(pipefd);
  77. if (ret == -1) {
  78. ksft_print_msg("pipe() failed: %d (%s)\n",
  79. errno, strerror(errno));
  80. return -1;
  81. }
  82. fflush(stdout);
  83. child = fork();
  84. if (child == -1) {
  85. ksft_print_msg("fork() failed: %d (%s)\n",
  86. errno, strerror(errno));
  87. close(pipefd[0]);
  88. close(pipefd[1]);
  89. return -1;
  90. }
  91. /* Child: put vector length on the pipe */
  92. if (child == 0) {
  93. /*
  94. * Replace stdout with the pipe, errors to stderr from
  95. * here as kselftest prints to stdout.
  96. */
  97. ret = dup2(pipefd[1], 1);
  98. if (ret == -1) {
  99. fprintf(stderr, "dup2() %d\n", errno);
  100. exit(EXIT_FAILURE);
  101. }
  102. /* exec() a new binary which puts the VL on stdout */
  103. ret = execl(data->rdvl_binary, data->rdvl_binary, NULL);
  104. fprintf(stderr, "execl(%s) failed: %d (%s)\n",
  105. data->rdvl_binary, errno, strerror(errno));
  106. exit(EXIT_FAILURE);
  107. }
  108. close(pipefd[1]);
  109. /* Parent; wait for the exit status from the child & verify it */
  110. do {
  111. pid = wait(&ret);
  112. if (pid == -1) {
  113. ksft_print_msg("wait() failed: %d (%s)\n",
  114. errno, strerror(errno));
  115. close(pipefd[0]);
  116. return -1;
  117. }
  118. } while (pid != child);
  119. assert(pid == child);
  120. if (!WIFEXITED(ret)) {
  121. ksft_print_msg("child exited abnormally\n");
  122. close(pipefd[0]);
  123. return -1;
  124. }
  125. if (WEXITSTATUS(ret) != 0) {
  126. ksft_print_msg("child returned error %d\n",
  127. WEXITSTATUS(ret));
  128. close(pipefd[0]);
  129. return -1;
  130. }
  131. out = fdopen(pipefd[0], "r");
  132. if (!out) {
  133. ksft_print_msg("failed to open child stdout\n");
  134. close(pipefd[0]);
  135. return -1;
  136. }
  137. ret = stdio_read_integer(out, "child", &read_vl);
  138. fclose(out);
  139. if (ret != 0)
  140. return ret;
  141. return read_vl;
  142. }
  143. static int file_read_integer(const char *name, int *val)
  144. {
  145. FILE *f;
  146. int ret;
  147. f = fopen(name, "r");
  148. if (!f) {
  149. ksft_test_result_fail("Unable to open %s: %d (%s)\n",
  150. name, errno,
  151. strerror(errno));
  152. return -1;
  153. }
  154. ret = stdio_read_integer(f, name, val);
  155. fclose(f);
  156. return ret;
  157. }
  158. static int file_write_integer(const char *name, int val)
  159. {
  160. FILE *f;
  161. f = fopen(name, "w");
  162. if (!f) {
  163. ksft_test_result_fail("Unable to open %s: %d (%s)\n",
  164. name, errno,
  165. strerror(errno));
  166. return -1;
  167. }
  168. fprintf(f, "%d", val);
  169. fclose(f);
  170. return 0;
  171. }
  172. /*
  173. * Verify that we can read the default VL via proc, checking that it
  174. * is set in a freshly spawned child.
  175. */
  176. static void proc_read_default(struct vec_data *data)
  177. {
  178. int default_vl, child_vl, ret;
  179. ret = file_read_integer(data->default_vl_file, &default_vl);
  180. if (ret != 0)
  181. return;
  182. /* Is this the actual default seen by new processes? */
  183. child_vl = get_child_rdvl(data);
  184. if (child_vl != default_vl) {
  185. ksft_test_result_fail("%s is %d but child VL is %d\n",
  186. data->default_vl_file,
  187. default_vl, child_vl);
  188. return;
  189. }
  190. ksft_test_result_pass("%s default vector length %d\n", data->name,
  191. default_vl);
  192. data->default_vl = default_vl;
  193. }
  194. /* Verify that we can write a minimum value and have it take effect */
  195. static void proc_write_min(struct vec_data *data)
  196. {
  197. int ret, new_default, child_vl;
  198. if (geteuid() != 0) {
  199. ksft_test_result_skip("Need to be root to write to /proc\n");
  200. return;
  201. }
  202. ret = file_write_integer(data->default_vl_file, ARCH_MIN_VL);
  203. if (ret != 0)
  204. return;
  205. /* What was the new value? */
  206. ret = file_read_integer(data->default_vl_file, &new_default);
  207. if (ret != 0)
  208. return;
  209. /* Did it take effect in a new process? */
  210. child_vl = get_child_rdvl(data);
  211. if (child_vl != new_default) {
  212. ksft_test_result_fail("%s is %d but child VL is %d\n",
  213. data->default_vl_file,
  214. new_default, child_vl);
  215. return;
  216. }
  217. ksft_test_result_pass("%s minimum vector length %d\n", data->name,
  218. new_default);
  219. data->min_vl = new_default;
  220. file_write_integer(data->default_vl_file, data->default_vl);
  221. }
  222. /* Verify that we can write a maximum value and have it take effect */
  223. static void proc_write_max(struct vec_data *data)
  224. {
  225. int ret, new_default, child_vl;
  226. if (geteuid() != 0) {
  227. ksft_test_result_skip("Need to be root to write to /proc\n");
  228. return;
  229. }
  230. /* -1 is accepted by the /proc interface as the maximum VL */
  231. ret = file_write_integer(data->default_vl_file, -1);
  232. if (ret != 0)
  233. return;
  234. /* What was the new value? */
  235. ret = file_read_integer(data->default_vl_file, &new_default);
  236. if (ret != 0)
  237. return;
  238. /* Did it take effect in a new process? */
  239. child_vl = get_child_rdvl(data);
  240. if (child_vl != new_default) {
  241. ksft_test_result_fail("%s is %d but child VL is %d\n",
  242. data->default_vl_file,
  243. new_default, child_vl);
  244. return;
  245. }
  246. ksft_test_result_pass("%s maximum vector length %d\n", data->name,
  247. new_default);
  248. data->max_vl = new_default;
  249. file_write_integer(data->default_vl_file, data->default_vl);
  250. }
  251. /* Can we read back a VL from prctl? */
  252. static void prctl_get(struct vec_data *data)
  253. {
  254. int ret;
  255. ret = prctl(data->prctl_get);
  256. if (ret == -1) {
  257. ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
  258. data->name, errno, strerror(errno));
  259. return;
  260. }
  261. /* Mask out any flags */
  262. ret &= PR_SVE_VL_LEN_MASK;
  263. /* Is that what we can read back directly? */
  264. if (ret == data->rdvl())
  265. ksft_test_result_pass("%s current VL is %d\n",
  266. data->name, ret);
  267. else
  268. ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
  269. data->name, ret, data->rdvl());
  270. }
  271. /* Does the prctl let us set the VL we already have? */
  272. static void prctl_set_same(struct vec_data *data)
  273. {
  274. int cur_vl = data->rdvl();
  275. int ret;
  276. ret = prctl(data->prctl_set, cur_vl);
  277. if (ret < 0) {
  278. ksft_test_result_fail("%s prctl set failed: %d (%s)\n",
  279. data->name, errno, strerror(errno));
  280. return;
  281. }
  282. ksft_test_result(cur_vl == data->rdvl(),
  283. "%s set VL %d and have VL %d\n",
  284. data->name, cur_vl, data->rdvl());
  285. }
  286. /* Can we set a new VL for this process? */
  287. static void prctl_set(struct vec_data *data)
  288. {
  289. int ret;
  290. if (data->min_vl == data->max_vl) {
  291. ksft_test_result_skip("%s only one VL supported\n",
  292. data->name);
  293. return;
  294. }
  295. /* Try to set the minimum VL */
  296. ret = prctl(data->prctl_set, data->min_vl);
  297. if (ret < 0) {
  298. ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
  299. data->name, data->min_vl,
  300. errno, strerror(errno));
  301. return;
  302. }
  303. if ((ret & PR_SVE_VL_LEN_MASK) != data->min_vl) {
  304. ksft_test_result_fail("%s prctl set %d but return value is %d\n",
  305. data->name, data->min_vl, data->rdvl());
  306. return;
  307. }
  308. if (data->rdvl() != data->min_vl) {
  309. ksft_test_result_fail("%s set %d but RDVL is %d\n",
  310. data->name, data->min_vl, data->rdvl());
  311. return;
  312. }
  313. /* Try to set the maximum VL */
  314. ret = prctl(data->prctl_set, data->max_vl);
  315. if (ret < 0) {
  316. ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
  317. data->name, data->max_vl,
  318. errno, strerror(errno));
  319. return;
  320. }
  321. if ((ret & PR_SVE_VL_LEN_MASK) != data->max_vl) {
  322. ksft_test_result_fail("%s prctl() set %d but return value is %d\n",
  323. data->name, data->max_vl, data->rdvl());
  324. return;
  325. }
  326. /* The _INHERIT flag should not be present when we read the VL */
  327. ret = prctl(data->prctl_get);
  328. if (ret == -1) {
  329. ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
  330. data->name, errno, strerror(errno));
  331. return;
  332. }
  333. if (ret & PR_SVE_VL_INHERIT) {
  334. ksft_test_result_fail("%s prctl() reports _INHERIT\n",
  335. data->name);
  336. return;
  337. }
  338. ksft_test_result_pass("%s prctl() set min/max\n", data->name);
  339. }
  340. /* If we didn't request it a new VL shouldn't affect the child */
  341. static void prctl_set_no_child(struct vec_data *data)
  342. {
  343. int ret, child_vl;
  344. if (data->min_vl == data->max_vl) {
  345. ksft_test_result_skip("%s only one VL supported\n",
  346. data->name);
  347. return;
  348. }
  349. ret = prctl(data->prctl_set, data->min_vl);
  350. if (ret < 0) {
  351. ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
  352. data->name, data->min_vl,
  353. errno, strerror(errno));
  354. return;
  355. }
  356. /* Ensure the default VL is different */
  357. ret = file_write_integer(data->default_vl_file, data->max_vl);
  358. if (ret != 0)
  359. return;
  360. /* Check that the child has the default we just set */
  361. child_vl = get_child_rdvl(data);
  362. if (child_vl != data->max_vl) {
  363. ksft_test_result_fail("%s is %d but child VL is %d\n",
  364. data->default_vl_file,
  365. data->max_vl, child_vl);
  366. return;
  367. }
  368. ksft_test_result_pass("%s vector length used default\n", data->name);
  369. file_write_integer(data->default_vl_file, data->default_vl);
  370. }
  371. /* If we didn't request it a new VL shouldn't affect the child */
  372. static void prctl_set_for_child(struct vec_data *data)
  373. {
  374. int ret, child_vl;
  375. if (data->min_vl == data->max_vl) {
  376. ksft_test_result_skip("%s only one VL supported\n",
  377. data->name);
  378. return;
  379. }
  380. ret = prctl(data->prctl_set, data->min_vl | PR_SVE_VL_INHERIT);
  381. if (ret < 0) {
  382. ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
  383. data->name, data->min_vl,
  384. errno, strerror(errno));
  385. return;
  386. }
  387. /* The _INHERIT flag should be present when we read the VL */
  388. ret = prctl(data->prctl_get);
  389. if (ret == -1) {
  390. ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
  391. data->name, errno, strerror(errno));
  392. return;
  393. }
  394. if (!(ret & PR_SVE_VL_INHERIT)) {
  395. ksft_test_result_fail("%s prctl() does not report _INHERIT\n",
  396. data->name);
  397. return;
  398. }
  399. /* Ensure the default VL is different */
  400. ret = file_write_integer(data->default_vl_file, data->max_vl);
  401. if (ret != 0)
  402. return;
  403. /* Check that the child inherited our VL */
  404. child_vl = get_child_rdvl(data);
  405. if (child_vl != data->min_vl) {
  406. ksft_test_result_fail("%s is %d but child VL is %d\n",
  407. data->default_vl_file,
  408. data->min_vl, child_vl);
  409. return;
  410. }
  411. ksft_test_result_pass("%s vector length was inherited\n", data->name);
  412. file_write_integer(data->default_vl_file, data->default_vl);
  413. }
  414. /* _ONEXEC takes effect only in the child process */
  415. static void prctl_set_onexec(struct vec_data *data)
  416. {
  417. int ret, child_vl;
  418. if (data->min_vl == data->max_vl) {
  419. ksft_test_result_skip("%s only one VL supported\n",
  420. data->name);
  421. return;
  422. }
  423. /* Set a known value for the default and our current VL */
  424. ret = file_write_integer(data->default_vl_file, data->max_vl);
  425. if (ret != 0)
  426. return;
  427. ret = prctl(data->prctl_set, data->max_vl);
  428. if (ret < 0) {
  429. ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
  430. data->name, data->min_vl,
  431. errno, strerror(errno));
  432. return;
  433. }
  434. /* Set a different value for the child to have on exec */
  435. ret = prctl(data->prctl_set, data->min_vl | PR_SVE_SET_VL_ONEXEC);
  436. if (ret < 0) {
  437. ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
  438. data->name, data->min_vl,
  439. errno, strerror(errno));
  440. return;
  441. }
  442. /* Our current VL should stay the same */
  443. if (data->rdvl() != data->max_vl) {
  444. ksft_test_result_fail("%s VL changed by _ONEXEC prctl()\n",
  445. data->name);
  446. return;
  447. }
  448. /* Check that the child inherited our VL */
  449. child_vl = get_child_rdvl(data);
  450. if (child_vl != data->min_vl) {
  451. ksft_test_result_fail("Set %d _ONEXEC but child VL is %d\n",
  452. data->min_vl, child_vl);
  453. return;
  454. }
  455. ksft_test_result_pass("%s vector length set on exec\n", data->name);
  456. file_write_integer(data->default_vl_file, data->default_vl);
  457. }
  458. /* For each VQ verify that setting via prctl() does the right thing */
  459. static void prctl_set_all_vqs(struct vec_data *data)
  460. {
  461. int ret, vq, vl, new_vl;
  462. int errors = 0;
  463. if (!data->min_vl || !data->max_vl) {
  464. ksft_test_result_skip("%s Failed to enumerate VLs, not testing VL setting\n",
  465. data->name);
  466. return;
  467. }
  468. for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
  469. vl = sve_vl_from_vq(vq);
  470. /* Attempt to set the VL */
  471. ret = prctl(data->prctl_set, vl);
  472. if (ret < 0) {
  473. errors++;
  474. ksft_print_msg("%s prctl set failed for %d: %d (%s)\n",
  475. data->name, vl,
  476. errno, strerror(errno));
  477. continue;
  478. }
  479. new_vl = ret & PR_SVE_VL_LEN_MASK;
  480. /* Check that we actually have the reported new VL */
  481. if (data->rdvl() != new_vl) {
  482. ksft_print_msg("Set %s VL %d but RDVL reports %d\n",
  483. data->name, new_vl, data->rdvl());
  484. errors++;
  485. }
  486. /* Was that the VL we asked for? */
  487. if (new_vl == vl)
  488. continue;
  489. /* Should round up to the minimum VL if below it */
  490. if (vl < data->min_vl) {
  491. if (new_vl != data->min_vl) {
  492. ksft_print_msg("%s VL %d returned %d not minimum %d\n",
  493. data->name, vl, new_vl,
  494. data->min_vl);
  495. errors++;
  496. }
  497. continue;
  498. }
  499. /* Should round down to maximum VL if above it */
  500. if (vl > data->max_vl) {
  501. if (new_vl != data->max_vl) {
  502. ksft_print_msg("%s VL %d returned %d not maximum %d\n",
  503. data->name, vl, new_vl,
  504. data->max_vl);
  505. errors++;
  506. }
  507. continue;
  508. }
  509. /* Otherwise we should've rounded down */
  510. if (!(new_vl < vl)) {
  511. ksft_print_msg("%s VL %d returned %d, did not round down\n",
  512. data->name, vl, new_vl);
  513. errors++;
  514. continue;
  515. }
  516. }
  517. ksft_test_result(errors == 0, "%s prctl() set all VLs, %d errors\n",
  518. data->name, errors);
  519. }
  520. typedef void (*test_type)(struct vec_data *);
  521. static const test_type tests[] = {
  522. /*
  523. * The default/min/max tests must be first and in this order
  524. * to provide data for other tests.
  525. */
  526. proc_read_default,
  527. proc_write_min,
  528. proc_write_max,
  529. prctl_get,
  530. prctl_set_same,
  531. prctl_set,
  532. prctl_set_no_child,
  533. prctl_set_for_child,
  534. prctl_set_onexec,
  535. prctl_set_all_vqs,
  536. };
  537. int main(void)
  538. {
  539. int i, j;
  540. ksft_print_header();
  541. ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data));
  542. for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
  543. struct vec_data *data = &vec_data[i];
  544. unsigned long supported;
  545. supported = getauxval(data->hwcap_type) & data->hwcap;
  546. for (j = 0; j < ARRAY_SIZE(tests); j++) {
  547. if (supported)
  548. tests[j](data);
  549. else
  550. ksft_test_result_skip("%s not supported\n",
  551. data->name);
  552. }
  553. }
  554. ksft_exit_pass();
  555. }