Xen Test Framework
main.c
Go to the documentation of this file.
1
36#include <xtf.h>
37
38const char test_title[] = "FPU Exception Emulation";
39
40#define CR0_SYM(...) TOK_OR(X86_CR0_, ##__VA_ARGS__)
41#define CR0_MASK CR0_SYM(EM, MP, TS)
42
44{
45 unsigned long cr0;
47};
48
49static unsigned long default_cr0;
50
55static const struct test_cfg x87[] =
56{
57 { CR0_SYM( ), 0 },
58 { CR0_SYM( TS), EXINFO_SYM(NM, 0) },
59 { CR0_SYM( MP ), 0 },
60 { CR0_SYM( MP, TS), EXINFO_SYM(NM, 0) },
61 { CR0_SYM(EM ), EXINFO_SYM(NM, 0) },
62 { CR0_SYM(EM, TS), EXINFO_SYM(NM, 0) },
63 { CR0_SYM(EM, MP ), EXINFO_SYM(NM, 0) },
64 { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
65};
66
68{
69 exinfo_t fault = 0;
70
71 asm volatile ("test %[fep], %[fep];"
72 "jz 1f;"
74 "1: fnop; 2:"
75 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
76 : "+a" (fault)
77 : [fep] "q" (force),
78 [rec] "p" (ex_record_fault_eax));
79
80 return fault;
81}
82
88static const struct test_cfg x87_wait[] =
89{
90 { CR0_SYM( ), 0 },
91 { CR0_SYM( TS), 0 },
92 { CR0_SYM( MP ), 0 },
93 { CR0_SYM( MP, TS), EXINFO_SYM(NM, 0) },
94 { CR0_SYM(EM ), 0 },
95 { CR0_SYM(EM, TS), 0 },
96 { CR0_SYM(EM, MP ), 0 },
97 { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
98};
99
101{
102 exinfo_t fault = 0;
103
104 asm volatile ("test %[fep], %[fep];"
105 "jz 1f;"
107 "1: wait; 2:"
108 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
109 : "+a" (fault)
110 : [fep] "q" (force),
111 [rec] "p" (ex_record_fault_eax));
112
113 return fault;
114}
115
120static const struct test_cfg mmx_sse[] =
121{
122 { CR0_SYM( ), 0 },
123 { CR0_SYM( TS), EXINFO_SYM(NM, 0) },
124 { CR0_SYM( MP ), 0 },
125 { CR0_SYM( MP, TS), EXINFO_SYM(NM, 0) },
126 { CR0_SYM(EM ), EXINFO_SYM(UD, 0) },
127 { CR0_SYM(EM, TS), EXINFO_SYM(UD, 0) },
128 { CR0_SYM(EM, MP ), EXINFO_SYM(UD, 0) },
129 { CR0_SYM(EM, MP, TS), EXINFO_SYM(UD, 0) },
130};
131
133{
134 exinfo_t fault = 0;
135
136 asm volatile ("test %[fep], %[fep];"
137 "jz 1f;"
139 "1: movq %%mm0, %%mm0; 2:"
140 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
141 : "+a" (fault)
142 : [fep] "q" (force),
143 [rec] "p" (ex_record_fault_eax));
144
145 return fault;
146}
147
149{
150 exinfo_t fault = 0;
151
152 asm volatile ("test %[fep], %[fep];"
153 "jz 1f;"
155 "1: movups %%xmm0, %%xmm0; 2:"
156 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
157 : "+a" (fault)
158 : [fep] "q" (force),
159 [rec] "p" (ex_record_fault_eax));
160
161 return fault;
162}
163
168static const struct test_cfg avx[] =
169{
170 { CR0_SYM( ), 0 },
171 { CR0_SYM( TS), EXINFO_SYM(NM, 0) },
172 { CR0_SYM( MP ), 0 },
173 { CR0_SYM( MP, TS), EXINFO_SYM(NM, 0) },
174 { CR0_SYM(EM ), 0 },
175 { CR0_SYM(EM, TS), EXINFO_SYM(NM, 0) },
176 { CR0_SYM(EM, MP ), 0 },
177 { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
178};
179
180static exinfo_t probe_avx(bool force)
181{
182 exinfo_t fault = 0;
183
184 asm volatile ("test %[fep], %[fep];"
185 "jz 1f;"
187 "1: vmovups %%xmm0, %%xmm0; 2:"
188 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
189 : "+a" (fault)
190 : [fep] "q" (force),
191 [rec] "p" (ex_record_fault_eax));
192
193 return fault;
194}
195
196void run_sequence(const struct test_cfg *seq, unsigned int nr,
197 unsigned int (*fn)(bool), bool force, exinfo_t override)
198{
199 unsigned int i;
200
201 for ( i = 0; i < nr; ++i )
202 {
203 const struct test_cfg *t = &seq[i];
204 exinfo_t res, exp = override ?: t->fault;
205
207 res = fn(force);
208
209 if ( res != exp )
210 {
211 char cr0str[12];
212
213 snprintf(cr0str, sizeof(cr0str), "%s%s%s",
214 t->cr0 & X86_CR0_EM ? " EM" : "",
215 t->cr0 & X86_CR0_MP ? " MP" : "",
216 t->cr0 & X86_CR0_TS ? " TS" : "");
217
218 xtf_failure(" Expected %pe, got %pe (cr0:%s)\n",
219 _p(exp), _p(res), cr0str[0] ? cr0str : " - ");
220 }
221 }
222}
223
224void run_tests(bool force)
225{
226 if ( cpu_has_fpu )
227 {
228 printk("Testing%s x87\n", force ? " emulated" : "");
230
231 printk("Testing%s x87 wait\n", force ? " emulated" : "");
233 }
234
235 if ( cpu_has_mmx )
236 {
237 printk("Testing%s MMX\n", force ? " emulated" : "");
239 }
240
241 if ( cpu_has_sse )
242 {
243 unsigned long cr4 = read_cr4();
244
245 printk("Testing%s SSE\n", force ? " emulated" : "");
248 EXINFO_SYM(UD, 0));
249
250 printk("Testing%s SSE (CR4.OSFXSR)\n", force ? " emulated" : "");
253
254 write_cr4(cr4);
255 }
256
257 if ( cpu_has_avx )
258 {
259 unsigned long cr4 = read_cr4();
260 unsigned long xcr0;
261
262 printk("Testing%s AVX\n", force ? " emulated" : "");
265 EXINFO_SYM(UD, 0));
266
267 printk("Testing%s AVX (CR4.OSXSAVE)\n", force ? " emulated" : "");
269 xcr0 = read_xcr0();
270 write_xcr0(xcr0 & ~XSTATE_YMM);
272 EXINFO_SYM(UD, 0));
273
274 printk("Testing%s AVX (CR4.OSXSAVE+XCR0.YMM)\n", force ? " emulated" : "");
277
278 write_xcr0(xcr0);
279 write_cr4(cr4);
280 }
281}
282
283void test_main(void)
284{
286
287 run_tests(false);
288
289 if ( !xtf_has_fep )
290 xtf_skip("FEP support not detected - some tests will be skipped\n");
291 else
292 run_tests(true);
293
295}
296
297/*
298 * Local variables:
299 * mode: C
300 * c-file-style: "BSD"
301 * c-basic-offset: 4
302 * tab-width: 4
303 * indent-tabs-mode: nil
304 * End:
305 */
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
Record the current fault in %eax.
Definition: extable.c:8
#define cpu_has_avx
Definition: cpuid.h:83
#define cpu_has_fpu
Definition: cpuid.h:61
#define cpu_has_sse
Definition: cpuid.h:76
#define cpu_has_mmx
Definition: cpuid.h:73
static void write_xcr0(uint64_t xcr0)
Definition: lib.h:397
static unsigned long read_cr4(void)
Definition: lib.h:252
static void write_cr0(unsigned long cr0)
Definition: lib.h:270
static void write_cr4(unsigned long cr4)
Definition: lib.h:285
static unsigned long read_cr0(void)
Definition: lib.h:225
static uint64_t read_xcr0(void)
Definition: lib.h:392
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use.
Definition: setup.c:276
void printk(const char *fmt,...)
Definition: console.c:134
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:110
const char test_title[]
The title of the test.
Definition: main.c:24
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
unsigned int exinfo_t
Packed exception and error code information.
Definition: exinfo.h:19
static const struct test_cfg avx[]
AVX instructions.
Definition: main.c:168
exinfo_t probe_x87_wait(bool force)
Definition: main.c:100
static unsigned long default_cr0
Definition: main.c:49
#define CR0_MASK
Definition: main.c:41
void run_sequence(const struct test_cfg *seq, unsigned int nr, unsigned int(*fn)(bool), bool force, exinfo_t override)
Definition: main.c:196
void run_tests(bool force)
Definition: main.c:224
static const struct test_cfg mmx_sse[]
MMX and SSE instructions.
Definition: main.c:120
#define CR0_SYM(...)
Definition: main.c:40
exinfo_t probe_mmx(bool force)
Definition: main.c:132
static const struct test_cfg x87[]
x87 coprocessor.
Definition: main.c:55
exinfo_t probe_x87(bool force)
Definition: main.c:67
static exinfo_t probe_avx(bool force)
Definition: main.c:180
static const struct test_cfg x87_wait[]
The x87 wait instruction.
Definition: main.c:88
exinfo_t probe_sse(bool force)
Definition: main.c:148
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
#define ARRAY_SIZE(a)
Definition: lib.h:8
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define X86_CR0_MP
Definition: processor.h:30
#define X86_CR4_OSFXSR
Definition: processor.h:53
#define XSTATE_YMM
Definition: processor.h:72
#define X86_CR0_TS
Definition: processor.h:32
#define X86_CR4_OSXSAVE
Definition: processor.h:60
#define X86_CR0_EM
Definition: processor.h:31
#define XSTATE_SSE
Definition: processor.h:70
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define NULL
Definition: stddef.h:12
int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: stdio.c:3
Definition: main.c:44
exinfo_t fault
Definition: main.c:46
unsigned long cr0
Definition: main.c:45