sve-ptrace.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2015-2021 ARM Limited.
  4. * Original author: Dave Martin <[email protected]>
  5. */
  6. #include <errno.h>
  7. #include <stdbool.h>
  8. #include <stddef.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <sys/auxv.h>
  14. #include <sys/prctl.h>
  15. #include <sys/ptrace.h>
  16. #include <sys/types.h>
  17. #include <sys/uio.h>
  18. #include <sys/wait.h>
  19. #include <asm/sigcontext.h>
  20. #include <asm/ptrace.h>
  21. #include "../../kselftest.h"
  22. /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */
  23. #ifndef NT_ARM_SVE
  24. #define NT_ARM_SVE 0x405
  25. #endif
  26. #ifndef NT_ARM_SSVE
  27. #define NT_ARM_SSVE 0x40b
  28. #endif
  29. struct vec_type {
  30. const char *name;
  31. unsigned long hwcap_type;
  32. unsigned long hwcap;
  33. int regset;
  34. int prctl_set;
  35. };
  36. static const struct vec_type vec_types[] = {
  37. {
  38. .name = "SVE",
  39. .hwcap_type = AT_HWCAP,
  40. .hwcap = HWCAP_SVE,
  41. .regset = NT_ARM_SVE,
  42. .prctl_set = PR_SVE_SET_VL,
  43. },
  44. {
  45. .name = "Streaming SVE",
  46. .hwcap_type = AT_HWCAP2,
  47. .hwcap = HWCAP2_SME,
  48. .regset = NT_ARM_SSVE,
  49. .prctl_set = PR_SME_SET_VL,
  50. },
  51. };
  52. #define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 4)
  53. #define FLAG_TESTS 2
  54. #define FPSIMD_TESTS 2
  55. #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types))
  56. static void fill_buf(char *buf, size_t size)
  57. {
  58. int i;
  59. for (i = 0; i < size; i++)
  60. buf[i] = random();
  61. }
  62. static int do_child(void)
  63. {
  64. if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
  65. ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno));
  66. if (raise(SIGSTOP))
  67. ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno));
  68. return EXIT_SUCCESS;
  69. }
  70. static int get_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
  71. {
  72. struct iovec iov;
  73. iov.iov_base = fpsimd;
  74. iov.iov_len = sizeof(*fpsimd);
  75. return ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov);
  76. }
  77. static int set_fpsimd(pid_t pid, struct user_fpsimd_state *fpsimd)
  78. {
  79. struct iovec iov;
  80. iov.iov_base = fpsimd;
  81. iov.iov_len = sizeof(*fpsimd);
  82. return ptrace(PTRACE_SETREGSET, pid, NT_PRFPREG, &iov);
  83. }
  84. static struct user_sve_header *get_sve(pid_t pid, const struct vec_type *type,
  85. void **buf, size_t *size)
  86. {
  87. struct user_sve_header *sve;
  88. void *p;
  89. size_t sz = sizeof *sve;
  90. struct iovec iov;
  91. while (1) {
  92. if (*size < sz) {
  93. p = realloc(*buf, sz);
  94. if (!p) {
  95. errno = ENOMEM;
  96. goto error;
  97. }
  98. *buf = p;
  99. *size = sz;
  100. }
  101. iov.iov_base = *buf;
  102. iov.iov_len = sz;
  103. if (ptrace(PTRACE_GETREGSET, pid, type->regset, &iov))
  104. goto error;
  105. sve = *buf;
  106. if (sve->size <= sz)
  107. break;
  108. sz = sve->size;
  109. }
  110. return sve;
  111. error:
  112. return NULL;
  113. }
  114. static int set_sve(pid_t pid, const struct vec_type *type,
  115. const struct user_sve_header *sve)
  116. {
  117. struct iovec iov;
  118. iov.iov_base = (void *)sve;
  119. iov.iov_len = sve->size;
  120. return ptrace(PTRACE_SETREGSET, pid, type->regset, &iov);
  121. }
  122. /* Validate setting and getting the inherit flag */
  123. static void ptrace_set_get_inherit(pid_t child, const struct vec_type *type)
  124. {
  125. struct user_sve_header sve;
  126. struct user_sve_header *new_sve = NULL;
  127. size_t new_sve_size = 0;
  128. int ret;
  129. /* First set the flag */
  130. memset(&sve, 0, sizeof(sve));
  131. sve.size = sizeof(sve);
  132. sve.vl = sve_vl_from_vq(SVE_VQ_MIN);
  133. sve.flags = SVE_PT_VL_INHERIT;
  134. ret = set_sve(child, type, &sve);
  135. if (ret != 0) {
  136. ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n",
  137. type->name);
  138. return;
  139. }
  140. /*
  141. * Read back the new register state and verify that we have
  142. * set the flags we expected.
  143. */
  144. if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
  145. ksft_test_result_fail("Failed to read %s SVE flags\n",
  146. type->name);
  147. return;
  148. }
  149. ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT,
  150. "%s SVE_PT_VL_INHERIT set\n", type->name);
  151. /* Now clear */
  152. sve.flags &= ~SVE_PT_VL_INHERIT;
  153. ret = set_sve(child, type, &sve);
  154. if (ret != 0) {
  155. ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n",
  156. type->name);
  157. return;
  158. }
  159. if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
  160. ksft_test_result_fail("Failed to read %s SVE flags\n",
  161. type->name);
  162. return;
  163. }
  164. ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT),
  165. "%s SVE_PT_VL_INHERIT cleared\n", type->name);
  166. free(new_sve);
  167. }
  168. /* Validate attempting to set the specfied VL via ptrace */
  169. static void ptrace_set_get_vl(pid_t child, const struct vec_type *type,
  170. unsigned int vl, bool *supported)
  171. {
  172. struct user_sve_header sve;
  173. struct user_sve_header *new_sve = NULL;
  174. size_t new_sve_size = 0;
  175. int ret, prctl_vl;
  176. *supported = false;
  177. /* Check if the VL is supported in this process */
  178. prctl_vl = prctl(type->prctl_set, vl);
  179. if (prctl_vl == -1)
  180. ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n",
  181. type->name, strerror(errno), errno);
  182. /* If the VL is not supported then a supported VL will be returned */
  183. *supported = (prctl_vl == vl);
  184. /* Set the VL by doing a set with no register payload */
  185. memset(&sve, 0, sizeof(sve));
  186. sve.size = sizeof(sve);
  187. sve.vl = vl;
  188. ret = set_sve(child, type, &sve);
  189. if (ret != 0) {
  190. ksft_test_result_fail("Failed to set %s VL %u\n",
  191. type->name, vl);
  192. return;
  193. }
  194. /*
  195. * Read back the new register state and verify that we have the
  196. * same VL that we got from prctl() on ourselves.
  197. */
  198. if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) {
  199. ksft_test_result_fail("Failed to read %s VL %u\n",
  200. type->name, vl);
  201. return;
  202. }
  203. ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n",
  204. type->name, vl);
  205. free(new_sve);
  206. }
  207. static void check_u32(unsigned int vl, const char *reg,
  208. uint32_t *in, uint32_t *out, int *errors)
  209. {
  210. if (*in != *out) {
  211. printf("# VL %d %s wrote %x read %x\n",
  212. vl, reg, *in, *out);
  213. (*errors)++;
  214. }
  215. }
  216. /* Access the FPSIMD registers via the SVE regset */
  217. static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type)
  218. {
  219. void *svebuf;
  220. struct user_sve_header *sve;
  221. struct user_fpsimd_state *fpsimd, new_fpsimd;
  222. unsigned int i, j;
  223. unsigned char *p;
  224. int ret;
  225. svebuf = malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
  226. if (!svebuf) {
  227. ksft_test_result_fail("Failed to allocate FPSIMD buffer\n");
  228. return;
  229. }
  230. memset(svebuf, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD));
  231. sve = svebuf;
  232. sve->flags = SVE_PT_REGS_FPSIMD;
  233. sve->size = SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD);
  234. sve->vl = 16; /* We don't care what the VL is */
  235. /* Try to set a known FPSIMD state via PT_REGS_SVE */
  236. fpsimd = (struct user_fpsimd_state *)((char *)sve +
  237. SVE_PT_FPSIMD_OFFSET);
  238. for (i = 0; i < 32; ++i) {
  239. p = (unsigned char *)&fpsimd->vregs[i];
  240. for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j)
  241. p[j] = j;
  242. }
  243. ret = set_sve(child, type, sve);
  244. ksft_test_result(ret == 0, "%s FPSIMD set via SVE: %d\n",
  245. type->name, ret);
  246. if (ret)
  247. goto out;
  248. /* Verify via the FPSIMD regset */
  249. if (get_fpsimd(child, &new_fpsimd)) {
  250. ksft_test_result_fail("get_fpsimd(): %s\n",
  251. strerror(errno));
  252. goto out;
  253. }
  254. if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0)
  255. ksft_test_result_pass("%s get_fpsimd() gave same state\n",
  256. type->name);
  257. else
  258. ksft_test_result_fail("%s get_fpsimd() gave different state\n",
  259. type->name);
  260. out:
  261. free(svebuf);
  262. }
  263. /* Validate attempting to set SVE data and read SVE data */
  264. static void ptrace_set_sve_get_sve_data(pid_t child,
  265. const struct vec_type *type,
  266. unsigned int vl)
  267. {
  268. void *write_buf;
  269. void *read_buf = NULL;
  270. struct user_sve_header *write_sve;
  271. struct user_sve_header *read_sve;
  272. size_t read_sve_size = 0;
  273. unsigned int vq = sve_vq_from_vl(vl);
  274. int ret, i;
  275. size_t data_size;
  276. int errors = 0;
  277. data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
  278. write_buf = malloc(data_size);
  279. if (!write_buf) {
  280. ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
  281. data_size, type->name, vl);
  282. return;
  283. }
  284. write_sve = write_buf;
  285. /* Set up some data and write it out */
  286. memset(write_sve, 0, data_size);
  287. write_sve->size = data_size;
  288. write_sve->vl = vl;
  289. write_sve->flags = SVE_PT_REGS_SVE;
  290. for (i = 0; i < __SVE_NUM_ZREGS; i++)
  291. fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
  292. SVE_PT_SVE_ZREG_SIZE(vq));
  293. for (i = 0; i < __SVE_NUM_PREGS; i++)
  294. fill_buf(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
  295. SVE_PT_SVE_PREG_SIZE(vq));
  296. fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
  297. fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
  298. /* TODO: Generate a valid FFR pattern */
  299. ret = set_sve(child, type, write_sve);
  300. if (ret != 0) {
  301. ksft_test_result_fail("Failed to set %s VL %u data\n",
  302. type->name, vl);
  303. goto out;
  304. }
  305. /* Read the data back */
  306. if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
  307. ksft_test_result_fail("Failed to read %s VL %u data\n",
  308. type->name, vl);
  309. goto out;
  310. }
  311. read_sve = read_buf;
  312. /* We might read more data if there's extensions we don't know */
  313. if (read_sve->size < write_sve->size) {
  314. ksft_test_result_fail("%s wrote %d bytes, only read %d\n",
  315. type->name, write_sve->size,
  316. read_sve->size);
  317. goto out_read;
  318. }
  319. for (i = 0; i < __SVE_NUM_ZREGS; i++) {
  320. if (memcmp(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
  321. read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
  322. SVE_PT_SVE_ZREG_SIZE(vq)) != 0) {
  323. printf("# Mismatch in %u Z%d\n", vl, i);
  324. errors++;
  325. }
  326. }
  327. for (i = 0; i < __SVE_NUM_PREGS; i++) {
  328. if (memcmp(write_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
  329. read_buf + SVE_PT_SVE_PREG_OFFSET(vq, i),
  330. SVE_PT_SVE_PREG_SIZE(vq)) != 0) {
  331. printf("# Mismatch in %u P%d\n", vl, i);
  332. errors++;
  333. }
  334. }
  335. check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
  336. read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
  337. check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
  338. read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
  339. ksft_test_result(errors == 0, "Set and get %s data for VL %u\n",
  340. type->name, vl);
  341. out_read:
  342. free(read_buf);
  343. out:
  344. free(write_buf);
  345. }
  346. /* Validate attempting to set SVE data and read it via the FPSIMD regset */
  347. static void ptrace_set_sve_get_fpsimd_data(pid_t child,
  348. const struct vec_type *type,
  349. unsigned int vl)
  350. {
  351. void *write_buf;
  352. struct user_sve_header *write_sve;
  353. unsigned int vq = sve_vq_from_vl(vl);
  354. struct user_fpsimd_state fpsimd_state;
  355. int ret, i;
  356. size_t data_size;
  357. int errors = 0;
  358. if (__BYTE_ORDER == __BIG_ENDIAN) {
  359. ksft_test_result_skip("Big endian not supported\n");
  360. return;
  361. }
  362. data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
  363. write_buf = malloc(data_size);
  364. if (!write_buf) {
  365. ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n",
  366. data_size, type->name, vl);
  367. return;
  368. }
  369. write_sve = write_buf;
  370. /* Set up some data and write it out */
  371. memset(write_sve, 0, data_size);
  372. write_sve->size = data_size;
  373. write_sve->vl = vl;
  374. write_sve->flags = SVE_PT_REGS_SVE;
  375. for (i = 0; i < __SVE_NUM_ZREGS; i++)
  376. fill_buf(write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
  377. SVE_PT_SVE_ZREG_SIZE(vq));
  378. fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE);
  379. fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE);
  380. ret = set_sve(child, type, write_sve);
  381. if (ret != 0) {
  382. ksft_test_result_fail("Failed to set %s VL %u data\n",
  383. type->name, vl);
  384. goto out;
  385. }
  386. /* Read the data back */
  387. if (get_fpsimd(child, &fpsimd_state)) {
  388. ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n",
  389. type->name, vl);
  390. goto out;
  391. }
  392. for (i = 0; i < __SVE_NUM_ZREGS; i++) {
  393. __uint128_t tmp = 0;
  394. /*
  395. * Z regs are stored endianness invariant, this won't
  396. * work for big endian
  397. */
  398. memcpy(&tmp, write_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
  399. sizeof(tmp));
  400. if (tmp != fpsimd_state.vregs[i]) {
  401. printf("# Mismatch in FPSIMD for %s VL %u Z%d\n",
  402. type->name, vl, i);
  403. errors++;
  404. }
  405. }
  406. check_u32(vl, "FPSR", write_buf + SVE_PT_SVE_FPSR_OFFSET(vq),
  407. &fpsimd_state.fpsr, &errors);
  408. check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq),
  409. &fpsimd_state.fpcr, &errors);
  410. ksft_test_result(errors == 0, "Set and get FPSIMD data for %s VL %u\n",
  411. type->name, vl);
  412. out:
  413. free(write_buf);
  414. }
  415. /* Validate attempting to set FPSIMD data and read it via the SVE regset */
  416. static void ptrace_set_fpsimd_get_sve_data(pid_t child,
  417. const struct vec_type *type,
  418. unsigned int vl)
  419. {
  420. void *read_buf = NULL;
  421. unsigned char *p;
  422. struct user_sve_header *read_sve;
  423. unsigned int vq = sve_vq_from_vl(vl);
  424. struct user_fpsimd_state write_fpsimd;
  425. int ret, i, j;
  426. size_t read_sve_size = 0;
  427. size_t expected_size;
  428. int errors = 0;
  429. if (__BYTE_ORDER == __BIG_ENDIAN) {
  430. ksft_test_result_skip("Big endian not supported\n");
  431. return;
  432. }
  433. for (i = 0; i < 32; ++i) {
  434. p = (unsigned char *)&write_fpsimd.vregs[i];
  435. for (j = 0; j < sizeof(write_fpsimd.vregs[i]); ++j)
  436. p[j] = j;
  437. }
  438. ret = set_fpsimd(child, &write_fpsimd);
  439. if (ret != 0) {
  440. ksft_test_result_fail("Failed to set FPSIMD state: %d\n)",
  441. ret);
  442. return;
  443. }
  444. if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) {
  445. ksft_test_result_fail("Failed to read %s VL %u data\n",
  446. type->name, vl);
  447. return;
  448. }
  449. read_sve = read_buf;
  450. if (read_sve->vl != vl) {
  451. ksft_test_result_fail("Child VL != expected VL %d\n",
  452. read_sve->vl, vl);
  453. goto out;
  454. }
  455. /* The kernel may return either SVE or FPSIMD format */
  456. switch (read_sve->flags & SVE_PT_REGS_MASK) {
  457. case SVE_PT_REGS_FPSIMD:
  458. expected_size = SVE_PT_FPSIMD_SIZE(vq, SVE_PT_REGS_FPSIMD);
  459. if (read_sve_size < expected_size) {
  460. ksft_test_result_fail("Read %d bytes, expected %d\n",
  461. read_sve_size, expected_size);
  462. goto out;
  463. }
  464. ret = memcmp(&write_fpsimd, read_buf + SVE_PT_FPSIMD_OFFSET,
  465. sizeof(write_fpsimd));
  466. if (ret != 0) {
  467. ksft_print_msg("Read FPSIMD data mismatch\n");
  468. errors++;
  469. }
  470. break;
  471. case SVE_PT_REGS_SVE:
  472. expected_size = SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE);
  473. if (read_sve_size < expected_size) {
  474. ksft_test_result_fail("Read %d bytes, expected %d\n",
  475. read_sve_size, expected_size);
  476. goto out;
  477. }
  478. for (i = 0; i < __SVE_NUM_ZREGS; i++) {
  479. __uint128_t tmp = 0;
  480. /*
  481. * Z regs are stored endianness invariant, this won't
  482. * work for big endian
  483. */
  484. memcpy(&tmp, read_buf + SVE_PT_SVE_ZREG_OFFSET(vq, i),
  485. sizeof(tmp));
  486. if (tmp != write_fpsimd.vregs[i]) {
  487. ksft_print_msg("Mismatch in FPSIMD for %s VL %u Z%d/V%d\n",
  488. type->name, vl, i, i);
  489. errors++;
  490. }
  491. }
  492. check_u32(vl, "FPSR", &write_fpsimd.fpsr,
  493. read_buf + SVE_PT_SVE_FPSR_OFFSET(vq), &errors);
  494. check_u32(vl, "FPCR", &write_fpsimd.fpcr,
  495. read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors);
  496. break;
  497. default:
  498. ksft_print_msg("Unexpected regs type %d\n",
  499. read_sve->flags & SVE_PT_REGS_MASK);
  500. errors++;
  501. break;
  502. }
  503. ksft_test_result(errors == 0, "Set FPSIMD, read via SVE for %s VL %u\n",
  504. type->name, vl);
  505. out:
  506. free(read_buf);
  507. }
  508. static int do_parent(pid_t child)
  509. {
  510. int ret = EXIT_FAILURE;
  511. pid_t pid;
  512. int status, i;
  513. siginfo_t si;
  514. unsigned int vq, vl;
  515. bool vl_supported;
  516. ksft_print_msg("Parent is %d, child is %d\n", getpid(), child);
  517. /* Attach to the child */
  518. while (1) {
  519. int sig;
  520. pid = wait(&status);
  521. if (pid == -1) {
  522. perror("wait");
  523. goto error;
  524. }
  525. /*
  526. * This should never happen but it's hard to flag in
  527. * the framework.
  528. */
  529. if (pid != child)
  530. continue;
  531. if (WIFEXITED(status) || WIFSIGNALED(status))
  532. ksft_exit_fail_msg("Child died unexpectedly\n");
  533. if (!WIFSTOPPED(status))
  534. goto error;
  535. sig = WSTOPSIG(status);
  536. if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &si)) {
  537. if (errno == ESRCH)
  538. goto disappeared;
  539. if (errno == EINVAL) {
  540. sig = 0; /* bust group-stop */
  541. goto cont;
  542. }
  543. ksft_test_result_fail("PTRACE_GETSIGINFO: %s\n",
  544. strerror(errno));
  545. goto error;
  546. }
  547. if (sig == SIGSTOP && si.si_code == SI_TKILL &&
  548. si.si_pid == pid)
  549. break;
  550. cont:
  551. if (ptrace(PTRACE_CONT, pid, NULL, sig)) {
  552. if (errno == ESRCH)
  553. goto disappeared;
  554. ksft_test_result_fail("PTRACE_CONT: %s\n",
  555. strerror(errno));
  556. goto error;
  557. }
  558. }
  559. for (i = 0; i < ARRAY_SIZE(vec_types); i++) {
  560. /* FPSIMD via SVE regset */
  561. if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
  562. ptrace_sve_fpsimd(child, &vec_types[i]);
  563. } else {
  564. ksft_test_result_skip("%s FPSIMD set via SVE\n",
  565. vec_types[i].name);
  566. ksft_test_result_skip("%s FPSIMD read\n",
  567. vec_types[i].name);
  568. }
  569. /* prctl() flags */
  570. if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) {
  571. ptrace_set_get_inherit(child, &vec_types[i]);
  572. } else {
  573. ksft_test_result_skip("%s SVE_PT_VL_INHERIT set\n",
  574. vec_types[i].name);
  575. ksft_test_result_skip("%s SVE_PT_VL_INHERIT cleared\n",
  576. vec_types[i].name);
  577. }
  578. /* Step through every possible VQ */
  579. for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
  580. vl = sve_vl_from_vq(vq);
  581. /* First, try to set this vector length */
  582. if (getauxval(vec_types[i].hwcap_type) &
  583. vec_types[i].hwcap) {
  584. ptrace_set_get_vl(child, &vec_types[i], vl,
  585. &vl_supported);
  586. } else {
  587. ksft_test_result_skip("%s get/set VL %d\n",
  588. vec_types[i].name, vl);
  589. vl_supported = false;
  590. }
  591. /* If the VL is supported validate data set/get */
  592. if (vl_supported) {
  593. ptrace_set_sve_get_sve_data(child, &vec_types[i], vl);
  594. ptrace_set_sve_get_fpsimd_data(child, &vec_types[i], vl);
  595. ptrace_set_fpsimd_get_sve_data(child, &vec_types[i], vl);
  596. } else {
  597. ksft_test_result_skip("%s set SVE get SVE for VL %d\n",
  598. vec_types[i].name, vl);
  599. ksft_test_result_skip("%s set SVE get FPSIMD for VL %d\n",
  600. vec_types[i].name, vl);
  601. ksft_test_result_skip("%s set FPSIMD get SVE for VL %d\n",
  602. vec_types[i].name, vl);
  603. }
  604. }
  605. }
  606. ret = EXIT_SUCCESS;
  607. error:
  608. kill(child, SIGKILL);
  609. disappeared:
  610. return ret;
  611. }
  612. int main(void)
  613. {
  614. int ret = EXIT_SUCCESS;
  615. pid_t child;
  616. srandom(getpid());
  617. ksft_print_header();
  618. ksft_set_plan(EXPECTED_TESTS);
  619. if (!(getauxval(AT_HWCAP) & HWCAP_SVE))
  620. ksft_exit_skip("SVE not available\n");
  621. child = fork();
  622. if (!child)
  623. return do_child();
  624. if (do_parent(child))
  625. ret = EXIT_FAILURE;
  626. ksft_print_cnts();
  627. return ret;
  628. }