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 11db4898e8SThomas Huth static uint64_t get_supported_xcr0(void) 127d36db35SAvi Kivity { 13985ab97eSPaolo Bonzini struct cpuid r; 14985ab97eSPaolo Bonzini r = cpuid_indexed(0xd, 0); 157d36db35SAvi Kivity printf("eax %x, ebx %x, ecx %x, edx %x\n", 16985ab97eSPaolo Bonzini r.a, r.b, r.c, r.d); 17985ab97eSPaolo Bonzini return r.a + ((u64)r.d << 32); 187d36db35SAvi Kivity } 197d36db35SAvi Kivity 207d36db35SAvi Kivity #define XCR_XFEATURE_ENABLED_MASK 0x00000000 217d36db35SAvi Kivity #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010 227d36db35SAvi Kivity 237d36db35SAvi Kivity #define XSTATE_FP 0x1 247d36db35SAvi Kivity #define XSTATE_SSE 0x2 257d36db35SAvi Kivity #define XSTATE_YMM 0x4 267d36db35SAvi Kivity 27db4898e8SThomas Huth static void test_xsave(void) 287d36db35SAvi Kivity { 297d36db35SAvi Kivity unsigned long cr4; 307d36db35SAvi Kivity uint64_t supported_xcr0; 317d36db35SAvi Kivity uint64_t test_bits; 327d36db35SAvi Kivity u64 xcr0; 337d36db35SAvi Kivity 347d36db35SAvi Kivity printf("Legal instruction testing:\n"); 358b1e9483SAndrew Jones 367d36db35SAvi Kivity supported_xcr0 = get_supported_xcr0(); 37fd6aada0SRadim Krčmář printf("Supported XCR0 bits: %#lx\n", supported_xcr0); 387d36db35SAvi Kivity 397d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 40a299895bSThomas Huth report((supported_xcr0 & test_bits) == test_bits, 41a299895bSThomas Huth "Check minimal XSAVE required bits"); 427d36db35SAvi Kivity 437d36db35SAvi Kivity cr4 = read_cr4(); 444143fbfdSSean Christopherson report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == 0, "Set CR4 OSXSAVE"); 45a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE), 46a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 1"); 477d36db35SAvi Kivity 488b1e9483SAndrew Jones printf("\tLegal tests\n"); 497d36db35SAvi Kivity test_bits = XSTATE_FP; 504143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 51a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)"); 528b1e9483SAndrew Jones 537d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 544143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 55a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)"); 56*fa68c037SSean Christopherson report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0, 57a299895bSThomas Huth " xgetbv(XCR_XFEATURE_ENABLED_MASK)"); 588b1e9483SAndrew Jones 598b1e9483SAndrew Jones printf("\tIllegal tests\n"); 607d36db35SAvi Kivity test_bits = 0; 614143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 62a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP"); 637d36db35SAvi Kivity 648b1e9483SAndrew Jones test_bits = XSTATE_SSE; 654143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 66a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP"); 678b1e9483SAndrew Jones 688b1e9483SAndrew Jones if (supported_xcr0 & XSTATE_YMM) { 698b1e9483SAndrew Jones test_bits = XSTATE_YMM; 704143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 71a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP"); 728b1e9483SAndrew Jones 738b1e9483SAndrew Jones test_bits = XSTATE_FP | XSTATE_YMM; 744143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 75a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP"); 768b1e9483SAndrew Jones } 778b1e9483SAndrew Jones 788b1e9483SAndrew Jones test_bits = XSTATE_SSE; 794143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 80a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 818b1e9483SAndrew Jones 828b1e9483SAndrew Jones test_bits = XSTATE_SSE; 834143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 84a299895bSThomas Huth "\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 858b1e9483SAndrew Jones 867d36db35SAvi Kivity cr4 &= ~X86_CR4_OSXSAVE; 874143fbfdSSean Christopherson report(write_cr4_safe(cr4) == 0, "Unset CR4 OSXSAVE"); 88a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 89a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 0"); 908b1e9483SAndrew Jones 918b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 927d36db35SAvi Kivity test_bits = XSTATE_FP; 934143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 94a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD"); 958b1e9483SAndrew Jones 967d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 974143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 98a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD"); 998b1e9483SAndrew Jones 1008b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 101*fa68c037SSean Christopherson report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 102a299895bSThomas Huth "\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD"); 1037d36db35SAvi Kivity } 1047d36db35SAvi Kivity 105db4898e8SThomas Huth static void test_no_xsave(void) 1067d36db35SAvi Kivity { 1077d36db35SAvi Kivity unsigned long cr4; 1087d36db35SAvi Kivity u64 xcr0; 1097d36db35SAvi Kivity 110a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 111a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 0"); 1127d36db35SAvi Kivity 1137d36db35SAvi Kivity printf("Illegal instruction testing:\n"); 1147d36db35SAvi Kivity 1157d36db35SAvi Kivity cr4 = read_cr4(); 1164143fbfdSSean Christopherson report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR, 117a299895bSThomas Huth "Set OSXSAVE in CR4 - expect #GP"); 1187d36db35SAvi Kivity 119*fa68c037SSean Christopherson report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 120a299895bSThomas Huth "Execute xgetbv - expect #UD"); 1217d36db35SAvi Kivity 1224143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR, 123a299895bSThomas Huth "Execute xsetbv - expect #UD"); 1247d36db35SAvi Kivity } 1257d36db35SAvi Kivity 1267d36db35SAvi Kivity int main(void) 1277d36db35SAvi Kivity { 128badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_XSAVE)) { 1297d36db35SAvi Kivity printf("CPU has XSAVE feature\n"); 1307d36db35SAvi Kivity test_xsave(); 1317d36db35SAvi Kivity } else { 1327d36db35SAvi Kivity printf("CPU don't has XSAVE feature\n"); 1337d36db35SAvi Kivity test_no_xsave(); 1347d36db35SAvi Kivity } 1358b1e9483SAndrew Jones return report_summary(); 1367d36db35SAvi Kivity } 137