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("Check minimal XSAVE required bits", 67 (supported_xcr0 & test_bits) == test_bits); 68 69 cr4 = read_cr4(); 70 report("Set CR4 OSXSAVE", write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == 0); 71 report("Check CPUID.1.ECX.OSXSAVE - expect 1", 72 this_cpu_has(X86_FEATURE_OSXSAVE)); 73 74 printf("\tLegal tests\n"); 75 test_bits = XSTATE_FP; 76 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)", 77 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0); 78 79 test_bits = XSTATE_FP | XSTATE_SSE; 80 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)", 81 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0); 82 report(" xgetbv(XCR_XFEATURE_ENABLED_MASK)", 83 xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0); 84 85 printf("\tIllegal tests\n"); 86 test_bits = 0; 87 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP", 88 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 89 90 test_bits = XSTATE_SSE; 91 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP", 92 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 93 94 if (supported_xcr0 & XSTATE_YMM) { 95 test_bits = XSTATE_YMM; 96 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP", 97 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 98 99 test_bits = XSTATE_FP | XSTATE_YMM; 100 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP", 101 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 102 } 103 104 test_bits = XSTATE_SSE; 105 report("\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP", 106 xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR); 107 108 test_bits = XSTATE_SSE; 109 report("\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP", 110 xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR); 111 112 cr4 &= ~X86_CR4_OSXSAVE; 113 report("Unset CR4 OSXSAVE", write_cr4_checking(cr4) == 0); 114 report("Check CPUID.1.ECX.OSXSAVE - expect 0", 115 this_cpu_has(X86_FEATURE_OSXSAVE) == 0); 116 117 printf("\tIllegal tests:\n"); 118 test_bits = XSTATE_FP; 119 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD", 120 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR); 121 122 test_bits = XSTATE_FP | XSTATE_SSE; 123 report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD", 124 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR); 125 126 printf("\tIllegal tests:\n"); 127 report("\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD", 128 xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR); 129 } 130 131 static void test_no_xsave(void) 132 { 133 unsigned long cr4; 134 u64 xcr0; 135 136 report("Check CPUID.1.ECX.OSXSAVE - expect 0", 137 this_cpu_has(X86_FEATURE_OSXSAVE) == 0); 138 139 printf("Illegal instruction testing:\n"); 140 141 cr4 = read_cr4(); 142 report("Set OSXSAVE in CR4 - expect #GP", 143 write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR); 144 145 report("Execute xgetbv - expect #UD", 146 xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR); 147 148 report("Execute xsetbv - expect #UD", 149 xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR); 150 } 151 152 int main(void) 153 { 154 setup_idt(); 155 if (this_cpu_has(X86_FEATURE_XSAVE)) { 156 printf("CPU has XSAVE feature\n"); 157 test_xsave(); 158 } else { 159 printf("CPU don't has XSAVE feature\n"); 160 test_no_xsave(); 161 } 162 return report_summary(); 163 } 164