}
#endif /* __GNUC__ */
+/*
+ * XSAVE/XRSTOR
+ * save/restore GSSE/SIMD/MMX fpu state
+ *
+ * The pointer passed in must be 64-byte aligned.
+ * See above comment for more information.
+ */
+#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
+
+static INLINE void
+XSAVE_ES1(uint8 *save, uint64 mask)
+{
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0xae, 0x21 \n"
+ :
+ : "c" (save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#else
+ __asm__ __volatile__ (
+ "xsave %0 \n"
+ : "=m" (*save)
+ : "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#endif
+}
+
+static INLINE void
+XRSTOR_ES1(const uint8 *load, uint64 mask)
+{
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0xae, 0x29 \n"
+ :
+ : "c" (load), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#else
+ __asm__ __volatile__ (
+ "xrstor %0 \n"
+ :
+ : "m" (*load), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#endif
+}
+
+static INLINE void
+XRSTOR_AMD_ES0(const uint8 *load, uint64 mask)
+{
+ uint64 dummy = 0;
+
+ __asm__ __volatile__
+ ("fnstsw %%ax \n" // Grab x87 ES bit
+ "bt $7,%%ax \n" // Test ES bit
+ "jnc 1f \n" // Jump if ES=0
+ "fnclex \n" // ES=1. Clear it so fild doesn't trap
+ "1: \n"
+ "ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
+ "fildl %0 \n" // Dummy Load from "safe address" changes all
+ // x87 exception pointers.
+ "mov %%ebx, %%eax \n"
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ ".byte 0x0f, 0xae, 0x29 \n"
+ :
+ : "m" (dummy),
+ "c" (load), "b" ((uint32)mask), "d" ((uint32)(mask >> 32))
+#else
+ "xrstor %1 \n"
+ :
+ : "m" (dummy), "m" (*load), "b" ((uint32)mask), "d" ((uint32)(mask >> 32))
+#endif
+ : "eax", "memory");
+}
+#endif /* __GNUC__ */
+
/*
*-----------------------------------------------------------------------------
*
#endif /* __GNUC__ */
+/*
+ * XSAVE/XRSTOR
+ * save/restore GSSE/SIMD/MMX fpu state
+ *
+ * The pointer passed in must be 64-byte aligned.
+ * See above comment for more information.
+ */
+#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
+
+static INLINE void
+XSAVE_ES1(uint8 *save, uint64 mask)
+{
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ __asm__ __volatile__ (
+ ".byte 0x48, 0x0f, 0xae, 0x21 \n"
+ :
+ : "c" (save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#else
+ __asm__ __volatile__ (
+ "xsaveq %0 \n"
+ : "=m" (*save)
+ : "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#endif
+}
+
+static INLINE void
+XSAVE_COMPAT_ES1(uint8 *save, uint64 mask)
+{
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0xae, 0x21 \n"
+ :
+ : "c" (save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#else
+ __asm__ __volatile__ (
+ "xsave %0 \n"
+ : "=m" (*save)
+ : "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#endif
+}
+
+static INLINE void
+XRSTOR_ES1(const uint8 *load, uint64 mask)
+{
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ __asm__ __volatile__ (
+ ".byte 0x48, 0x0f, 0xae, 0x29 \n"
+ :
+ : "c" (load), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#else
+ __asm__ __volatile__ (
+ "xrstorq %0 \n"
+ :
+ : "m" (*load), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#endif
+}
+
+static INLINE void
+XRSTOR_COMPAT_ES1(const uint8 *load, uint64 mask)
+{
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0xae, 0x29 \n"
+ :
+ : "c" (load), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#else
+ __asm__ __volatile__ (
+ "xrstor %0 \n"
+ :
+ : "m" (*load), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
+ : "memory");
+#endif
+}
+
+static INLINE void
+XRSTOR_AMD_ES0(const uint8 *load, uint64 mask)
+{
+ uint64 dummy = 0;
+
+ __asm__ __volatile__
+ ("fnstsw %%ax \n" // Grab x87 ES bit
+ "bt $7,%%ax \n" // Test ES bit
+ "jnc 1f \n" // Jump if ES=0
+ "fnclex \n" // ES=1. Clear it so fild doesn't trap
+ "1: \n"
+ "ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
+ "fildl %0 \n" // Dummy Load from "safe address" changes all
+ // x87 exception pointers.
+ "mov %%ebx, %%eax \n"
+#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
+ ".byte 0x48, 0x0f, 0xae, 0x29 \n"
+ :
+ : "m" (dummy),
+ "c" (load), "b" ((uint32)mask), "d" ((uint32)(mask >> 32))
+#else
+ "xrstorq %1 \n"
+ :
+ : "m" (dummy), "m" (*load), "b" ((uint32)mask), "d" ((uint32)(mask >> 32))
+#endif
+ : "eax", "memory");
+}
+
+#endif /* __GNUC__ */
+
/*
*-----------------------------------------------------------------------------
CPUIDLEVEL(FALSE, 6, 6) \
CPUIDLEVEL(FALSE, A, 0xA) \
CPUIDLEVEL(FALSE, B, 0xB) \
+ CPUIDLEVEL(FALSE, D, 0xD) \
CPUIDLEVEL(FALSE, 86, 0x80000006)
#define CPUID_ALL_LEVELS \
FLAGDEFA( 1, ECX, COMMON, 23, 1, POPCNT, YES, TRUE, POPCNT) \
FLAGDEF( 1, ECX, INTEL, 24, 1, ULE, NO, TRUE) \
FLAGDEFA( 1, ECX, INTEL, 25, 1, AES, YES, TRUE, AES) \
-FLAGDEFA( 1, ECX, INTEL, 26, 1, XSAVE, NO, FALSE, XSAVE) \
-FLAGDEF( 1, ECX, INTEL, 27, 1, OSXSAVE, NO, TRUE) \
-FLAGDEFA( 1, ECX, INTEL, 28, 1, AVX, NO, TRUE, AVX) \
+FLAGDEFA( 1, ECX, COMMON, 26, 1, XSAVE, NO, FALSE, XSAVE) \
+FLAGDEF( 1, ECX, COMMON, 27, 1, OSXSAVE, NO, TRUE) \
+FLAGDEFA( 1, ECX, COMMON, 28, 1, AVX, NO, TRUE, AVX) \
FLAGDEFA( 1, ECX, COMMON, 31, 1, HYPERVISOR, ANY, FALSE, HYPERVISOR)\
FLAGDEFA( 1, EDX, COMMON, 0, 1, FPU, YES, TRUE, FPU) \
FLAGDEFA( 1, EDX, COMMON, 1, 1, VME, YES, FALSE, VME) \
FIELDDEF( B, ECX, INTEL, 8, 8, LEVEL_TYPE, NA, FALSE) \
FIELDDEF( B, EDX, INTEL, 0, 32, X2APIC_ID, NA, FALSE)
+/* LEVEL, REG, VENDOR, POS, SIZE, NAME, MON SUPP, CPL3, [FUNC] */
+#define CPUID_FIELD_DATA_LEVEL_D \
+FIELDDEFA( D, EAX, COMMON, 0, 32, XCR0_MASTER_LOWER, NA, FALSE, XCR0_MASTER_LOWER) \
+FIELDDEF( D, EBX, COMMON, 0, 32, XSAVE_ENABLED_SIZE, NA, FALSE) \
+FIELDDEFA( D, ECX, COMMON, 0, 32, XSAVE_MAX_SIZE, NA, FALSE, XSAVE_MAX_SIZE) \
+FIELDDEFA( D, EDX, COMMON, 0, 32, XCR0_MASTER_UPPER, NA, FALSE, XCR0_MASTER_UPPER)
+
/* LEVEL, REG, VENDOR, POS, SIZE, NAME, MON SUPP, CPL3, [FUNC] */
#define CPUID_FIELD_DATA_LEVEL_400 \
FIELDDEF(400, EAX, COMMON, 0, 32, NUM_HYP_LEVELS, NA, FALSE) \
CPUID_FIELD_DATA_LEVEL_6 \
CPUID_FIELD_DATA_LEVEL_A \
CPUID_FIELD_DATA_LEVEL_B \
+ CPUID_FIELD_DATA_LEVEL_D \
CPUID_FIELD_DATA_LEVEL_400 \
CPUID_FIELD_DATA_LEVEL_410 \
CPUID_FIELD_DATA_LEVEL_80 \