Commit 3ff0631ed9b993f933c1430c7eae5c8b851bb8d2
1 parent
b1ba6574
added linux < 2.4.21 vm86 bug workaround - added extensive TF flag test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@376 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
93 additions
and
3 deletions
tests/test-i386.c
@@ -13,6 +13,7 @@ | @@ -13,6 +13,7 @@ | ||
13 | 13 | ||
14 | #define TEST_CMOV 0 | 14 | #define TEST_CMOV 0 |
15 | #define TEST_FCOMI 0 | 15 | #define TEST_FCOMI 0 |
16 | +//#define LINUX_VM86_IOPL_FIX | ||
16 | 17 | ||
17 | #define xglue(x, y) x ## y | 18 | #define xglue(x, y) x ## y |
18 | #define glue(x, y) xglue(x, y) | 19 | #define glue(x, y) xglue(x, y) |
@@ -1106,7 +1107,7 @@ void test_vm86(void) | @@ -1106,7 +1107,7 @@ void test_vm86(void) | ||
1106 | switch(VM86_TYPE(ret)) { | 1107 | switch(VM86_TYPE(ret)) { |
1107 | case VM86_INTx: | 1108 | case VM86_INTx: |
1108 | { | 1109 | { |
1109 | - int int_num, ah; | 1110 | + int int_num, ah, v; |
1110 | 1111 | ||
1111 | int_num = VM86_ARG(ret); | 1112 | int_num = VM86_ARG(ret); |
1112 | if (int_num != 0x21) | 1113 | if (int_num != 0x21) |
@@ -1134,8 +1135,12 @@ void test_vm86(void) | @@ -1134,8 +1135,12 @@ void test_vm86(void) | ||
1134 | r->eax = (r->eax & ~0xff) | '$'; | 1135 | r->eax = (r->eax & ~0xff) | '$'; |
1135 | } | 1136 | } |
1136 | break; | 1137 | break; |
1137 | - case 0xff: /* extension: write hex number in edx */ | ||
1138 | - printf("%08x\n", (int)r->edx); | 1138 | + case 0xff: /* extension: write eflags number in edx */ |
1139 | + v = (int)r->edx; | ||
1140 | +#ifndef LINUX_VM86_IOPL_FIX | ||
1141 | + v &= ~0x3000; | ||
1142 | +#endif | ||
1143 | + printf("%08x\n", v); | ||
1139 | break; | 1144 | break; |
1140 | default: | 1145 | default: |
1141 | unknown_int: | 1146 | unknown_int: |
@@ -1356,6 +1361,90 @@ void test_exceptions(void) | @@ -1356,6 +1361,90 @@ void test_exceptions(void) | ||
1356 | printf("val=0x%x\n", val); | 1361 | printf("val=0x%x\n", val); |
1357 | } | 1362 | } |
1358 | 1363 | ||
1364 | +/* specific precise single step test */ | ||
1365 | +void sig_trap_handler(int sig, siginfo_t *info, void *puc) | ||
1366 | +{ | ||
1367 | + struct ucontext *uc = puc; | ||
1368 | + printf("EIP=0x%08x\n", uc->uc_mcontext.gregs[REG_EIP]); | ||
1369 | +} | ||
1370 | + | ||
1371 | +const uint8_t sstep_buf1[4] = { 1, 2, 3, 4}; | ||
1372 | +uint8_t sstep_buf2[4]; | ||
1373 | + | ||
1374 | +void test_single_step(void) | ||
1375 | +{ | ||
1376 | + struct sigaction act; | ||
1377 | + volatile int val; | ||
1378 | + int i; | ||
1379 | + | ||
1380 | + val = 0; | ||
1381 | + act.sa_sigaction = sig_trap_handler; | ||
1382 | + sigemptyset(&act.sa_mask); | ||
1383 | + act.sa_flags = SA_SIGINFO; | ||
1384 | + sigaction(SIGTRAP, &act, NULL); | ||
1385 | + asm volatile ("pushf\n" | ||
1386 | + "orl $0x00100, (%%esp)\n" | ||
1387 | + "popf\n" | ||
1388 | + "movl $0xabcd, %0\n" | ||
1389 | + | ||
1390 | + /* jmp test */ | ||
1391 | + "movl $3, %%ecx\n" | ||
1392 | + "1:\n" | ||
1393 | + "addl $1, %0\n" | ||
1394 | + "decl %%ecx\n" | ||
1395 | + "jnz 1b\n" | ||
1396 | + | ||
1397 | + /* movsb: the single step should stop at each movsb iteration */ | ||
1398 | + "movl $sstep_buf1, %%esi\n" | ||
1399 | + "movl $sstep_buf2, %%edi\n" | ||
1400 | + "movl $0, %%ecx\n" | ||
1401 | + "rep movsb\n" | ||
1402 | + "movl $3, %%ecx\n" | ||
1403 | + "rep movsb\n" | ||
1404 | + "movl $1, %%ecx\n" | ||
1405 | + "rep movsb\n" | ||
1406 | + | ||
1407 | + /* cmpsb: the single step should stop at each cmpsb iteration */ | ||
1408 | + "movl $sstep_buf1, %%esi\n" | ||
1409 | + "movl $sstep_buf2, %%edi\n" | ||
1410 | + "movl $0, %%ecx\n" | ||
1411 | + "rep cmpsb\n" | ||
1412 | + "movl $4, %%ecx\n" | ||
1413 | + "rep cmpsb\n" | ||
1414 | + | ||
1415 | + /* getpid() syscall: single step should skip one | ||
1416 | + instruction */ | ||
1417 | + "movl $20, %%eax\n" | ||
1418 | + "int $0x80\n" | ||
1419 | + "movl $0, %%eax\n" | ||
1420 | + | ||
1421 | + /* when modifying SS, trace is not done on the next | ||
1422 | + instruction */ | ||
1423 | + "movl %%ss, %%ecx\n" | ||
1424 | + "movl %%ecx, %%ss\n" | ||
1425 | + "addl $1, %0\n" | ||
1426 | + "movl $1, %%eax\n" | ||
1427 | + "movl %%ecx, %%ss\n" | ||
1428 | + "jmp 1f\n" | ||
1429 | + "addl $1, %0\n" | ||
1430 | + "1:\n" | ||
1431 | + "movl $1, %%eax\n" | ||
1432 | + "pushl %%ecx\n" | ||
1433 | + "popl %%ss\n" | ||
1434 | + "addl $1, %0\n" | ||
1435 | + "movl $1, %%eax\n" | ||
1436 | + | ||
1437 | + "pushf\n" | ||
1438 | + "andl $~0x00100, (%%esp)\n" | ||
1439 | + "popf\n" | ||
1440 | + : "=m" (val) | ||
1441 | + : | ||
1442 | + : "cc", "memory", "eax", "ecx", "esi", "edi"); | ||
1443 | + printf("val=%d\n", val); | ||
1444 | + for(i = 0; i < 4; i++) | ||
1445 | + printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]); | ||
1446 | +} | ||
1447 | + | ||
1359 | /* self modifying code test */ | 1448 | /* self modifying code test */ |
1360 | uint8_t code[] = { | 1449 | uint8_t code[] = { |
1361 | 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */ | 1450 | 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */ |
@@ -1402,5 +1491,6 @@ int main(int argc, char **argv) | @@ -1402,5 +1491,6 @@ int main(int argc, char **argv) | ||
1402 | test_vm86(); | 1491 | test_vm86(); |
1403 | test_exceptions(); | 1492 | test_exceptions(); |
1404 | test_self_modifying_code(); | 1493 | test_self_modifying_code(); |
1494 | + test_single_step(); | ||
1405 | return 0; | 1495 | return 0; |
1406 | } | 1496 | } |