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 #define XCR_XFEATURE_ENABLED_MASK 0x00000000 12 #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010 13 14 #define XSTATE_FP 0x1 15 #define XSTATE_SSE 0x2 16 #define XSTATE_YMM 0x4 17 18 static void test_xsave(void) 19 { 20 unsigned long cr4; 21 uint64_t supported_xcr0; 22 uint64_t test_bits; 23 u64 xcr0; 24 25 printf("Legal instruction testing:\n"); 26 27 supported_xcr0 = this_cpu_supported_xcr0(); 28 printf("Supported XCR0 bits: %#lx\n", supported_xcr0); 29 30 test_bits = XSTATE_FP | XSTATE_SSE; 31 report((supported_xcr0 & test_bits) == test_bits, 32 "Check minimal XSAVE required bits"); 33 34 cr4 = read_cr4(); 35 report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == 0, "Set CR4 OSXSAVE"); 36 report(this_cpu_has(X86_FEATURE_OSXSAVE), 37 "Check CPUID.1.ECX.OSXSAVE - expect 1"); 38 39 printf("\tLegal tests\n"); 40 test_bits = XSTATE_FP; 41 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 42 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)"); 43 44 test_bits = XSTATE_FP | XSTATE_SSE; 45 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 46 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)"); 47 report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0, 48 " xgetbv(XCR_XFEATURE_ENABLED_MASK)"); 49 50 printf("\tIllegal tests\n"); 51 test_bits = 0; 52 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 53 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP"); 54 55 test_bits = XSTATE_SSE; 56 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 57 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP"); 58 59 if (supported_xcr0 & XSTATE_YMM) { 60 test_bits = XSTATE_YMM; 61 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 62 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP"); 63 64 test_bits = XSTATE_FP | XSTATE_YMM; 65 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 66 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP"); 67 } 68 69 test_bits = XSTATE_SSE; 70 report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 71 "\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 72 73 test_bits = XSTATE_SSE; 74 report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 75 "\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 76 77 cr4 &= ~X86_CR4_OSXSAVE; 78 report(write_cr4_safe(cr4) == 0, "Unset CR4 OSXSAVE"); 79 report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 80 "Check CPUID.1.ECX.OSXSAVE - expect 0"); 81 82 printf("\tIllegal tests:\n"); 83 test_bits = XSTATE_FP; 84 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 85 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD"); 86 87 test_bits = XSTATE_FP | XSTATE_SSE; 88 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 89 "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD"); 90 91 printf("\tIllegal tests:\n"); 92 report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 93 "\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD"); 94 } 95 96 static void test_no_xsave(void) 97 { 98 unsigned long cr4; 99 u64 xcr0; 100 101 report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 102 "Check CPUID.1.ECX.OSXSAVE - expect 0"); 103 104 printf("Illegal instruction testing:\n"); 105 106 cr4 = read_cr4(); 107 report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR, 108 "Set OSXSAVE in CR4 - expect #GP"); 109 110 report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 111 "Execute xgetbv - expect #UD"); 112 113 report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR, 114 "Execute xsetbv - expect #UD"); 115 } 116 117 int main(void) 118 { 119 if (this_cpu_has(X86_FEATURE_XSAVE)) { 120 printf("CPU has XSAVE feature\n"); 121 test_xsave(); 122 } else { 123 printf("CPU don't has XSAVE feature\n"); 124 test_no_xsave(); 125 } 126 return report_summary(); 127 } 128