vec-syscfg.c 18 KB

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