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 int xgetbv_checking(u32 index, u64 *result) 127d36db35SAvi Kivity { 137d36db35SAvi Kivity u32 eax, edx; 147d36db35SAvi Kivity 157d36db35SAvi Kivity asm volatile(ASM_TRY("1f") 167d36db35SAvi Kivity ".byte 0x0f,0x01,0xd0\n\t" /* xgetbv */ 177d36db35SAvi Kivity "1:" 187d36db35SAvi Kivity : "=a" (eax), "=d" (edx) 197d36db35SAvi Kivity : "c" (index)); 207d36db35SAvi Kivity *result = eax + ((u64)edx << 32); 217d36db35SAvi Kivity return exception_vector(); 227d36db35SAvi Kivity } 237d36db35SAvi Kivity 24*4143fbfdSSean Christopherson static int xsetbv_safe(u32 index, u64 value) 257d36db35SAvi Kivity { 267d36db35SAvi Kivity u32 eax = value; 277d36db35SAvi Kivity u32 edx = value >> 32; 287d36db35SAvi Kivity 297d36db35SAvi Kivity asm volatile(ASM_TRY("1f") 307d36db35SAvi Kivity ".byte 0x0f,0x01,0xd1\n\t" /* xsetbv */ 317d36db35SAvi Kivity "1:" 327d36db35SAvi Kivity : : "a" (eax), "d" (edx), "c" (index)); 337d36db35SAvi Kivity return exception_vector(); 347d36db35SAvi Kivity } 357d36db35SAvi Kivity 36db4898e8SThomas Huth static uint64_t get_supported_xcr0(void) 377d36db35SAvi Kivity { 38985ab97eSPaolo Bonzini struct cpuid r; 39985ab97eSPaolo Bonzini r = cpuid_indexed(0xd, 0); 407d36db35SAvi Kivity printf("eax %x, ebx %x, ecx %x, edx %x\n", 41985ab97eSPaolo Bonzini r.a, r.b, r.c, r.d); 42985ab97eSPaolo Bonzini return r.a + ((u64)r.d << 32); 437d36db35SAvi Kivity } 447d36db35SAvi Kivity 457d36db35SAvi Kivity #define XCR_XFEATURE_ENABLED_MASK 0x00000000 467d36db35SAvi Kivity #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010 477d36db35SAvi Kivity 487d36db35SAvi Kivity #define XSTATE_FP 0x1 497d36db35SAvi Kivity #define XSTATE_SSE 0x2 507d36db35SAvi Kivity #define XSTATE_YMM 0x4 517d36db35SAvi Kivity 52db4898e8SThomas Huth static void test_xsave(void) 537d36db35SAvi Kivity { 547d36db35SAvi Kivity unsigned long cr4; 557d36db35SAvi Kivity uint64_t supported_xcr0; 567d36db35SAvi Kivity uint64_t test_bits; 577d36db35SAvi Kivity u64 xcr0; 587d36db35SAvi Kivity 597d36db35SAvi Kivity printf("Legal instruction testing:\n"); 608b1e9483SAndrew Jones 617d36db35SAvi Kivity supported_xcr0 = get_supported_xcr0(); 62fd6aada0SRadim Krčmář printf("Supported XCR0 bits: %#lx\n", supported_xcr0); 637d36db35SAvi Kivity 647d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 65a299895bSThomas Huth report((supported_xcr0 & test_bits) == test_bits, 66a299895bSThomas Huth "Check minimal XSAVE required bits"); 677d36db35SAvi Kivity 687d36db35SAvi Kivity cr4 = read_cr4(); 69*4143fbfdSSean Christopherson report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == 0, "Set CR4 OSXSAVE"); 70a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE), 71a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 1"); 727d36db35SAvi Kivity 738b1e9483SAndrew Jones printf("\tLegal tests\n"); 747d36db35SAvi Kivity test_bits = XSTATE_FP; 75*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 76a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)"); 778b1e9483SAndrew Jones 787d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 79*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0, 80a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)"); 81a299895bSThomas Huth report(xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0, 82a299895bSThomas Huth " xgetbv(XCR_XFEATURE_ENABLED_MASK)"); 838b1e9483SAndrew Jones 848b1e9483SAndrew Jones printf("\tIllegal tests\n"); 857d36db35SAvi Kivity test_bits = 0; 86*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 87a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP"); 887d36db35SAvi Kivity 898b1e9483SAndrew Jones test_bits = XSTATE_SSE; 90*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 91a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP"); 928b1e9483SAndrew Jones 938b1e9483SAndrew Jones if (supported_xcr0 & XSTATE_YMM) { 948b1e9483SAndrew Jones test_bits = XSTATE_YMM; 95*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 96a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP"); 978b1e9483SAndrew Jones 988b1e9483SAndrew Jones test_bits = XSTATE_FP | XSTATE_YMM; 99*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR, 100a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP"); 1018b1e9483SAndrew Jones } 1028b1e9483SAndrew Jones 1038b1e9483SAndrew Jones test_bits = XSTATE_SSE; 104*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 105a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 1068b1e9483SAndrew Jones 1078b1e9483SAndrew Jones test_bits = XSTATE_SSE; 108*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR, 109a299895bSThomas Huth "\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP"); 1108b1e9483SAndrew Jones 1117d36db35SAvi Kivity cr4 &= ~X86_CR4_OSXSAVE; 112*4143fbfdSSean Christopherson report(write_cr4_safe(cr4) == 0, "Unset CR4 OSXSAVE"); 113a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 114a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 0"); 1158b1e9483SAndrew Jones 1168b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 1177d36db35SAvi Kivity test_bits = XSTATE_FP; 118*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 119a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD"); 1208b1e9483SAndrew Jones 1217d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 122*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR, 123a299895bSThomas Huth "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD"); 1248b1e9483SAndrew Jones 1258b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 126a299895bSThomas Huth report(xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 127a299895bSThomas Huth "\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD"); 1287d36db35SAvi Kivity } 1297d36db35SAvi Kivity 130db4898e8SThomas Huth static void test_no_xsave(void) 1317d36db35SAvi Kivity { 1327d36db35SAvi Kivity unsigned long cr4; 1337d36db35SAvi Kivity u64 xcr0; 1347d36db35SAvi Kivity 135a299895bSThomas Huth report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0, 136a299895bSThomas Huth "Check CPUID.1.ECX.OSXSAVE - expect 0"); 1377d36db35SAvi Kivity 1387d36db35SAvi Kivity printf("Illegal instruction testing:\n"); 1397d36db35SAvi Kivity 1407d36db35SAvi Kivity cr4 = read_cr4(); 141*4143fbfdSSean Christopherson report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR, 142a299895bSThomas Huth "Set OSXSAVE in CR4 - expect #GP"); 1437d36db35SAvi Kivity 144a299895bSThomas Huth report(xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR, 145a299895bSThomas Huth "Execute xgetbv - expect #UD"); 1467d36db35SAvi Kivity 147*4143fbfdSSean Christopherson report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR, 148a299895bSThomas Huth "Execute xsetbv - expect #UD"); 1497d36db35SAvi Kivity } 1507d36db35SAvi Kivity 1517d36db35SAvi Kivity int main(void) 1527d36db35SAvi Kivity { 153badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_XSAVE)) { 1547d36db35SAvi Kivity printf("CPU has XSAVE feature\n"); 1557d36db35SAvi Kivity test_xsave(); 1567d36db35SAvi Kivity } else { 1577d36db35SAvi Kivity printf("CPU don't has XSAVE feature\n"); 1587d36db35SAvi Kivity test_no_xsave(); 1597d36db35SAvi Kivity } 1608b1e9483SAndrew Jones return report_summary(); 1617d36db35SAvi Kivity } 162