17d36db35SAvi Kivity #include "libcflat.h" 2e7c37968SGleb Natapov #include "desc.h" 3985ab97eSPaolo Bonzini #include "processor.h" 47d36db35SAvi Kivity 57d36db35SAvi Kivity #ifdef __x86_64__ 67d36db35SAvi Kivity #define uint64_t unsigned long 77d36db35SAvi Kivity #else 87d36db35SAvi Kivity #define uint64_t unsigned long long 97d36db35SAvi Kivity #endif 107d36db35SAvi Kivity 117d36db35SAvi Kivity #define XCR_XFEATURE_ENABLED_MASK 0x00000000 127d36db35SAvi Kivity #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010 137d36db35SAvi Kivity 147d36db35SAvi Kivity #define XSTATE_FP 0x1 157d36db35SAvi Kivity #define XSTATE_SSE 0x2 167d36db35SAvi Kivity #define XSTATE_YMM 0x4 177d36db35SAvi Kivity 18db4898e8SThomas Huth static void test_xsave(void) 197d36db35SAvi Kivity { 207d36db35SAvi Kivity unsigned long cr4; 217d36db35SAvi Kivity uint64_t supported_xcr0; 227d36db35SAvi Kivity uint64_t test_bits; 237d36db35SAvi Kivity u64 xcr0; 247d36db35SAvi Kivity 257d36db35SAvi Kivity printf("Legal instruction testing:\n"); 268b1e9483SAndrew Jones 27*587db1e8SSean Christopherson supported_xcr0 = this_cpu_supported_xcr0(); 28fd6aada0SRadim Krčmář printf("Supported XCR0 bits: %#lx\n", supported_xcr0); 297d36db35SAvi Kivity 307d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 31a299895bSThomas Huth report((supported_xcr0 & test_bits) == test_bits, 32a299895bSThomas Huth "Check minimal XSAVE required bits"); 337d36db35SAvi Kivity 347d36db35SAvi Kivity cr4 = read_cr4(); 354143fbfdSSean Christopherson report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == 0, "Set CR4 OSXSAVE"); 36a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE), 37a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 1"); 387d36db35SAvi Kivity 398b1e9483SAndrew Jones printf("\tLegal tests\n"); 407d36db35SAvi Kivity test_bits = XSTATE_FP; 414143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 42a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)"); 438b1e9483SAndrew Jones 447d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 454143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 46a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)"); 47fa68c037SSean Christopherson report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0, 48a299895bSThomas Huth " xgetbv(XCR_XFEATURE_ENABLED_MASK)"); 498b1e9483SAndrew Jones 508b1e9483SAndrew Jones printf("\tIllegal tests\n"); 517d36db35SAvi Kivity test_bits = 0; 524143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 53a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP"); 547d36db35SAvi Kivity 558b1e9483SAndrew Jones test_bits = XSTATE_SSE; 564143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 57a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP"); 588b1e9483SAndrew Jones 598b1e9483SAndrew Jones if (supported_xcr0 & XSTATE_YMM) { 608b1e9483SAndrew Jones test_bits = XSTATE_YMM; 614143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 62a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP"); 638b1e9483SAndrew Jones 648b1e9483SAndrew Jones test_bits = XSTATE_FP | XSTATE_YMM; 654143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 66a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP"); 678b1e9483SAndrew Jones } 688b1e9483SAndrew Jones 698b1e9483SAndrew Jones test_bits = XSTATE_SSE; 704143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 71a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 728b1e9483SAndrew Jones 738b1e9483SAndrew Jones test_bits = XSTATE_SSE; 744143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 75a299895bSThomas Huth "\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 768b1e9483SAndrew Jones 777d36db35SAvi Kivity cr4 &= ~X86_CR4_OSXSAVE; 784143fbfdSSean Christopherson report(write_cr4_safe(cr4) == 0, "Unset CR4 OSXSAVE"); 79a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 80a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 0"); 818b1e9483SAndrew Jones 828b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 837d36db35SAvi Kivity test_bits = XSTATE_FP; 844143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 85a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD"); 868b1e9483SAndrew Jones 877d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 884143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 89a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD"); 908b1e9483SAndrew Jones 918b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 92fa68c037SSean Christopherson report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 93a299895bSThomas Huth "\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD"); 947d36db35SAvi Kivity } 957d36db35SAvi Kivity 96db4898e8SThomas Huth static void test_no_xsave(void) 977d36db35SAvi Kivity { 987d36db35SAvi Kivity unsigned long cr4; 997d36db35SAvi Kivity u64 xcr0; 1007d36db35SAvi Kivity 101a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 102a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 0"); 1037d36db35SAvi Kivity 1047d36db35SAvi Kivity printf("Illegal instruction testing:\n"); 1057d36db35SAvi Kivity 1067d36db35SAvi Kivity cr4 = read_cr4(); 1074143fbfdSSean Christopherson report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR, 108a299895bSThomas Huth "Set OSXSAVE in CR4 - expect #GP"); 1097d36db35SAvi Kivity 110fa68c037SSean Christopherson report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 111a299895bSThomas Huth "Execute xgetbv - expect #UD"); 1127d36db35SAvi Kivity 1134143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR, 114a299895bSThomas Huth "Execute xsetbv - expect #UD"); 1157d36db35SAvi Kivity } 1167d36db35SAvi Kivity 1177d36db35SAvi Kivity int main(void) 1187d36db35SAvi Kivity { 119badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_XSAVE)) { 1207d36db35SAvi Kivity printf("CPU has XSAVE feature\n"); 1217d36db35SAvi Kivity test_xsave(); 1227d36db35SAvi Kivity } else { 1237d36db35SAvi Kivity printf("CPU don't has XSAVE feature\n"); 1247d36db35SAvi Kivity test_no_xsave(); 1257d36db35SAvi Kivity } 1268b1e9483SAndrew Jones return report_summary(); 1277d36db35SAvi Kivity } 128