ia64/xen-unstable

view tools/tests/test_x86_emulator.c @ 13425:e079f1ff6744

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