Commit f3f2d9be03816c991fff05ba30e6d9490005d282
1 parent
77729c24
call gate fix - verr and verw fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@459 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
43 additions
and
5 deletions
target-i386/helper.c
... | ... | @@ -19,6 +19,8 @@ |
19 | 19 | */ |
20 | 20 | #include "exec.h" |
21 | 21 | |
22 | +//#define DEBUG_PCALL | |
23 | + | |
22 | 24 | const uint8_t parity_table[256] = { |
23 | 25 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
24 | 26 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
... | ... | @@ -540,6 +542,27 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
540 | 542 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
541 | 543 | uint32_t old_cs, old_ss, old_esp, old_eip; |
542 | 544 | |
545 | +#ifdef DEBUG_PCALL | |
546 | + if (loglevel) { | |
547 | + static int count; | |
548 | + fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d CS:IP=%04x:%08x CPL=%d\n", | |
549 | + count, intno, error_code, is_int, env->segs[R_CS].selector, env->eip, env->hflags & 3); | |
550 | +#if 0 | |
551 | + { | |
552 | + int i; | |
553 | + uint8_t *ptr; | |
554 | + printf(" code="); | |
555 | + ptr = env->segs[R_CS].base + env->eip; | |
556 | + for(i = 0; i < 16; i++) { | |
557 | + printf(" %02x", ldub(ptr + i)); | |
558 | + } | |
559 | + printf("\n"); | |
560 | + } | |
561 | +#endif | |
562 | + count++; | |
563 | + } | |
564 | +#endif | |
565 | + | |
543 | 566 | has_error_code = 0; |
544 | 567 | if (!is_int && !is_hw) { |
545 | 568 | switch(intno) { |
... | ... | @@ -1260,11 +1283,22 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1260 | 1283 | |
1261 | 1284 | new_cs = T0; |
1262 | 1285 | new_eip = T1; |
1286 | +#ifdef DEBUG_PCALL | |
1287 | + if (loglevel) { | |
1288 | + fprintf(logfile, "lcall %04x:%08x\n", | |
1289 | + new_cs, new_eip); | |
1290 | + } | |
1291 | +#endif | |
1263 | 1292 | if ((new_cs & 0xfffc) == 0) |
1264 | 1293 | raise_exception_err(EXCP0D_GPF, 0); |
1265 | 1294 | if (load_segment(&e1, &e2, new_cs) != 0) |
1266 | 1295 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1267 | 1296 | cpl = env->hflags & HF_CPL_MASK; |
1297 | +#ifdef DEBUG_PCALL | |
1298 | + if (loglevel) { | |
1299 | + fprintf(logfile, "desc=%08x:%08x\n", e1, e2); | |
1300 | + } | |
1301 | +#endif | |
1268 | 1302 | if (e2 & DESC_S_MASK) { |
1269 | 1303 | if (!(e2 & DESC_CS_MASK)) |
1270 | 1304 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
... | ... | @@ -1341,6 +1375,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1341 | 1375 | raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
1342 | 1376 | selector = e1 >> 16; |
1343 | 1377 | offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); |
1378 | + param_count = e2 & 0x1f; | |
1344 | 1379 | if ((selector & 0xfffc) == 0) |
1345 | 1380 | raise_exception_err(EXCP0D_GPF, 0); |
1346 | 1381 | |
... | ... | @@ -1357,6 +1392,11 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1357 | 1392 | if (!(e2 & DESC_C_MASK) && dpl < cpl) { |
1358 | 1393 | /* to inner priviledge */ |
1359 | 1394 | get_ss_esp_from_tss(&ss, &sp, dpl); |
1395 | +#ifdef DEBUG_PCALL | |
1396 | + if (loglevel) | |
1397 | + fprintf(logfile, "ss=%04x sp=%04x param_count=%d ESP=%x\n", | |
1398 | + ss, sp, param_count, ESP); | |
1399 | +#endif | |
1360 | 1400 | if ((ss & 0xfffc) == 0) |
1361 | 1401 | raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
1362 | 1402 | if ((ss & 3) != dpl) |
... | ... | @@ -1373,7 +1413,6 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1373 | 1413 | if (!(ss_e2 & DESC_P_MASK)) |
1374 | 1414 | raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
1375 | 1415 | |
1376 | - param_count = e2 & 0x1f; | |
1377 | 1416 | push_size = ((param_count * 2) + 8) << shift; |
1378 | 1417 | |
1379 | 1418 | old_esp = ESP; |
... | ... | @@ -1389,7 +1428,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1389 | 1428 | get_seg_limit(ss_e1, ss_e2), |
1390 | 1429 | ss_e2); |
1391 | 1430 | |
1392 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | |
1431 | + if (!(ss_e2 & DESC_B_MASK)) | |
1393 | 1432 | sp &= 0xffff; |
1394 | 1433 | ssp = env->segs[R_SS].base + sp; |
1395 | 1434 | if (shift) { |
... | ... | @@ -1441,7 +1480,6 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1441 | 1480 | e2); |
1442 | 1481 | cpu_x86_set_cpl(env, dpl); |
1443 | 1482 | |
1444 | - /* from this point, not restartable if same priviledge */ | |
1445 | 1483 | if (!(env->segs[R_SS].flags & DESC_B_MASK)) |
1446 | 1484 | ESP = (ESP & 0xffff0000) | (sp & 0xffff); |
1447 | 1485 | else |
... | ... | @@ -1838,7 +1876,7 @@ void helper_verr(void) |
1838 | 1876 | if (dpl < cpl || dpl < rpl) |
1839 | 1877 | return; |
1840 | 1878 | } |
1841 | - /* ok */ | |
1879 | + CC_SRC |= CC_Z; | |
1842 | 1880 | } |
1843 | 1881 | |
1844 | 1882 | void helper_verw(void) |
... | ... | @@ -1866,7 +1904,7 @@ void helper_verw(void) |
1866 | 1904 | if (!(e2 & DESC_W_MASK)) |
1867 | 1905 | return; |
1868 | 1906 | } |
1869 | - /* ok */ | |
1907 | + CC_SRC |= CC_Z; | |
1870 | 1908 | } |
1871 | 1909 | |
1872 | 1910 | /* FPU helpers */ | ... | ... |