xref: /kvm-unit-tests/x86/xsave.c (revision 587db1e85faad8d7a39f3d2c1f1943a9163f8b19)
1 #include "libcflat.h"
2 #include "desc.h"
3 #include "processor.h"
4 
5 #ifdef __x86_64__
6 #define uint64_t unsigned long
7 #else
8 #define uint64_t unsigned long long
9 #endif
10 
11 #define XCR_XFEATURE_ENABLED_MASK       0x00000000
12 #define XCR_XFEATURE_ILLEGAL_MASK       0x00000010
13 
14 #define XSTATE_FP       0x1
15 #define XSTATE_SSE      0x2
16 #define XSTATE_YMM      0x4
17 
18 static void test_xsave(void)
19 {
20     unsigned long cr4;
21     uint64_t supported_xcr0;
22     uint64_t test_bits;
23     u64 xcr0;
24 
25     printf("Legal instruction testing:\n");
26 
27     supported_xcr0 = this_cpu_supported_xcr0();
28     printf("Supported XCR0 bits: %#lx\n", supported_xcr0);
29 
30     test_bits = XSTATE_FP | XSTATE_SSE;
31     report((supported_xcr0 & test_bits) == test_bits,
32            "Check minimal XSAVE required bits");
33 
34     cr4 = read_cr4();
35     report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == 0, "Set CR4 OSXSAVE");
36     report(this_cpu_has(X86_FEATURE_OSXSAVE),
37            "Check CPUID.1.ECX.OSXSAVE - expect 1");
38 
39     printf("\tLegal tests\n");
40     test_bits = XSTATE_FP;
41     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0,
42            "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP)");
43 
44     test_bits = XSTATE_FP | XSTATE_SSE;
45     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == 0,
46            "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE)");
47     report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == 0,
48            "        xgetbv(XCR_XFEATURE_ENABLED_MASK)");
49 
50     printf("\tIllegal tests\n");
51     test_bits = 0;
52     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR,
53            "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, 0) - expect #GP");
54 
55     test_bits = XSTATE_SSE;
56     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR,
57            "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_SSE) - expect #GP");
58 
59     if (supported_xcr0 & XSTATE_YMM) {
60         test_bits = XSTATE_YMM;
61         report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR,
62                "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_YMM) - expect #GP");
63 
64         test_bits = XSTATE_FP | XSTATE_YMM;
65         report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == GP_VECTOR,
66                "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_YMM) - expect #GP");
67     }
68 
69     test_bits = XSTATE_SSE;
70     report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR,
71            "\t\txsetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP");
72 
73     test_bits = XSTATE_SSE;
74     report(xsetbv_safe(XCR_XFEATURE_ILLEGAL_MASK, test_bits) == GP_VECTOR,
75            "\t\txgetbv(XCR_XFEATURE_ILLEGAL_MASK, XSTATE_FP) - expect #GP");
76 
77     cr4 &= ~X86_CR4_OSXSAVE;
78     report(write_cr4_safe(cr4) == 0, "Unset CR4 OSXSAVE");
79     report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0,
80            "Check CPUID.1.ECX.OSXSAVE - expect 0");
81 
82     printf("\tIllegal tests:\n");
83     test_bits = XSTATE_FP;
84     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR,
85            "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP) - expect #UD");
86 
87     test_bits = XSTATE_FP | XSTATE_SSE;
88     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, test_bits) == UD_VECTOR,
89            "\t\txsetbv(XCR_XFEATURE_ENABLED_MASK, XSTATE_FP | XSTATE_SSE) - expect #UD");
90 
91     printf("\tIllegal tests:\n");
92     report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR,
93            "\txgetbv(XCR_XFEATURE_ENABLED_MASK) - expect #UD");
94 }
95 
96 static void test_no_xsave(void)
97 {
98     unsigned long cr4;
99     u64 xcr0;
100 
101     report(this_cpu_has(X86_FEATURE_OSXSAVE) == 0,
102            "Check CPUID.1.ECX.OSXSAVE - expect 0");
103 
104     printf("Illegal instruction testing:\n");
105 
106     cr4 = read_cr4();
107     report(write_cr4_safe(cr4 | X86_CR4_OSXSAVE) == GP_VECTOR,
108            "Set OSXSAVE in CR4 - expect #GP");
109 
110     report(xgetbv_safe(XCR_XFEATURE_ENABLED_MASK, &xcr0) == UD_VECTOR,
111            "Execute xgetbv - expect #UD");
112 
113     report(xsetbv_safe(XCR_XFEATURE_ENABLED_MASK, 0x3) == UD_VECTOR,
114            "Execute xsetbv - expect #UD");
115 }
116 
117 int main(void)
118 {
119     if (this_cpu_has(X86_FEATURE_XSAVE)) {
120         printf("CPU has XSAVE feature\n");
121         test_xsave();
122     } else {
123         printf("CPU don't has XSAVE feature\n");
124         test_no_xsave();
125     }
126     return report_summary();
127 }
128