1 #include "libcflat.h" 2 #include "desc.h" 3 #include "processor.h" 4 5 #ifdef __x86_64__ 6 #define uint64_t unsigned long 7 #else 8 #define uint64_t unsigned long long 9 #endif 10 11 static int xgetbv_checking(u32 index, u64 *result) 12 { 13 u32 eax, edx; 14 15 asm volatile(ASM_TRY("1f") 16 ".byte 0x0f,0x01,0xd0\n\t" /* xgetbv */ 17 "1:" 18 : "=a" (eax), "=d" (edx) 19 : "c" (index)); 20 *result = eax + ((u64)edx << 32); 21 return exception_vector(); 22 } 23 24 static int xsetbv_checking(u32 index, u64 value) 25 { 26 u32 eax = value; 27 u32 edx = value >> 32; 28 29 asm volatile(ASM_TRY("1f") 30 ".byte 0x0f,0x01,0xd1\n\t" /* xsetbv */ 31 "1:" 32 : : "a" (eax), "d" (edx), "c" (index)); 33 return exception_vector(); 34 } 35 36 static uint64_t get_supported_xcr0(void) 37 { 38 struct cpuid r; 39 r = cpuid_indexed(0xd, 0); 40 printf("eax %x, ebx %x, ecx %x, edx %x\n", 41 r.a, r.b, r.c, r.d); 42 return r.a + ((u64)r.d << 32); 43 } 44 45 #define X86_CR4_OSXSAVE 0x00040000 46 #define XCR_XFEATURE_ENABLED_MASK 0x00000000 47 #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010 48 49 #define XSTATE_FP 0x1 50 #define XSTATE_SSE 0x2 51 #define XSTATE_YMM 0x4 52 53 static void test_xsave(void) 54 { 55 unsigned long cr4; 56 uint64_t supported_xcr0; 57 uint64_t test_bits; 58 u64 xcr0; 59 60 printf("Legal instruction testing:\n"); 61 62 supported_xcr0 = get_supported_xcr0(); 63 printf("Supported XCR0 bits: %#lx\n", supported_xcr0); 64 65 test_bits = XSTATE_FP | XSTATE_SSE; 66 report((supported_xcr0 & test_bits) == test_bits, 67 "Check minimal XSAVE required bits"); 68 69 cr4 = read_cr4(); 70 report(write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == 0, "Set CR4 OSXSAVE"); 71 report(this_cpu_has(X86_FEATURE_OSXSAVE), 72 "Check CPUID.1.ECX.OSXSAVE - expect 1"); 73 74 printf("\tLegal tests\n"); 75 test_bits = XSTATE_FP; 76 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 77 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)"); 78 79 test_bits = XSTATE_FP | XSTATE_SSE; 80 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 81 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)"); 82 report(xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0, 83 " xgetbv(XCR_XFEATURE_ENABLED_MASK)"); 84 85 printf("\tIllegal tests\n"); 86 test_bits = 0; 87 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 88 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP"); 89 90 test_bits = XSTATE_SSE; 91 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 92 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP"); 93 94 if (supported_xcr0 & XSTATE_YMM) { 95 test_bits = XSTATE_YMM; 96 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 97 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP"); 98 99 test_bits = XSTATE_FP | XSTATE_YMM; 100 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 101 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP"); 102 } 103 104 test_bits = XSTATE_SSE; 105 report(xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 106 "\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 107 108 test_bits = XSTATE_SSE; 109 report(xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 110 "\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 111 112 cr4 &= ~X86_CR4_OSXSAVE; 113 report(write_cr4_checking(cr4) == 0, "Unset CR4 OSXSAVE"); 114 report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 115 "Check CPUID.1.ECX.OSXSAVE - expect 0"); 116 117 printf("\tIllegal tests:\n"); 118 test_bits = XSTATE_FP; 119 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 120 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD"); 121 122 test_bits = XSTATE_FP | XSTATE_SSE; 123 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 124 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD"); 125 126 printf("\tIllegal tests:\n"); 127 report(xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 128 "\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD"); 129 } 130 131 static void test_no_xsave(void) 132 { 133 unsigned long cr4; 134 u64 xcr0; 135 136 report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 137 "Check CPUID.1.ECX.OSXSAVE - expect 0"); 138 139 printf("Illegal instruction testing:\n"); 140 141 cr4 = read_cr4(); 142 report(write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR, 143 "Set OSXSAVE in CR4 - expect #GP"); 144 145 report(xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 146 "Execute xgetbv - expect #UD"); 147 148 report(xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR, 149 "Execute xsetbv - expect #UD"); 150 } 151 152 int main(void) 153 { 154 if (this_cpu_has(X86_FEATURE_XSAVE)) { 155 printf("CPU has XSAVE feature\n"); 156 test_xsave(); 157 } else { 158 printf("CPU don't has XSAVE feature\n"); 159 test_no_xsave(); 160 } 161 return report_summary(); 162 } 163