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
test_xsave(void)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
test_no_xsave(void)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
main(void)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