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