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