1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 #include <err.h> 5 #include <errno.h> 6 #include <pthread.h> 7 #include <setjmp.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <stdbool.h> 11 #include <unistd.h> 12 #include <x86intrin.h> 13 14 #include <sys/auxv.h> 15 #include <sys/mman.h> 16 #include <sys/shm.h> 17 #include <sys/ptrace.h> 18 #include <sys/syscall.h> 19 #include <sys/wait.h> 20 #include <sys/uio.h> 21 22 #include "../kselftest.h" /* For __cpuid_count() */ 23 24 #ifndef __x86_64__ 25 # error This test is 64-bit only 26 #endif 27 28 #define XSAVE_HDR_OFFSET 512 29 #define XSAVE_HDR_SIZE 64 30 31 struct xsave_buffer { 32 union { 33 struct { 34 char legacy[XSAVE_HDR_OFFSET]; 35 char header[XSAVE_HDR_SIZE]; 36 char extended[0]; 37 }; 38 char bytes[0]; 39 }; 40 }; 41 42 static inline uint64_t xgetbv(uint32_t index) 43 { 44 uint32_t eax, edx; 45 46 asm volatile("xgetbv;" 47 : "=a" (eax), "=d" (edx) 48 : "c" (index)); 49 return eax + ((uint64_t)edx << 32); 50 } 51 52 static inline void xsave(struct xsave_buffer *xbuf, uint64_t rfbm) 53 { 54 uint32_t rfbm_lo = rfbm; 55 uint32_t rfbm_hi = rfbm >> 32; 56 57 asm volatile("xsave (%%rdi)" 58 : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi) 59 : "memory"); 60 } 61 62 static inline void xrstor(struct xsave_buffer *xbuf, uint64_t rfbm) 63 { 64 uint32_t rfbm_lo = rfbm; 65 uint32_t rfbm_hi = rfbm >> 32; 66 67 asm volatile("xrstor (%%rdi)" 68 : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi)); 69 } 70 71 /* err() exits and will not return */ 72 #define fatal_error(msg, ...) err(1, "[FAIL]\t" msg, ##__VA_ARGS__) 73 74 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 75 int flags) 76 { 77 struct sigaction sa; 78 79 memset(&sa, 0, sizeof(sa)); 80 sa.sa_sigaction = handler; 81 sa.sa_flags = SA_SIGINFO | flags; 82 sigemptyset(&sa.sa_mask); 83 if (sigaction(sig, &sa, 0)) 84 fatal_error("sigaction"); 85 } 86 87 static void clearhandler(int sig) 88 { 89 struct sigaction sa; 90 91 memset(&sa, 0, sizeof(sa)); 92 sa.sa_handler = SIG_DFL; 93 sigemptyset(&sa.sa_mask); 94 if (sigaction(sig, &sa, 0)) 95 fatal_error("sigaction"); 96 } 97 98 #define XFEATURE_XTILECFG 17 99 #define XFEATURE_XTILEDATA 18 100 #define XFEATURE_MASK_XTILECFG (1 << XFEATURE_XTILECFG) 101 #define XFEATURE_MASK_XTILEDATA (1 << XFEATURE_XTILEDATA) 102 #define XFEATURE_MASK_XTILE (XFEATURE_MASK_XTILECFG | XFEATURE_MASK_XTILEDATA) 103 104 #define CPUID_LEAF1_ECX_XSAVE_MASK (1 << 26) 105 #define CPUID_LEAF1_ECX_OSXSAVE_MASK (1 << 27) 106 static inline void check_cpuid_xsave(void) 107 { 108 uint32_t eax, ebx, ecx, edx; 109 110 /* 111 * CPUID.1:ECX.XSAVE[bit 26] enumerates general 112 * support for the XSAVE feature set, including 113 * XGETBV. 114 */ 115 __cpuid_count(1, 0, eax, ebx, ecx, edx); 116 if (!(ecx & CPUID_LEAF1_ECX_XSAVE_MASK)) 117 fatal_error("cpuid: no CPU xsave support"); 118 if (!(ecx & CPUID_LEAF1_ECX_OSXSAVE_MASK)) 119 fatal_error("cpuid: no OS xsave support"); 120 } 121 122 static uint32_t xbuf_size; 123 124 static struct { 125 uint32_t xbuf_offset; 126 uint32_t size; 127 } xtiledata; 128 129 #define CPUID_LEAF_XSTATE 0xd 130 #define CPUID_SUBLEAF_XSTATE_USER 0x0 131 #define TILE_CPUID 0x1d 132 #define TILE_PALETTE_ID 0x1 133 134 static void check_cpuid_xtiledata(void) 135 { 136 uint32_t eax, ebx, ecx, edx; 137 138 __cpuid_count(CPUID_LEAF_XSTATE, CPUID_SUBLEAF_XSTATE_USER, 139 eax, ebx, ecx, edx); 140 141 /* 142 * EBX enumerates the size (in bytes) required by the XSAVE 143 * instruction for an XSAVE area containing all the user state 144 * components corresponding to bits currently set in XCR0. 145 * 146 * Stash that off so it can be used to allocate buffers later. 147 */ 148 xbuf_size = ebx; 149 150 __cpuid_count(CPUID_LEAF_XSTATE, XFEATURE_XTILEDATA, 151 eax, ebx, ecx, edx); 152 /* 153 * eax: XTILEDATA state component size 154 * ebx: XTILEDATA state component offset in user buffer 155 */ 156 if (!eax || !ebx) 157 fatal_error("xstate cpuid: invalid tile data size/offset: %d/%d", 158 eax, ebx); 159 160 xtiledata.size = eax; 161 xtiledata.xbuf_offset = ebx; 162 } 163 164 /* The helpers for managing XSAVE buffer and tile states: */ 165 166 struct xsave_buffer *alloc_xbuf(void) 167 { 168 struct xsave_buffer *xbuf; 169 170 /* XSAVE buffer should be 64B-aligned. */ 171 xbuf = aligned_alloc(64, xbuf_size); 172 if (!xbuf) 173 fatal_error("aligned_alloc()"); 174 return xbuf; 175 } 176 177 static inline void clear_xstate_header(struct xsave_buffer *buffer) 178 { 179 memset(&buffer->header, 0, sizeof(buffer->header)); 180 } 181 182 static inline uint64_t get_xstatebv(struct xsave_buffer *buffer) 183 { 184 /* XSTATE_BV is at the beginning of the header: */ 185 return *(uint64_t *)&buffer->header; 186 } 187 188 static inline void set_xstatebv(struct xsave_buffer *buffer, uint64_t bv) 189 { 190 /* XSTATE_BV is at the beginning of the header: */ 191 *(uint64_t *)(&buffer->header) = bv; 192 } 193 194 static void set_rand_tiledata(struct xsave_buffer *xbuf) 195 { 196 int *ptr = (int *)&xbuf->bytes[xtiledata.xbuf_offset]; 197 int data; 198 int i; 199 200 /* 201 * Ensure that 'data' is never 0. This ensures that 202 * the registers are never in their initial configuration 203 * and thus never tracked as being in the init state. 204 */ 205 data = rand() | 1; 206 207 for (i = 0; i < xtiledata.size / sizeof(int); i++, ptr++) 208 *ptr = data; 209 } 210 211 struct xsave_buffer *stashed_xsave; 212 213 static void init_stashed_xsave(void) 214 { 215 stashed_xsave = alloc_xbuf(); 216 if (!stashed_xsave) 217 fatal_error("failed to allocate stashed_xsave\n"); 218 clear_xstate_header(stashed_xsave); 219 } 220 221 static void free_stashed_xsave(void) 222 { 223 free(stashed_xsave); 224 } 225 226 /* See 'struct _fpx_sw_bytes' at sigcontext.h */ 227 #define SW_BYTES_OFFSET 464 228 /* N.B. The struct's field name varies so read from the offset. */ 229 #define SW_BYTES_BV_OFFSET (SW_BYTES_OFFSET + 8) 230 231 static inline struct _fpx_sw_bytes *get_fpx_sw_bytes(void *buffer) 232 { 233 return (struct _fpx_sw_bytes *)(buffer + SW_BYTES_OFFSET); 234 } 235 236 static inline uint64_t get_fpx_sw_bytes_features(void *buffer) 237 { 238 return *(uint64_t *)(buffer + SW_BYTES_BV_OFFSET); 239 } 240 241 /* Work around printf() being unsafe in signals: */ 242 #define SIGNAL_BUF_LEN 1000 243 char signal_message_buffer[SIGNAL_BUF_LEN]; 244 void sig_print(char *msg) 245 { 246 int left = SIGNAL_BUF_LEN - strlen(signal_message_buffer) - 1; 247 248 strncat(signal_message_buffer, msg, left); 249 } 250 251 static volatile bool noperm_signaled; 252 static int noperm_errs; 253 /* 254 * Signal handler for when AMX is used but 255 * permission has not been obtained. 256 */ 257 static void handle_noperm(int sig, siginfo_t *si, void *ctx_void) 258 { 259 ucontext_t *ctx = (ucontext_t *)ctx_void; 260 void *xbuf = ctx->uc_mcontext.fpregs; 261 struct _fpx_sw_bytes *sw_bytes; 262 uint64_t features; 263 264 /* Reset the signal message buffer: */ 265 signal_message_buffer[0] = '\0'; 266 sig_print("\tAt SIGILL handler,\n"); 267 268 if (si->si_code != ILL_ILLOPC) { 269 noperm_errs++; 270 sig_print("[FAIL]\tInvalid signal code.\n"); 271 } else { 272 sig_print("[OK]\tValid signal code (ILL_ILLOPC).\n"); 273 } 274 275 sw_bytes = get_fpx_sw_bytes(xbuf); 276 /* 277 * Without permission, the signal XSAVE buffer should not 278 * have room for AMX register state (aka. xtiledata). 279 * Check that the size does not overlap with where xtiledata 280 * will reside. 281 * 282 * This also implies that no state components *PAST* 283 * XTILEDATA (features >=19) can be present in the buffer. 284 */ 285 if (sw_bytes->xstate_size <= xtiledata.xbuf_offset) { 286 sig_print("[OK]\tValid xstate size\n"); 287 } else { 288 noperm_errs++; 289 sig_print("[FAIL]\tInvalid xstate size\n"); 290 } 291 292 features = get_fpx_sw_bytes_features(xbuf); 293 /* 294 * Without permission, the XTILEDATA feature 295 * bit should not be set. 296 */ 297 if ((features & XFEATURE_MASK_XTILEDATA) == 0) { 298 sig_print("[OK]\tValid xstate mask\n"); 299 } else { 300 noperm_errs++; 301 sig_print("[FAIL]\tInvalid xstate mask\n"); 302 } 303 304 noperm_signaled = true; 305 ctx->uc_mcontext.gregs[REG_RIP] += 3; /* Skip the faulting XRSTOR */ 306 } 307 308 /* Return true if XRSTOR is successful; otherwise, false. */ 309 static inline bool xrstor_safe(struct xsave_buffer *xbuf, uint64_t mask) 310 { 311 noperm_signaled = false; 312 xrstor(xbuf, mask); 313 314 /* Print any messages produced by the signal code: */ 315 printf("%s", signal_message_buffer); 316 /* 317 * Reset the buffer to make sure any future printing 318 * only outputs new messages: 319 */ 320 signal_message_buffer[0] = '\0'; 321 322 if (noperm_errs) 323 fatal_error("saw %d errors in noperm signal handler\n", noperm_errs); 324 325 return !noperm_signaled; 326 } 327 328 /* 329 * Use XRSTOR to populate the XTILEDATA registers with 330 * random data. 331 * 332 * Return true if successful; otherwise, false. 333 */ 334 static inline bool load_rand_tiledata(struct xsave_buffer *xbuf) 335 { 336 clear_xstate_header(xbuf); 337 set_xstatebv(xbuf, XFEATURE_MASK_XTILEDATA); 338 set_rand_tiledata(xbuf); 339 return xrstor_safe(xbuf, XFEATURE_MASK_XTILEDATA); 340 } 341 342 /* Return XTILEDATA to its initial configuration. */ 343 static inline void init_xtiledata(void) 344 { 345 clear_xstate_header(stashed_xsave); 346 xrstor_safe(stashed_xsave, XFEATURE_MASK_XTILEDATA); 347 } 348 349 enum expected_result { FAIL_EXPECTED, SUCCESS_EXPECTED }; 350 351 /* arch_prctl() and sigaltstack() test */ 352 353 #define ARCH_GET_XCOMP_PERM 0x1022 354 #define ARCH_REQ_XCOMP_PERM 0x1023 355 356 static void req_xtiledata_perm(void) 357 { 358 syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, XFEATURE_XTILEDATA); 359 } 360 361 static void validate_req_xcomp_perm(enum expected_result exp) 362 { 363 unsigned long bitmask, expected_bitmask; 364 long rc; 365 366 rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, &bitmask); 367 if (rc) { 368 fatal_error("prctl(ARCH_GET_XCOMP_PERM) error: %ld", rc); 369 } else if (!(bitmask & XFEATURE_MASK_XTILECFG)) { 370 fatal_error("ARCH_GET_XCOMP_PERM returns XFEATURE_XTILECFG off."); 371 } 372 373 rc = syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, XFEATURE_XTILEDATA); 374 if (exp == FAIL_EXPECTED) { 375 if (rc) { 376 printf("[OK]\tARCH_REQ_XCOMP_PERM saw expected failure..\n"); 377 return; 378 } 379 380 fatal_error("ARCH_REQ_XCOMP_PERM saw unexpected success.\n"); 381 } else if (rc) { 382 fatal_error("ARCH_REQ_XCOMP_PERM saw unexpected failure.\n"); 383 } 384 385 expected_bitmask = bitmask | XFEATURE_MASK_XTILEDATA; 386 387 rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, &bitmask); 388 if (rc) { 389 fatal_error("prctl(ARCH_GET_XCOMP_PERM) error: %ld", rc); 390 } else if (bitmask != expected_bitmask) { 391 fatal_error("ARCH_REQ_XCOMP_PERM set a wrong bitmask: %lx, expected: %lx.\n", 392 bitmask, expected_bitmask); 393 } else { 394 printf("\tARCH_REQ_XCOMP_PERM is successful.\n"); 395 } 396 } 397 398 static void validate_xcomp_perm(enum expected_result exp) 399 { 400 bool load_success = load_rand_tiledata(stashed_xsave); 401 402 if (exp == FAIL_EXPECTED) { 403 if (load_success) { 404 noperm_errs++; 405 printf("[FAIL]\tLoad tiledata succeeded.\n"); 406 } else { 407 printf("[OK]\tLoad tiledata failed.\n"); 408 } 409 } else if (exp == SUCCESS_EXPECTED) { 410 if (load_success) { 411 printf("[OK]\tLoad tiledata succeeded.\n"); 412 } else { 413 noperm_errs++; 414 printf("[FAIL]\tLoad tiledata failed.\n"); 415 } 416 } 417 } 418 419 #ifndef AT_MINSIGSTKSZ 420 # define AT_MINSIGSTKSZ 51 421 #endif 422 423 static void *alloc_altstack(unsigned int size) 424 { 425 void *altstack; 426 427 altstack = mmap(NULL, size, PROT_READ | PROT_WRITE, 428 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 429 430 if (altstack == MAP_FAILED) 431 fatal_error("mmap() for altstack"); 432 433 return altstack; 434 } 435 436 static void setup_altstack(void *addr, unsigned long size, enum expected_result exp) 437 { 438 stack_t ss; 439 int rc; 440 441 memset(&ss, 0, sizeof(ss)); 442 ss.ss_size = size; 443 ss.ss_sp = addr; 444 445 rc = sigaltstack(&ss, NULL); 446 447 if (exp == FAIL_EXPECTED) { 448 if (rc) { 449 printf("[OK]\tsigaltstack() failed.\n"); 450 } else { 451 fatal_error("sigaltstack() succeeded unexpectedly.\n"); 452 } 453 } else if (rc) { 454 fatal_error("sigaltstack()"); 455 } 456 } 457 458 static void test_dynamic_sigaltstack(void) 459 { 460 unsigned int small_size, enough_size; 461 unsigned long minsigstksz; 462 void *altstack; 463 464 minsigstksz = getauxval(AT_MINSIGSTKSZ); 465 printf("\tAT_MINSIGSTKSZ = %lu\n", minsigstksz); 466 /* 467 * getauxval() itself can return 0 for failure or 468 * success. But, in this case, AT_MINSIGSTKSZ 469 * will always return a >=0 value if implemented. 470 * Just check for 0. 471 */ 472 if (minsigstksz == 0) { 473 printf("no support for AT_MINSIGSTKSZ, skipping sigaltstack tests\n"); 474 return; 475 } 476 477 enough_size = minsigstksz * 2; 478 479 altstack = alloc_altstack(enough_size); 480 printf("\tAllocate memory for altstack (%u bytes).\n", enough_size); 481 482 /* 483 * Try setup_altstack() with a size which can not fit 484 * XTILEDATA. ARCH_REQ_XCOMP_PERM should fail. 485 */ 486 small_size = minsigstksz - xtiledata.size; 487 printf("\tAfter sigaltstack() with small size (%u bytes).\n", small_size); 488 setup_altstack(altstack, small_size, SUCCESS_EXPECTED); 489 validate_req_xcomp_perm(FAIL_EXPECTED); 490 491 /* 492 * Try setup_altstack() with a size derived from 493 * AT_MINSIGSTKSZ. It should be more than large enough 494 * and thus ARCH_REQ_XCOMP_PERM should succeed. 495 */ 496 printf("\tAfter sigaltstack() with enough size (%u bytes).\n", enough_size); 497 setup_altstack(altstack, enough_size, SUCCESS_EXPECTED); 498 validate_req_xcomp_perm(SUCCESS_EXPECTED); 499 500 /* 501 * Try to coerce setup_altstack() to again accept a 502 * too-small altstack. This ensures that big-enough 503 * sigaltstacks can not shrink to a too-small value 504 * once XTILEDATA permission is established. 505 */ 506 printf("\tThen, sigaltstack() with small size (%u bytes).\n", small_size); 507 setup_altstack(altstack, small_size, FAIL_EXPECTED); 508 } 509 510 static void test_dynamic_state(void) 511 { 512 pid_t parent, child, grandchild; 513 514 parent = fork(); 515 if (parent < 0) { 516 /* fork() failed */ 517 fatal_error("fork"); 518 } else if (parent > 0) { 519 int status; 520 /* fork() succeeded. Now in the parent. */ 521 522 wait(&status); 523 if (!WIFEXITED(status) || WEXITSTATUS(status)) 524 fatal_error("arch_prctl test parent exit"); 525 return; 526 } 527 /* fork() succeeded. Now in the child . */ 528 529 printf("[RUN]\tCheck ARCH_REQ_XCOMP_PERM around process fork() and sigaltack() test.\n"); 530 531 printf("\tFork a child.\n"); 532 child = fork(); 533 if (child < 0) { 534 fatal_error("fork"); 535 } else if (child > 0) { 536 int status; 537 538 wait(&status); 539 if (!WIFEXITED(status) || WEXITSTATUS(status)) 540 fatal_error("arch_prctl test child exit"); 541 _exit(0); 542 } 543 544 /* 545 * The permission request should fail without an 546 * XTILEDATA-compatible signal stack 547 */ 548 printf("\tTest XCOMP_PERM at child.\n"); 549 validate_xcomp_perm(FAIL_EXPECTED); 550 551 /* 552 * Set up an XTILEDATA-compatible signal stack and 553 * also obtain permission to populate XTILEDATA. 554 */ 555 printf("\tTest dynamic sigaltstack at child:\n"); 556 test_dynamic_sigaltstack(); 557 558 /* Ensure that XTILEDATA can be populated. */ 559 printf("\tTest XCOMP_PERM again at child.\n"); 560 validate_xcomp_perm(SUCCESS_EXPECTED); 561 562 printf("\tFork a grandchild.\n"); 563 grandchild = fork(); 564 if (grandchild < 0) { 565 /* fork() failed */ 566 fatal_error("fork"); 567 } else if (!grandchild) { 568 /* fork() succeeded. Now in the (grand)child. */ 569 printf("\tTest XCOMP_PERM at grandchild.\n"); 570 571 /* 572 * Ensure that the grandchild inherited 573 * permission and a compatible sigaltstack: 574 */ 575 validate_xcomp_perm(SUCCESS_EXPECTED); 576 } else { 577 int status; 578 /* fork() succeeded. Now in the parent. */ 579 580 wait(&status); 581 if (!WIFEXITED(status) || WEXITSTATUS(status)) 582 fatal_error("fork test grandchild"); 583 } 584 585 _exit(0); 586 } 587 588 static inline int __compare_tiledata_state(struct xsave_buffer *xbuf1, struct xsave_buffer *xbuf2) 589 { 590 return memcmp(&xbuf1->bytes[xtiledata.xbuf_offset], 591 &xbuf2->bytes[xtiledata.xbuf_offset], 592 xtiledata.size); 593 } 594 595 /* 596 * Save current register state and compare it to @xbuf1.' 597 * 598 * Returns false if @xbuf1 matches the registers. 599 * Returns true if @xbuf1 differs from the registers. 600 */ 601 static inline bool __validate_tiledata_regs(struct xsave_buffer *xbuf1) 602 { 603 struct xsave_buffer *xbuf2; 604 int ret; 605 606 xbuf2 = alloc_xbuf(); 607 if (!xbuf2) 608 fatal_error("failed to allocate XSAVE buffer\n"); 609 610 xsave(xbuf2, XFEATURE_MASK_XTILEDATA); 611 ret = __compare_tiledata_state(xbuf1, xbuf2); 612 613 free(xbuf2); 614 615 if (ret == 0) 616 return false; 617 return true; 618 } 619 620 static inline void validate_tiledata_regs_same(struct xsave_buffer *xbuf) 621 { 622 int ret = __validate_tiledata_regs(xbuf); 623 624 if (ret != 0) 625 fatal_error("TILEDATA registers changed"); 626 } 627 628 static inline void validate_tiledata_regs_changed(struct xsave_buffer *xbuf) 629 { 630 int ret = __validate_tiledata_regs(xbuf); 631 632 if (ret == 0) 633 fatal_error("TILEDATA registers did not change"); 634 } 635 636 /* tiledata inheritance test */ 637 638 static void test_fork(void) 639 { 640 pid_t child, grandchild; 641 642 child = fork(); 643 if (child < 0) { 644 /* fork() failed */ 645 fatal_error("fork"); 646 } else if (child > 0) { 647 /* fork() succeeded. Now in the parent. */ 648 int status; 649 650 wait(&status); 651 if (!WIFEXITED(status) || WEXITSTATUS(status)) 652 fatal_error("fork test child"); 653 return; 654 } 655 /* fork() succeeded. Now in the child. */ 656 printf("[RUN]\tCheck tile data inheritance.\n\tBefore fork(), load tiledata\n"); 657 658 load_rand_tiledata(stashed_xsave); 659 660 grandchild = fork(); 661 if (grandchild < 0) { 662 /* fork() failed */ 663 fatal_error("fork"); 664 } else if (grandchild > 0) { 665 /* fork() succeeded. Still in the first child. */ 666 int status; 667 668 wait(&status); 669 if (!WIFEXITED(status) || WEXITSTATUS(status)) 670 fatal_error("fork test grand child"); 671 _exit(0); 672 } 673 /* fork() succeeded. Now in the (grand)child. */ 674 675 /* 676 * TILEDATA registers are not preserved across fork(). 677 * Ensure that their value has changed: 678 */ 679 validate_tiledata_regs_changed(stashed_xsave); 680 681 _exit(0); 682 } 683 684 /* Context switching test */ 685 686 static struct _ctxtswtest_cfg { 687 unsigned int iterations; 688 unsigned int num_threads; 689 } ctxtswtest_config; 690 691 struct futex_info { 692 pthread_t thread; 693 int nr; 694 pthread_mutex_t mutex; 695 struct futex_info *next; 696 }; 697 698 static void *check_tiledata(void *info) 699 { 700 struct futex_info *finfo = (struct futex_info *)info; 701 struct xsave_buffer *xbuf; 702 int i; 703 704 xbuf = alloc_xbuf(); 705 if (!xbuf) 706 fatal_error("unable to allocate XSAVE buffer"); 707 708 /* 709 * Load random data into 'xbuf' and then restore 710 * it to the tile registers themselves. 711 */ 712 load_rand_tiledata(xbuf); 713 for (i = 0; i < ctxtswtest_config.iterations; i++) { 714 pthread_mutex_lock(&finfo->mutex); 715 716 /* 717 * Ensure the register values have not 718 * diverged from those recorded in 'xbuf'. 719 */ 720 validate_tiledata_regs_same(xbuf); 721 722 /* Load new, random values into xbuf and registers */ 723 load_rand_tiledata(xbuf); 724 725 /* 726 * The last thread's last unlock will be for 727 * thread 0's mutex. However, thread 0 will 728 * have already exited the loop and the mutex 729 * will already be unlocked. 730 * 731 * Because this is not an ERRORCHECK mutex, 732 * that inconsistency will be silently ignored. 733 */ 734 pthread_mutex_unlock(&finfo->next->mutex); 735 } 736 737 free(xbuf); 738 /* 739 * Return this thread's finfo, which is 740 * a unique value for this thread. 741 */ 742 return finfo; 743 } 744 745 static int create_threads(int num, struct futex_info *finfo) 746 { 747 int i; 748 749 for (i = 0; i < num; i++) { 750 int next_nr; 751 752 finfo[i].nr = i; 753 /* 754 * Thread 'i' will wait on this mutex to 755 * be unlocked. Lock it immediately after 756 * initialization: 757 */ 758 pthread_mutex_init(&finfo[i].mutex, NULL); 759 pthread_mutex_lock(&finfo[i].mutex); 760 761 next_nr = (i + 1) % num; 762 finfo[i].next = &finfo[next_nr]; 763 764 if (pthread_create(&finfo[i].thread, NULL, check_tiledata, &finfo[i])) 765 fatal_error("pthread_create()"); 766 } 767 return 0; 768 } 769 770 static void affinitize_cpu0(void) 771 { 772 cpu_set_t cpuset; 773 774 CPU_ZERO(&cpuset); 775 CPU_SET(0, &cpuset); 776 777 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) 778 fatal_error("sched_setaffinity to CPU 0"); 779 } 780 781 static void test_context_switch(void) 782 { 783 struct futex_info *finfo; 784 int i; 785 786 /* Affinitize to one CPU to force context switches */ 787 affinitize_cpu0(); 788 789 req_xtiledata_perm(); 790 791 printf("[RUN]\tCheck tiledata context switches, %d iterations, %d threads.\n", 792 ctxtswtest_config.iterations, 793 ctxtswtest_config.num_threads); 794 795 796 finfo = malloc(sizeof(*finfo) * ctxtswtest_config.num_threads); 797 if (!finfo) 798 fatal_error("malloc()"); 799 800 create_threads(ctxtswtest_config.num_threads, finfo); 801 802 /* 803 * This thread wakes up thread 0 804 * Thread 0 will wake up 1 805 * Thread 1 will wake up 2 806 * ... 807 * the last thread will wake up 0 808 * 809 * ... this will repeat for the configured 810 * number of iterations. 811 */ 812 pthread_mutex_unlock(&finfo[0].mutex); 813 814 /* Wait for all the threads to finish: */ 815 for (i = 0; i < ctxtswtest_config.num_threads; i++) { 816 void *thread_retval; 817 int rc; 818 819 rc = pthread_join(finfo[i].thread, &thread_retval); 820 821 if (rc) 822 fatal_error("pthread_join() failed for thread %d err: %d\n", 823 i, rc); 824 825 if (thread_retval != &finfo[i]) 826 fatal_error("unexpected thread retval for thread %d: %p\n", 827 i, thread_retval); 828 829 } 830 831 printf("[OK]\tNo incorrect case was found.\n"); 832 833 free(finfo); 834 } 835 836 /* Ptrace test */ 837 838 /* 839 * Make sure the ptracee has the expanded kernel buffer on the first 840 * use. Then, initialize the state before performing the state 841 * injection from the ptracer. 842 */ 843 static inline void ptracee_firstuse_tiledata(void) 844 { 845 load_rand_tiledata(stashed_xsave); 846 init_xtiledata(); 847 } 848 849 /* 850 * Ptracer injects the randomized tile data state. It also reads 851 * before and after that, which will execute the kernel's state copy 852 * functions. So, the tester is advised to double-check any emitted 853 * kernel messages. 854 */ 855 static void ptracer_inject_tiledata(pid_t target) 856 { 857 struct xsave_buffer *xbuf; 858 struct iovec iov; 859 860 xbuf = alloc_xbuf(); 861 if (!xbuf) 862 fatal_error("unable to allocate XSAVE buffer"); 863 864 printf("\tRead the init'ed tiledata via ptrace().\n"); 865 866 iov.iov_base = xbuf; 867 iov.iov_len = xbuf_size; 868 869 memset(stashed_xsave, 0, xbuf_size); 870 871 if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 872 fatal_error("PTRACE_GETREGSET"); 873 874 if (!__compare_tiledata_state(stashed_xsave, xbuf)) 875 printf("[OK]\tThe init'ed tiledata was read from ptracee.\n"); 876 else 877 printf("[FAIL]\tThe init'ed tiledata was not read from ptracee.\n"); 878 879 printf("\tInject tiledata via ptrace().\n"); 880 881 load_rand_tiledata(xbuf); 882 883 memcpy(&stashed_xsave->bytes[xtiledata.xbuf_offset], 884 &xbuf->bytes[xtiledata.xbuf_offset], 885 xtiledata.size); 886 887 if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 888 fatal_error("PTRACE_SETREGSET"); 889 890 if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov)) 891 fatal_error("PTRACE_GETREGSET"); 892 893 if (!__compare_tiledata_state(stashed_xsave, xbuf)) 894 printf("[OK]\tTiledata was correctly written to ptracee.\n"); 895 else 896 printf("[FAIL]\tTiledata was not correctly written to ptracee.\n"); 897 } 898 899 static void test_ptrace(void) 900 { 901 pid_t child; 902 int status; 903 904 child = fork(); 905 if (child < 0) { 906 err(1, "fork"); 907 } else if (!child) { 908 if (ptrace(PTRACE_TRACEME, 0, NULL, NULL)) 909 err(1, "PTRACE_TRACEME"); 910 911 ptracee_firstuse_tiledata(); 912 913 raise(SIGTRAP); 914 _exit(0); 915 } 916 917 do { 918 wait(&status); 919 } while (WSTOPSIG(status) != SIGTRAP); 920 921 ptracer_inject_tiledata(child); 922 923 ptrace(PTRACE_DETACH, child, NULL, NULL); 924 wait(&status); 925 if (!WIFEXITED(status) || WEXITSTATUS(status)) 926 err(1, "ptrace test"); 927 } 928 929 int main(void) 930 { 931 /* Check hardware availability at first */ 932 check_cpuid_xsave(); 933 check_cpuid_xtiledata(); 934 935 init_stashed_xsave(); 936 sethandler(SIGILL, handle_noperm, 0); 937 938 test_dynamic_state(); 939 940 /* Request permission for the following tests */ 941 req_xtiledata_perm(); 942 943 test_fork(); 944 945 ctxtswtest_config.iterations = 10; 946 ctxtswtest_config.num_threads = 5; 947 test_context_switch(); 948 949 test_ptrace(); 950 951 clearhandler(SIGILL); 952 free_stashed_xsave(); 953 954 return 0; 955 } 956