xref: /kvm-unit-tests/x86/xsave.c (revision f3f338619e4938c2509f5c691adc1f331b07c203)
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 
test_xsave(void)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 
test_no_xsave(void)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 
main(void)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