cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

amx.c (20448B)


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