xstate.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <elf.h>
  4. #include <pthread.h>
  5. #include <stdbool.h>
  6. #include <asm/prctl.h>
  7. #include <sys/ptrace.h>
  8. #include <sys/syscall.h>
  9. #include <sys/uio.h>
  10. #include <sys/wait.h>
  11. #include "helpers.h"
  12. #include "xstate.h"
  13. /*
  14. * The userspace xstate test suite is designed to be generic and operates
  15. * with randomized xstate data. However, some states require special handling:
  16. *
  17. * - PKRU and XTILECFG need specific adjustments, such as modifying
  18. * randomization behavior or using fixed values.
  19. * - But, PKRU already has a dedicated test suite in /tools/selftests/mm.
  20. * - Legacy states (FP and SSE) are excluded, as they are not considered
  21. * part of extended states (xstates) and their usage is already deeply
  22. * integrated into user-space libraries.
  23. */
  24. #define XFEATURE_MASK_TEST_SUPPORTED \
  25. ((1 << XFEATURE_YMM) | \
  26. (1 << XFEATURE_OPMASK) | \
  27. (1 << XFEATURE_ZMM_Hi256) | \
  28. (1 << XFEATURE_Hi16_ZMM) | \
  29. (1 << XFEATURE_XTILEDATA) | \
  30. (1 << XFEATURE_APX))
  31. static inline uint64_t xgetbv(uint32_t index)
  32. {
  33. uint32_t eax, edx;
  34. asm volatile("xgetbv" : "=a" (eax), "=d" (edx) : "c" (index));
  35. return eax + ((uint64_t)edx << 32);
  36. }
  37. static inline uint64_t get_xstatebv(struct xsave_buffer *xbuf)
  38. {
  39. return *(uint64_t *)(&xbuf->header);
  40. }
  41. static struct xstate_info xstate;
  42. struct futex_info {
  43. unsigned int iterations;
  44. struct futex_info *next;
  45. pthread_mutex_t mutex;
  46. pthread_t thread;
  47. bool valid;
  48. int nr;
  49. };
  50. static inline void load_rand_xstate(struct xstate_info *xstate, struct xsave_buffer *xbuf)
  51. {
  52. clear_xstate_header(xbuf);
  53. set_xstatebv(xbuf, xstate->mask);
  54. set_rand_data(xstate, xbuf);
  55. xrstor(xbuf, xstate->mask);
  56. }
  57. static inline void load_init_xstate(struct xstate_info *xstate, struct xsave_buffer *xbuf)
  58. {
  59. clear_xstate_header(xbuf);
  60. xrstor(xbuf, xstate->mask);
  61. }
  62. static inline void copy_xstate(struct xsave_buffer *xbuf_dst, struct xsave_buffer *xbuf_src)
  63. {
  64. memcpy(&xbuf_dst->bytes[xstate.xbuf_offset],
  65. &xbuf_src->bytes[xstate.xbuf_offset],
  66. xstate.size);
  67. }
  68. static inline bool validate_xstate_same(struct xsave_buffer *xbuf1, struct xsave_buffer *xbuf2)
  69. {
  70. int ret;
  71. ret = memcmp(&xbuf1->bytes[xstate.xbuf_offset],
  72. &xbuf2->bytes[xstate.xbuf_offset],
  73. xstate.size);
  74. return ret == 0;
  75. }
  76. static inline bool validate_xregs_same(struct xsave_buffer *xbuf1)
  77. {
  78. struct xsave_buffer *xbuf2;
  79. bool ret;
  80. xbuf2 = alloc_xbuf();
  81. if (!xbuf2)
  82. ksft_exit_fail_msg("failed to allocate XSAVE buffer\n");
  83. xsave(xbuf2, xstate.mask);
  84. ret = validate_xstate_same(xbuf1, xbuf2);
  85. free(xbuf2);
  86. return ret;
  87. }
  88. /* Context switching test */
  89. static void *check_xstate(void *info)
  90. {
  91. struct futex_info *finfo = (struct futex_info *)info;
  92. struct xsave_buffer *xbuf;
  93. int i;
  94. xbuf = alloc_xbuf();
  95. if (!xbuf)
  96. ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
  97. /*
  98. * Load random data into 'xbuf' and then restore it to the xstate
  99. * registers.
  100. */
  101. load_rand_xstate(&xstate, xbuf);
  102. finfo->valid = true;
  103. for (i = 0; i < finfo->iterations; i++) {
  104. pthread_mutex_lock(&finfo->mutex);
  105. /*
  106. * Ensure the register values have not diverged from the
  107. * record. Then reload a new random value. If it failed
  108. * ever before, skip it.
  109. */
  110. if (finfo->valid) {
  111. finfo->valid = validate_xregs_same(xbuf);
  112. load_rand_xstate(&xstate, xbuf);
  113. }
  114. /*
  115. * The last thread's last unlock will be for thread 0's
  116. * mutex. However, thread 0 will have already exited the
  117. * loop and the mutex will already be unlocked.
  118. *
  119. * Because this is not an ERRORCHECK mutex, that
  120. * inconsistency will be silently ignored.
  121. */
  122. pthread_mutex_unlock(&finfo->next->mutex);
  123. }
  124. free(xbuf);
  125. return finfo;
  126. }
  127. static void create_threads(uint32_t num_threads, uint32_t iterations, struct futex_info *finfo)
  128. {
  129. int i;
  130. for (i = 0; i < num_threads; i++) {
  131. int next_nr;
  132. finfo[i].nr = i;
  133. finfo[i].iterations = iterations;
  134. /*
  135. * Thread 'i' will wait on this mutex to be unlocked.
  136. * Lock it immediately after initialization:
  137. */
  138. pthread_mutex_init(&finfo[i].mutex, NULL);
  139. pthread_mutex_lock(&finfo[i].mutex);
  140. next_nr = (i + 1) % num_threads;
  141. finfo[i].next = &finfo[next_nr];
  142. if (pthread_create(&finfo[i].thread, NULL, check_xstate, &finfo[i]))
  143. ksft_exit_fail_msg("pthread_create() failed\n");
  144. }
  145. }
  146. static bool checkout_threads(uint32_t num_threads, struct futex_info *finfo)
  147. {
  148. void *thread_retval;
  149. bool valid = true;
  150. int err, i;
  151. for (i = 0; i < num_threads; i++) {
  152. err = pthread_join(finfo[i].thread, &thread_retval);
  153. if (err)
  154. ksft_exit_fail_msg("pthread_join() failed for thread %d err: %d\n", i, err);
  155. if (thread_retval != &finfo[i]) {
  156. ksft_exit_fail_msg("unexpected thread retval for thread %d: %p\n",
  157. i, thread_retval);
  158. }
  159. valid &= finfo[i].valid;
  160. }
  161. return valid;
  162. }
  163. static void affinitize_cpu0(void)
  164. {
  165. cpu_set_t cpuset;
  166. CPU_ZERO(&cpuset);
  167. CPU_SET(0, &cpuset);
  168. if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
  169. ksft_exit_fail_msg("sched_setaffinity to CPU 0 failed\n");
  170. }
  171. static void test_context_switch(uint32_t num_threads, uint32_t iterations)
  172. {
  173. struct futex_info *finfo;
  174. /* Affinitize to one CPU to force context switches */
  175. affinitize_cpu0();
  176. printf("[RUN]\t%s: check context switches, %d iterations, %d threads.\n",
  177. xstate.name, iterations, num_threads);
  178. finfo = malloc(sizeof(*finfo) * num_threads);
  179. if (!finfo)
  180. ksft_exit_fail_msg("unable allocate memory\n");
  181. create_threads(num_threads, iterations, finfo);
  182. /*
  183. * This thread wakes up thread 0
  184. * Thread 0 will wake up 1
  185. * Thread 1 will wake up 2
  186. * ...
  187. * The last thread will wake up 0
  188. *
  189. * This will repeat for the configured
  190. * number of iterations.
  191. */
  192. pthread_mutex_unlock(&finfo[0].mutex);
  193. /* Wait for all the threads to finish: */
  194. if (checkout_threads(num_threads, finfo))
  195. printf("[OK]\tNo incorrect case was found.\n");
  196. else
  197. printf("[FAIL]\tFailed with context switching test.\n");
  198. free(finfo);
  199. }
  200. /*
  201. * Ptrace test for the ABI format as described in arch/x86/include/asm/user.h
  202. */
  203. /*
  204. * Make sure the ptracee has the expanded kernel buffer on the first use.
  205. * Then, initialize the state before performing the state injection from
  206. * the ptracer. For non-dynamic states, this is benign.
  207. */
  208. static inline void ptracee_touch_xstate(void)
  209. {
  210. struct xsave_buffer *xbuf;
  211. xbuf = alloc_xbuf();
  212. load_rand_xstate(&xstate, xbuf);
  213. load_init_xstate(&xstate, xbuf);
  214. free(xbuf);
  215. }
  216. /*
  217. * Ptracer injects the randomized xstate data. It also reads before and
  218. * after that, which will execute the kernel's state copy functions.
  219. */
  220. static void ptracer_inject_xstate(pid_t target)
  221. {
  222. uint32_t xbuf_size = get_xbuf_size();
  223. struct xsave_buffer *xbuf1, *xbuf2;
  224. struct iovec iov;
  225. /*
  226. * Allocate buffers to keep data while ptracer can write the
  227. * other buffer
  228. */
  229. xbuf1 = alloc_xbuf();
  230. xbuf2 = alloc_xbuf();
  231. if (!xbuf1 || !xbuf2)
  232. ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
  233. iov.iov_base = xbuf1;
  234. iov.iov_len = xbuf_size;
  235. if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
  236. ksft_exit_fail_msg("PTRACE_GETREGSET failed\n");
  237. printf("[RUN]\t%s: inject xstate via ptrace().\n", xstate.name);
  238. load_rand_xstate(&xstate, xbuf1);
  239. copy_xstate(xbuf2, xbuf1);
  240. if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
  241. ksft_exit_fail_msg("PTRACE_SETREGSET failed\n");
  242. if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
  243. ksft_exit_fail_msg("PTRACE_GETREGSET failed\n");
  244. if (*(uint64_t *)get_fpx_sw_bytes(xbuf1) == xgetbv(0))
  245. printf("[OK]\t'xfeatures' in SW reserved area was correctly written\n");
  246. else
  247. printf("[FAIL]\t'xfeatures' in SW reserved area was not correctly written\n");
  248. if (validate_xstate_same(xbuf2, xbuf1))
  249. printf("[OK]\txstate was correctly updated.\n");
  250. else
  251. printf("[FAIL]\txstate was not correctly updated.\n");
  252. free(xbuf1);
  253. free(xbuf2);
  254. }
  255. static void test_ptrace(void)
  256. {
  257. pid_t child;
  258. int status;
  259. child = fork();
  260. if (child < 0) {
  261. ksft_exit_fail_msg("fork() failed\n");
  262. } else if (!child) {
  263. if (ptrace(PTRACE_TRACEME, 0, NULL, NULL))
  264. ksft_exit_fail_msg("PTRACE_TRACEME failed\n");
  265. ptracee_touch_xstate();
  266. raise(SIGTRAP);
  267. _exit(0);
  268. }
  269. do {
  270. wait(&status);
  271. } while (WSTOPSIG(status) != SIGTRAP);
  272. ptracer_inject_xstate(child);
  273. ptrace(PTRACE_DETACH, child, NULL, NULL);
  274. wait(&status);
  275. if (!WIFEXITED(status) || WEXITSTATUS(status))
  276. ksft_exit_fail_msg("ptracee exit error\n");
  277. }
  278. /*
  279. * Test signal delivery for the ABI compatibility.
  280. * See the ABI format: arch/x86/include/uapi/asm/sigcontext.h
  281. */
  282. /*
  283. * Avoid using printf() in signal handlers as it is not
  284. * async-signal-safe.
  285. */
  286. #define SIGNAL_BUF_LEN 1000
  287. static char signal_message_buffer[SIGNAL_BUF_LEN];
  288. static void sig_print(char *msg)
  289. {
  290. int left = SIGNAL_BUF_LEN - strlen(signal_message_buffer) - 1;
  291. strncat(signal_message_buffer, msg, left);
  292. }
  293. static struct xsave_buffer *stashed_xbuf;
  294. static void validate_sigfpstate(int sig, siginfo_t *si, void *ctx_void)
  295. {
  296. ucontext_t *ctx = (ucontext_t *)ctx_void;
  297. void *xbuf = ctx->uc_mcontext.fpregs;
  298. struct _fpx_sw_bytes *sw_bytes;
  299. uint32_t magic2;
  300. /* Reset the signal message buffer: */
  301. signal_message_buffer[0] = '\0';
  302. sw_bytes = get_fpx_sw_bytes(xbuf);
  303. if (sw_bytes->magic1 == FP_XSTATE_MAGIC1)
  304. sig_print("[OK]\t'magic1' is valid\n");
  305. else
  306. sig_print("[FAIL]\t'magic1' is not valid\n");
  307. if (get_fpx_sw_bytes_features(xbuf) & xstate.mask)
  308. sig_print("[OK]\t'xfeatures' in SW reserved area is valid\n");
  309. else
  310. sig_print("[FAIL]\t'xfeatures' in SW reserved area is not valid\n");
  311. if (get_xstatebv(xbuf) & xstate.mask)
  312. sig_print("[OK]\t'xfeatures' in XSAVE header is valid\n");
  313. else
  314. sig_print("[FAIL]\t'xfeatures' in XSAVE header is not valid\n");
  315. if (validate_xstate_same(stashed_xbuf, xbuf))
  316. sig_print("[OK]\txstate delivery was successful\n");
  317. else
  318. sig_print("[FAIL]\txstate delivery was not successful\n");
  319. magic2 = *(uint32_t *)(xbuf + sw_bytes->xstate_size);
  320. if (magic2 == FP_XSTATE_MAGIC2)
  321. sig_print("[OK]\t'magic2' is valid\n");
  322. else
  323. sig_print("[FAIL]\t'magic2' is not valid\n");
  324. set_rand_data(&xstate, xbuf);
  325. copy_xstate(stashed_xbuf, xbuf);
  326. }
  327. static void test_signal(void)
  328. {
  329. bool valid_xstate;
  330. /*
  331. * The signal handler will access this to verify xstate context
  332. * preservation.
  333. */
  334. stashed_xbuf = alloc_xbuf();
  335. if (!stashed_xbuf)
  336. ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
  337. printf("[RUN]\t%s: load xstate and raise SIGUSR1\n", xstate.name);
  338. sethandler(SIGUSR1, validate_sigfpstate, 0);
  339. load_rand_xstate(&xstate, stashed_xbuf);
  340. raise(SIGUSR1);
  341. /*
  342. * Immediately record the test result, deferring printf() to
  343. * prevent unintended state contamination by that.
  344. */
  345. valid_xstate = validate_xregs_same(stashed_xbuf);
  346. printf("%s", signal_message_buffer);
  347. printf("[RUN]\t%s: load new xstate from sighandler and check it after sigreturn\n",
  348. xstate.name);
  349. if (valid_xstate)
  350. printf("[OK]\txstate was restored correctly\n");
  351. else
  352. printf("[FAIL]\txstate restoration failed\n");
  353. clearhandler(SIGUSR1);
  354. free(stashed_xbuf);
  355. }
  356. void test_xstate(uint32_t feature_num)
  357. {
  358. const unsigned int ctxtsw_num_threads = 5, ctxtsw_iterations = 10;
  359. unsigned long features;
  360. long rc;
  361. if (!(XFEATURE_MASK_TEST_SUPPORTED & (1 << feature_num))) {
  362. ksft_print_msg("The xstate test does not fully support the component %u, yet.\n",
  363. feature_num);
  364. return;
  365. }
  366. rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_SUPP, &features);
  367. if (rc || !(features & (1 << feature_num))) {
  368. ksft_print_msg("The kernel does not support feature number: %u\n", feature_num);
  369. return;
  370. }
  371. xstate = get_xstate_info(feature_num);
  372. if (!xstate.size || !xstate.xbuf_offset) {
  373. ksft_exit_fail_msg("invalid state size/offset (%d/%d)\n",
  374. xstate.size, xstate.xbuf_offset);
  375. }
  376. test_context_switch(ctxtsw_num_threads, ctxtsw_iterations);
  377. test_ptrace();
  378. test_signal();
  379. }