ia64/xen-unstable

view tools/tests/test_x86_emulator.c @ 19615:13a4f4e6d0a3

x86 hvm: Correctly emulate task switches into vm86 mode.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 19 02:12:04 2009 +0100 (2009-05-19)
parents c33a40b4c22b
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <public/xen.h>
6 #include <sys/mman.h>
8 #include "x86_emulate/x86_emulate.h"
9 #include "blowfish.h"
11 #define MMAP_SZ 16384
13 /* EFLAGS bit definitions. */
14 #define EFLG_OF (1<<11)
15 #define EFLG_DF (1<<10)
16 #define EFLG_SF (1<<7)
17 #define EFLG_ZF (1<<6)
18 #define EFLG_AF (1<<4)
19 #define EFLG_PF (1<<2)
20 #define EFLG_CF (1<<0)
22 static int read(
23 unsigned int seg,
24 unsigned long offset,
25 void *p_data,
26 unsigned int bytes,
27 struct x86_emulate_ctxt *ctxt)
28 {
29 memcpy(p_data, (void *)offset, bytes);
30 return X86EMUL_OKAY;
31 }
33 static int write(
34 unsigned int seg,
35 unsigned long offset,
36 void *p_data,
37 unsigned int bytes,
38 struct x86_emulate_ctxt *ctxt)
39 {
40 memcpy((void *)offset, p_data, bytes);
41 return X86EMUL_OKAY;
42 }
44 static int cmpxchg(
45 unsigned int seg,
46 unsigned long offset,
47 void *old,
48 void *new,
49 unsigned int bytes,
50 struct x86_emulate_ctxt *ctxt)
51 {
52 memcpy((void *)offset, new, bytes);
53 return X86EMUL_OKAY;
54 }
56 static struct x86_emulate_ops emulops = {
57 .read = read,
58 .insn_fetch = read,
59 .write = write,
60 .cmpxchg = cmpxchg,
61 };
63 int main(int argc, char **argv)
64 {
65 struct x86_emulate_ctxt ctxt;
66 struct cpu_user_regs regs;
67 char *instr;
68 unsigned int *res, i;
69 int rc;
70 #ifndef __x86_64__
71 unsigned int bcdres_native, bcdres_emul;
72 #endif
74 ctxt.regs = &regs;
75 ctxt.force_writeback = 0;
76 ctxt.addr_size = 32;
77 ctxt.sp_size = 32;
79 res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE,
80 MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
81 if ( res == MAP_FAILED )
82 {
83 fprintf(stderr, "mmap to low address failed\n");
84 exit(1);
85 }
86 instr = (char *)res + 0x100;
88 printf("%-40s", "Testing addl %%ecx,(%%eax)...");
89 instr[0] = 0x01; instr[1] = 0x08;
90 regs.eflags = 0x200;
91 regs.eip = (unsigned long)&instr[0];
92 regs.ecx = 0x12345678;
93 regs.eax = (unsigned long)res;
94 *res = 0x7FFFFFFF;
95 rc = x86_emulate(&ctxt, &emulops);
96 if ( (rc != X86EMUL_OKAY) ||
97 (*res != 0x92345677) ||
98 (regs.eflags != 0xa94) ||
99 (regs.eip != (unsigned long)&instr[2]) )
100 goto fail;
101 printf("okay\n");
103 printf("%-40s", "Testing addl %%ecx,%%eax...");
104 instr[0] = 0x01; instr[1] = 0xc8;
105 regs.eflags = 0x200;
106 regs.eip = (unsigned long)&instr[0];
107 regs.ecx = 0x12345678;
108 regs.eax = 0x7FFFFFFF;
109 rc = x86_emulate(&ctxt, &emulops);
110 if ( (rc != X86EMUL_OKAY) ||
111 (regs.ecx != 0x12345678) ||
112 (regs.eax != 0x92345677) ||
113 (regs.eflags != 0xa94) ||
114 (regs.eip != (unsigned long)&instr[2]) )
115 goto fail;
116 printf("okay\n");
118 printf("%-40s", "Testing xorl (%%eax),%%ecx...");
119 instr[0] = 0x33; instr[1] = 0x08;
120 regs.eflags = 0x200;
121 regs.eip = (unsigned long)&instr[0];
122 #ifdef __x86_64__
123 regs.ecx = 0xFFFFFFFF12345678UL;
124 #else
125 regs.ecx = 0x12345678UL;
126 #endif
127 regs.eax = (unsigned long)res;
128 rc = x86_emulate(&ctxt, &emulops);
129 if ( (rc != X86EMUL_OKAY) ||
130 (*res != 0x92345677) ||
131 (regs.ecx != 0x8000000FUL) ||
132 (regs.eip != (unsigned long)&instr[2]) )
133 goto fail;
134 printf("okay\n");
136 printf("%-40s", "Testing movl (%%eax),%%ecx...");
137 instr[0] = 0x8b; instr[1] = 0x08;
138 regs.eflags = 0x200;
139 regs.eip = (unsigned long)&instr[0];
140 regs.ecx = ~0UL;
141 regs.eax = (unsigned long)res;
142 rc = x86_emulate(&ctxt, &emulops);
143 if ( (rc != X86EMUL_OKAY) ||
144 (*res != 0x92345677) ||
145 (regs.ecx != 0x92345677UL) ||
146 (regs.eip != (unsigned long)&instr[2]) )
147 goto fail;
148 printf("okay\n");
150 printf("%-40s", "Testing lock cmpxchgb %%cl,(%%ebx)...");
151 instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x0b;
152 regs.eflags = 0x200;
153 regs.eip = (unsigned long)&instr[0];
154 regs.eax = 0x92345677UL;
155 regs.ecx = 0xAA;
156 regs.ebx = (unsigned long)res;
157 rc = x86_emulate(&ctxt, &emulops);
158 if ( (rc != X86EMUL_OKAY) ||
159 (*res != 0x923456AA) ||
160 (regs.eflags != 0x244) ||
161 (regs.eax != 0x92345677UL) ||
162 (regs.eip != (unsigned long)&instr[4]) )
163 goto fail;
164 printf("okay\n");
166 printf("%-40s", "Testing lock cmpxchgb %%cl,(%%ebx)...");
167 instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x0b;
168 regs.eflags = 0x200;
169 regs.eip = (unsigned long)&instr[0];
170 regs.eax = 0xAABBCC77UL;
171 regs.ecx = 0xFF;
172 regs.ebx = (unsigned long)res;
173 rc = x86_emulate(&ctxt, &emulops);
174 if ( (rc != X86EMUL_OKAY) ||
175 (*res != 0x923456AA) ||
176 ((regs.eflags&0x240) != 0x200) ||
177 (regs.eax != 0xAABBCCAA) ||
178 (regs.ecx != 0xFF) ||
179 (regs.eip != (unsigned long)&instr[4]) )
180 goto fail;
181 printf("okay\n");
183 printf("%-40s", "Testing xchgl %%ecx,(%%eax)...");
184 instr[0] = 0x87; instr[1] = 0x08;
185 regs.eflags = 0x200;
186 regs.eip = (unsigned long)&instr[0];
187 regs.ecx = 0x12345678;
188 regs.eax = (unsigned long)res;
189 rc = x86_emulate(&ctxt, &emulops);
190 if ( (rc != X86EMUL_OKAY) ||
191 (*res != 0x12345678) ||
192 (regs.eflags != 0x200) ||
193 (regs.ecx != 0x923456AA) ||
194 (regs.eip != (unsigned long)&instr[2]) )
195 goto fail;
196 printf("okay\n");
198 printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%ebx)...");
199 instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x0b;
200 regs.eflags = 0x200;
201 *res = 0x923456AA;
202 regs.eip = (unsigned long)&instr[0];
203 regs.eax = 0x923456AAUL;
204 regs.ecx = 0xDDEEFF00L;
205 regs.ebx = (unsigned long)res;
206 rc = x86_emulate(&ctxt, &emulops);
207 if ( (rc != X86EMUL_OKAY) ||
208 (*res != 0xDDEEFF00) ||
209 (regs.eflags != 0x244) ||
210 (regs.eax != 0x923456AAUL) ||
211 (regs.eip != (unsigned long)&instr[4]) )
212 goto fail;
213 printf("okay\n");
215 printf("%-40s", "Testing rep movsw...");
216 instr[0] = 0xf3; instr[1] = 0x66; instr[2] = 0xa5;
217 *res = 0x22334455;
218 regs.eflags = 0x200;
219 regs.ecx = 23;
220 regs.eip = (unsigned long)&instr[0];
221 regs.esi = (unsigned long)res + 0;
222 regs.edi = (unsigned long)res + 2;
223 rc = x86_emulate(&ctxt, &emulops);
224 if ( (rc != X86EMUL_OKAY) ||
225 (*res != 0x44554455) ||
226 (regs.eflags != 0x200) ||
227 (regs.ecx != 22) ||
228 (regs.esi != ((unsigned long)res + 2)) ||
229 (regs.edi != ((unsigned long)res + 4)) ||
230 (regs.eip != (unsigned long)&instr[0]) )
231 goto fail;
232 printf("okay\n");
234 printf("%-40s", "Testing btrl $0x1,(%edi)...");
235 instr[0] = 0x0f; instr[1] = 0xba; instr[2] = 0x37; instr[3] = 0x01;
236 *res = 0x2233445F;
237 regs.eflags = 0x200;
238 regs.eip = (unsigned long)&instr[0];
239 regs.edi = (unsigned long)res;
240 rc = x86_emulate(&ctxt, &emulops);
241 if ( (rc != X86EMUL_OKAY) ||
242 (*res != 0x2233445D) ||
243 ((regs.eflags&0x201) != 0x201) ||
244 (regs.eip != (unsigned long)&instr[4]) )
245 goto fail;
246 printf("okay\n");
248 printf("%-40s", "Testing btrl %eax,(%edi)...");
249 instr[0] = 0x0f; instr[1] = 0xb3; instr[2] = 0x07;
250 *res = 0x2233445F;
251 regs.eflags = 0x200;
252 regs.eip = (unsigned long)&instr[0];
253 regs.eax = -32;
254 regs.edi = (unsigned long)(res+1);
255 rc = x86_emulate(&ctxt, &emulops);
256 if ( (rc != X86EMUL_OKAY) ||
257 (*res != 0x2233445E) ||
258 ((regs.eflags&0x201) != 0x201) ||
259 (regs.eip != (unsigned long)&instr[3]) )
260 goto fail;
261 printf("okay\n");
263 res[0] = 0x12345678;
264 res[1] = 0x87654321;
266 printf("%-40s", "Testing cmpxchg8b (%edi) [succeeding]...");
267 instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
268 regs.eflags = 0x200;
269 regs.eax = res[0];
270 regs.edx = res[1];
271 regs.ebx = 0x9999AAAA;
272 regs.ecx = 0xCCCCFFFF;
273 regs.eip = (unsigned long)&instr[0];
274 regs.edi = (unsigned long)res;
275 rc = x86_emulate(&ctxt, &emulops);
276 if ( (rc != X86EMUL_OKAY) ||
277 (res[0] != 0x9999AAAA) ||
278 (res[1] != 0xCCCCFFFF) ||
279 ((regs.eflags&0x240) != 0x240) ||
280 (regs.eip != (unsigned long)&instr[3]) )
281 goto fail;
282 printf("okay\n");
284 printf("%-40s", "Testing cmpxchg8b (%edi) [failing]...");
285 instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
286 regs.eflags = 0x200;
287 regs.eip = (unsigned long)&instr[0];
288 regs.edi = (unsigned long)res;
289 rc = x86_emulate(&ctxt, &emulops);
290 if ( (rc != X86EMUL_OKAY) ||
291 (res[0] != 0x9999AAAA) ||
292 (res[1] != 0xCCCCFFFF) ||
293 (regs.eax != 0x9999AAAA) ||
294 (regs.edx != 0xCCCCFFFF) ||
295 ((regs.eflags&0x240) != 0x200) ||
296 (regs.eip != (unsigned long)&instr[3]) )
297 goto fail;
298 printf("okay\n");
300 printf("%-40s", "Testing movsxbd (%%eax),%%ecx...");
301 instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08;
302 regs.eflags = 0x200;
303 regs.eip = (unsigned long)&instr[0];
304 regs.ecx = 0x12345678;
305 regs.eax = (unsigned long)res;
306 *res = 0x82;
307 rc = x86_emulate(&ctxt, &emulops);
308 if ( (rc != X86EMUL_OKAY) ||
309 (*res != 0x82) ||
310 (regs.ecx != 0xFFFFFF82) ||
311 ((regs.eflags&0x240) != 0x200) ||
312 (regs.eip != (unsigned long)&instr[3]) )
313 goto fail;
314 printf("okay\n");
316 printf("%-40s", "Testing movzxwd (%%eax),%%ecx...");
317 instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08;
318 regs.eflags = 0x200;
319 regs.eip = (unsigned long)&instr[0];
320 regs.ecx = 0x12345678;
321 regs.eax = (unsigned long)res;
322 *res = 0x1234aa82;
323 rc = x86_emulate(&ctxt, &emulops);
324 if ( (rc != X86EMUL_OKAY) ||
325 (*res != 0x1234aa82) ||
326 (regs.ecx != 0xaa82) ||
327 ((regs.eflags&0x240) != 0x200) ||
328 (regs.eip != (unsigned long)&instr[3]) )
329 goto fail;
330 printf("okay\n");
332 printf("%-40s", "Testing xadd %%ax,(%%ecx)...");
333 instr[0] = 0x66; instr[1] = 0x0f; instr[2] = 0xc1; instr[3] = 0x01;
334 regs.eflags = 0x200;
335 regs.eip = (unsigned long)&instr[0];
336 regs.ecx = (unsigned long)res;
337 regs.eax = 0x12345678;
338 *res = 0x11111111;
339 rc = x86_emulate(&ctxt, &emulops);
340 if ( (rc != X86EMUL_OKAY) ||
341 (*res != 0x11116789) ||
342 (regs.eax != 0x12341111) ||
343 ((regs.eflags&0x240) != 0x200) ||
344 (regs.eip != (unsigned long)&instr[4]) )
345 goto fail;
346 printf("okay\n");
348 printf("%-40s", "Testing dec %%ax...");
349 instr[0] = 0x66; instr[1] = 0x48;
350 regs.eflags = 0x200;
351 regs.eip = (unsigned long)&instr[0];
352 regs.eax = 0x00000000;
353 rc = x86_emulate(&ctxt, &emulops);
354 if ( (rc != X86EMUL_OKAY) ||
355 (regs.eax != 0x0000ffff) ||
356 ((regs.eflags&0x240) != 0x200) ||
357 (regs.eip != (unsigned long)&instr[2]) )
358 goto fail;
359 printf("okay\n");
361 printf("%-40s", "Testing lea 8(%%ebp),%%eax...");
362 instr[0] = 0x8d; instr[1] = 0x45; instr[2] = 0x08;
363 regs.eflags = 0x200;
364 regs.eip = (unsigned long)&instr[0];
365 regs.eax = 0x12345678;
366 regs.ebp = 0xaaaaaaaa;
367 rc = x86_emulate(&ctxt, &emulops);
368 if ( (rc != X86EMUL_OKAY) ||
369 (regs.eax != 0xaaaaaab2) ||
370 ((regs.eflags&0x240) != 0x200) ||
371 (regs.eip != (unsigned long)&instr[3]) )
372 goto fail;
373 printf("okay\n");
375 printf("%-40s", "Testing daa/das (all inputs)...");
376 #ifndef __x86_64__
377 /* Bits 0-7: AL; Bit 8: EFLG_AF; Bit 9: EFLG_CF; Bit 10: DAA vs. DAS. */
378 for ( i = 0; i < 0x800; i++ )
379 {
380 regs.eflags = (i & 0x200) ? EFLG_CF : 0;
381 regs.eflags |= (i & 0x100) ? EFLG_AF : 0;
382 if ( i & 0x400 )
383 __asm__ (
384 "pushf; and $0xffffffee,(%%esp); or %1,(%%esp); popf; das; "
385 "pushf; popl %1"
386 : "=a" (bcdres_native), "=r" (regs.eflags)
387 : "0" (i & 0xff), "1" (regs.eflags) );
388 else
389 __asm__ (
390 "pushf; and $0xffffffee,(%%esp); or %1,(%%esp); popf; daa; "
391 "pushf; popl %1"
392 : "=a" (bcdres_native), "=r" (regs.eflags)
393 : "0" (i & 0xff), "1" (regs.eflags) );
394 bcdres_native |= (regs.eflags & EFLG_PF) ? 0x1000 : 0;
395 bcdres_native |= (regs.eflags & EFLG_ZF) ? 0x800 : 0;
396 bcdres_native |= (regs.eflags & EFLG_SF) ? 0x400 : 0;
397 bcdres_native |= (regs.eflags & EFLG_CF) ? 0x200 : 0;
398 bcdres_native |= (regs.eflags & EFLG_AF) ? 0x100 : 0;
400 instr[0] = (i & 0x400) ? 0x2f: 0x27; /* daa/das */
401 regs.eflags = (i & 0x200) ? EFLG_CF : 0;
402 regs.eflags |= (i & 0x100) ? EFLG_AF : 0;
403 regs.eip = (unsigned long)&instr[0];
404 regs.eax = (unsigned char)i;
405 rc = x86_emulate(&ctxt, &emulops);
406 bcdres_emul = regs.eax;
407 bcdres_emul |= (regs.eflags & EFLG_PF) ? 0x1000 : 0;
408 bcdres_emul |= (regs.eflags & EFLG_ZF) ? 0x800 : 0;
409 bcdres_emul |= (regs.eflags & EFLG_SF) ? 0x400 : 0;
410 bcdres_emul |= (regs.eflags & EFLG_CF) ? 0x200 : 0;
411 bcdres_emul |= (regs.eflags & EFLG_AF) ? 0x100 : 0;
412 if ( (rc != X86EMUL_OKAY) || (regs.eax > 255) ||
413 (regs.eip != (unsigned long)&instr[1]) )
414 goto fail;
416 if ( bcdres_emul != bcdres_native )
417 {
418 printf("%s: AL=%02x %s %s\n"
419 "Output: AL=%02x %s %s %s %s %s\n"
420 "Emul.: AL=%02x %s %s %s %s %s\n",
421 (i & 0x400) ? "DAS" : "DAA",
422 (unsigned char)i,
423 (i & 0x200) ? "CF" : " ",
424 (i & 0x100) ? "AF" : " ",
425 (unsigned char)bcdres_native,
426 (bcdres_native & 0x200) ? "CF" : " ",
427 (bcdres_native & 0x100) ? "AF" : " ",
428 (bcdres_native & 0x1000) ? "PF" : " ",
429 (bcdres_native & 0x800) ? "ZF" : " ",
430 (bcdres_native & 0x400) ? "SF" : " ",
431 (unsigned char)bcdres_emul,
432 (bcdres_emul & 0x200) ? "CF" : " ",
433 (bcdres_emul & 0x100) ? "AF" : " ",
434 (bcdres_emul & 0x1000) ? "PF" : " ",
435 (bcdres_emul & 0x800) ? "ZF" : " ",
436 (bcdres_emul & 0x400) ? "SF" : " ");
437 goto fail;
438 }
439 }
440 printf("okay\n");
441 #else
442 printf("skipped\n");
443 #endif
445 printf("Testing blowfish code sequence");
446 memcpy(res, blowfish_code, sizeof(blowfish_code));
447 regs.eax = 2;
448 regs.edx = 1;
449 regs.eip = (unsigned long)res;
450 regs.esp = (unsigned long)res + MMAP_SZ - 4;
451 *(uint32_t *)(unsigned long)regs.esp = 0x12345678;
452 regs.eflags = 2;
453 i = 0;
454 while ( (uint32_t)regs.eip != 0x12345678 )
455 {
456 if ( (i++ & 8191) == 0 )
457 printf(".");
458 rc = x86_emulate(&ctxt, &emulops);
459 if ( rc != X86EMUL_OKAY )
460 {
461 printf("failed at %%eip == %08x\n", (unsigned int)regs.eip);
462 return 1;
463 }
464 }
465 if ( (regs.esp != ((unsigned long)res + MMAP_SZ)) ||
466 (regs.eax != 2) || (regs.edx != 1) )
467 goto fail;
468 printf("okay\n");
470 #ifndef __x86_64__
471 printf("%-40s", "Testing blowfish native execution...");
472 asm volatile (
473 "movl $0x100000,%%ecx; call *%%ecx"
474 : "=a" (regs.eax), "=d" (regs.edx)
475 : "0" (2), "1" (1) : "ecx" );
476 if ( (regs.eax != 2) || (regs.edx != 1) )
477 goto fail;
478 printf("okay\n");
479 #endif
481 return 0;
483 fail:
484 printf("failed!\n");
485 return 1;
486 }