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 24db4898e8SThomas Huth static int xsetbv_checking(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 X86_CR4_OSXSAVE 0x00040000 467d36db35SAvi Kivity #define XCR_XFEATURE_ENABLED_MASK 0x00000000 477d36db35SAvi Kivity #define XCR_XFEATURE_ILLEGAL_MASK 0x00000010 487d36db35SAvi Kivity 497d36db35SAvi Kivity #define XSTATE_FP 0x1 507d36db35SAvi Kivity #define XSTATE_SSE 0x2 517d36db35SAvi Kivity #define XSTATE_YMM 0x4 527d36db35SAvi Kivity 53db4898e8SThomas Huth static void test_xsave(void) 547d36db35SAvi Kivity { 557d36db35SAvi Kivity unsigned long cr4; 567d36db35SAvi Kivity uint64_t supported_xcr0; 577d36db35SAvi Kivity uint64_t test_bits; 587d36db35SAvi Kivity u64 xcr0; 597d36db35SAvi Kivity 607d36db35SAvi Kivity printf("Legal instruction testing:\n"); 618b1e9483SAndrew Jones 627d36db35SAvi Kivity supported_xcr0 = get_supported_xcr0(); 63fd6aada0SRadim Krčmář printf("Supported XCR0 bits: %#lx\n", supported_xcr0); 647d36db35SAvi Kivity 657d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 668b1e9483SAndrew Jones report("Check minimal XSAVE required bits", 678b1e9483SAndrew Jones (supported_xcr0 & test_bits) == test_bits); 687d36db35SAvi Kivity 697d36db35SAvi Kivity cr4 = read_cr4(); 708b1e9483SAndrew Jones report("Set CR4 OSXSAVE", write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == 0); 718b1e9483SAndrew Jones report("Check CPUID.1.ECX.OSXSAVE - expect 1", 72*badc98caSKrish Sadhukhan this_cpu_has(X86_FEATURE_OSXSAVE)); 737d36db35SAvi Kivity 748b1e9483SAndrew Jones printf("\tLegal tests\n"); 757d36db35SAvi Kivity test_bits = XSTATE_FP; 768b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)", 778b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0); 788b1e9483SAndrew Jones 797d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 808b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)", 818b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0); 828b1e9483SAndrew Jones report(" xgetbv(XCR_XFEATURE_ENABLED_MASK)", 838b1e9483SAndrew Jones xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0); 848b1e9483SAndrew Jones 858b1e9483SAndrew Jones printf("\tIllegal tests\n"); 867d36db35SAvi Kivity test_bits = 0; 878b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP", 888b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 897d36db35SAvi Kivity 908b1e9483SAndrew Jones test_bits = XSTATE_SSE; 918b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP", 928b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 938b1e9483SAndrew Jones 948b1e9483SAndrew Jones if (supported_xcr0 & XSTATE_YMM) { 958b1e9483SAndrew Jones test_bits = XSTATE_YMM; 968b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP", 978b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 988b1e9483SAndrew Jones 998b1e9483SAndrew Jones test_bits = XSTATE_FP | XSTATE_YMM; 1008b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP", 1018b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR); 1028b1e9483SAndrew Jones } 1038b1e9483SAndrew Jones 1048b1e9483SAndrew Jones test_bits = XSTATE_SSE; 1058b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP", 1068b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR); 1078b1e9483SAndrew Jones 1088b1e9483SAndrew Jones test_bits = XSTATE_SSE; 1098b1e9483SAndrew Jones report("\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP", 1108b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR); 1118b1e9483SAndrew Jones 1127d36db35SAvi Kivity cr4 &= ~X86_CR4_OSXSAVE; 1138b1e9483SAndrew Jones report("Unset CR4 OSXSAVE", write_cr4_checking(cr4) == 0); 1148b1e9483SAndrew Jones report("Check CPUID.1.ECX.OSXSAVE - expect 0", 115*badc98caSKrish Sadhukhan this_cpu_has(X86_FEATURE_OSXSAVE) == 0); 1168b1e9483SAndrew Jones 1178b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 1187d36db35SAvi Kivity test_bits = XSTATE_FP; 1198b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD", 1208b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR); 1218b1e9483SAndrew Jones 1227d36db35SAvi Kivity test_bits = XSTATE_FP | XSTATE_SSE; 1238b1e9483SAndrew Jones report("\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD", 1248b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR); 1258b1e9483SAndrew Jones 1268b1e9483SAndrew Jones printf("\tIllegal tests:\n"); 1278b1e9483SAndrew Jones report("\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD", 1288b1e9483SAndrew Jones xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR); 1297d36db35SAvi Kivity } 1307d36db35SAvi Kivity 131db4898e8SThomas Huth static void test_no_xsave(void) 1327d36db35SAvi Kivity { 1337d36db35SAvi Kivity unsigned long cr4; 1347d36db35SAvi Kivity u64 xcr0; 1357d36db35SAvi Kivity 1368b1e9483SAndrew Jones report("Check CPUID.1.ECX.OSXSAVE - expect 0", 137*badc98caSKrish Sadhukhan this_cpu_has(X86_FEATURE_OSXSAVE) == 0); 1387d36db35SAvi Kivity 1397d36db35SAvi Kivity printf("Illegal instruction testing:\n"); 1407d36db35SAvi Kivity 1417d36db35SAvi Kivity cr4 = read_cr4(); 1428b1e9483SAndrew Jones report("Set OSXSAVE in CR4 - expect #GP", 1438b1e9483SAndrew Jones write_cr4_checking(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR); 1447d36db35SAvi Kivity 1458b1e9483SAndrew Jones report("Execute xgetbv - expect #UD", 1468b1e9483SAndrew Jones xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR); 1477d36db35SAvi Kivity 1488b1e9483SAndrew Jones report("Execute xsetbv - expect #UD", 1498b1e9483SAndrew Jones xsetbv_checking(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR); 1507d36db35SAvi Kivity } 1517d36db35SAvi Kivity 1527d36db35SAvi Kivity int main(void) 1537d36db35SAvi Kivity { 1547d36db35SAvi Kivity setup_idt(); 155*badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_XSAVE)) { 1567d36db35SAvi Kivity printf("CPU has XSAVE feature\n"); 1577d36db35SAvi Kivity test_xsave(); 1587d36db35SAvi Kivity } else { 1597d36db35SAvi Kivity printf("CPU don't has XSAVE feature\n"); 1607d36db35SAvi Kivity test_no_xsave(); 1617d36db35SAvi Kivity } 1628b1e9483SAndrew Jones return report_summary(); 1637d36db35SAvi Kivity } 164