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