tools/testing/selftests/x86/xstate.h

Source file repositories/reference/linux-study-clean/tools/testing/selftests/x86/xstate.h

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/x86/xstate.h
Extension
.h
Size
4478 bytes
Lines
198
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct xsave_buffer {
	union {
		struct {
			char legacy[XSAVE_HDR_OFFSET];
			char header[XSAVE_HDR_SIZE];
			char extended[0];
		};
		char bytes[0];
	};
};

static inline void xsave(struct xsave_buffer *xbuf, uint64_t rfbm)
{
	uint32_t rfbm_hi = rfbm >> 32;
	uint32_t rfbm_lo = rfbm;

	asm volatile("xsave (%%rdi)"
		     : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi)
		     : "memory");
}

static inline void xrstor(struct xsave_buffer *xbuf, uint64_t rfbm)
{
	uint32_t rfbm_hi = rfbm >> 32;
	uint32_t rfbm_lo = rfbm;

	asm volatile("xrstor (%%rdi)"
		     : : "D" (xbuf), "a" (rfbm_lo), "d" (rfbm_hi));
}

#define CPUID_LEAF_XSTATE		0xd
#define CPUID_SUBLEAF_XSTATE_USER	0x0

static inline uint32_t get_xbuf_size(void)
{
	uint32_t eax, ebx, ecx, edx;

	__cpuid_count(CPUID_LEAF_XSTATE, CPUID_SUBLEAF_XSTATE_USER,
		      eax, ebx, ecx, edx);

	/*
	 * EBX enumerates the size (in bytes) required by the XSAVE
	 * instruction for an XSAVE area containing all the user state
	 * components corresponding to bits currently set in XCR0.
	 */
	return ebx;
}

struct xstate_info {
	const char *name;
	uint32_t num;
	uint32_t mask;
	uint32_t xbuf_offset;
	uint32_t size;
};

static inline struct xstate_info get_xstate_info(uint32_t xfeature_num)
{
	struct xstate_info xstate = { };
	uint32_t eax, ebx, ecx, edx;

	if (xfeature_num >= XFEATURE_MAX) {
		ksft_print_msg("unknown state\n");
		return xstate;
	}

	xstate.name = xfeature_names[xfeature_num];
	xstate.num  = xfeature_num;
	xstate.mask = 1 << xfeature_num;

	__cpuid_count(CPUID_LEAF_XSTATE, xfeature_num,
		      eax, ebx, ecx, edx);
	xstate.size        = eax;
	xstate.xbuf_offset = ebx;
	return xstate;
}

static inline struct xsave_buffer *alloc_xbuf(void)
{
	uint32_t xbuf_size = get_xbuf_size();

	/* XSAVE buffer should be 64B-aligned. */
	return aligned_alloc(64, xbuf_size);
}

static inline void clear_xstate_header(struct xsave_buffer *xbuf)
{
	memset(&xbuf->header, 0, sizeof(xbuf->header));
}

Annotation

Implementation Notes