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