Revision f419b321 target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
933 | 933 |
} |
934 | 934 |
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); |
935 | 935 |
} |
936 |
#endif |
|
936 | 937 |
|
937 | 938 |
void helper_syscall(int next_eip_addend) |
938 | 939 |
{ |
... | ... | |
942 | 943 |
raise_exception_err(EXCP06_ILLOP, 0); |
943 | 944 |
} |
944 | 945 |
selector = (env->star >> 32) & 0xffff; |
946 |
#ifdef TARGET_X86_64 |
|
945 | 947 |
if (env->hflags & HF_LMA_MASK) { |
946 | 948 |
ECX = env->eip + next_eip_addend; |
947 | 949 |
env->regs[11] = compute_eflags(); |
... | ... | |
962 | 964 |
env->eip = env->lstar; |
963 | 965 |
else |
964 | 966 |
env->eip = env->cstar; |
965 |
} else { |
|
967 |
} else |
|
968 |
#endif |
|
969 |
{ |
|
966 | 970 |
ECX = (uint32_t)(env->eip + next_eip_addend); |
967 | 971 |
|
968 | 972 |
cpu_x86_set_cpl(env, 0); |
... | ... | |
985 | 989 |
{ |
986 | 990 |
int cpl, selector; |
987 | 991 |
|
992 |
if (!(env->efer & MSR_EFER_SCE)) { |
|
993 |
raise_exception_err(EXCP06_ILLOP, 0); |
|
994 |
} |
|
988 | 995 |
cpl = env->hflags & HF_CPL_MASK; |
989 | 996 |
if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) { |
990 | 997 |
raise_exception_err(EXCP0D_GPF, 0); |
991 | 998 |
} |
992 | 999 |
selector = (env->star >> 48) & 0xffff; |
1000 |
#ifdef TARGET_X86_64 |
|
993 | 1001 |
if (env->hflags & HF_LMA_MASK) { |
994 | 1002 |
if (dflag == 2) { |
995 | 1003 |
cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, |
... | ... | |
1015 | 1023 |
load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | |
1016 | 1024 |
IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK); |
1017 | 1025 |
cpu_x86_set_cpl(env, 3); |
1018 |
} else { |
|
1026 |
} else |
|
1027 |
#endif |
|
1028 |
{ |
|
1019 | 1029 |
cpu_x86_load_seg_cache(env, R_CS, selector | 3, |
1020 | 1030 |
0, 0xffffffff, |
1021 | 1031 |
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
... | ... | |
1030 | 1040 |
env->eflags |= IF_MASK; |
1031 | 1041 |
cpu_x86_set_cpl(env, 3); |
1032 | 1042 |
} |
1033 |
} |
|
1043 |
#ifdef USE_KQEMU |
|
1044 |
if (kqemu_is_ok(env)) { |
|
1045 |
if (env->hflags & HF_LMA_MASK) |
|
1046 |
CC_OP = CC_OP_EFLAGS; |
|
1047 |
env->exception_index = -1; |
|
1048 |
cpu_loop_exit(); |
|
1049 |
} |
|
1034 | 1050 |
#endif |
1051 |
} |
|
1035 | 1052 |
|
1036 | 1053 |
/* real mode interrupt */ |
1037 | 1054 |
static void do_interrupt_real(int intno, int is_int, int error_code, |
... | ... | |
1265 | 1282 |
|
1266 | 1283 |
void helper_cpuid(void) |
1267 | 1284 |
{ |
1268 |
switch((uint32_t)EAX) { |
|
1285 |
uint32_t index; |
|
1286 |
index = (uint32_t)EAX; |
|
1287 |
|
|
1288 |
/* test if maximum index reached */ |
|
1289 |
if (index & 0x80000000) { |
|
1290 |
if (index > env->cpuid_xlevel) |
|
1291 |
index = env->cpuid_level; |
|
1292 |
} else { |
|
1293 |
if (index > env->cpuid_level) |
|
1294 |
index = env->cpuid_level; |
|
1295 |
} |
|
1296 |
|
|
1297 |
switch(index) { |
|
1269 | 1298 |
case 0: |
1270 |
EAX = 2; /* max EAX index supported */
|
|
1299 |
EAX = env->cpuid_level;
|
|
1271 | 1300 |
EBX = env->cpuid_vendor1; |
1272 | 1301 |
EDX = env->cpuid_vendor2; |
1273 | 1302 |
ECX = env->cpuid_vendor3; |
... | ... | |
1278 | 1307 |
ECX = env->cpuid_ext_features; |
1279 | 1308 |
EDX = env->cpuid_features; |
1280 | 1309 |
break; |
1281 |
default:
|
|
1310 |
case 2:
|
|
1282 | 1311 |
/* cache info: needed for Pentium Pro compatibility */ |
1283 | 1312 |
EAX = 0x410601; |
1284 | 1313 |
EBX = 0; |
1285 | 1314 |
ECX = 0; |
1286 | 1315 |
EDX = 0; |
1287 | 1316 |
break; |
1288 |
#ifdef TARGET_X86_64 |
|
1289 | 1317 |
case 0x80000000: |
1290 |
EAX = 0x80000008;
|
|
1318 |
EAX = env->cpuid_xlevel;
|
|
1291 | 1319 |
EBX = env->cpuid_vendor1; |
1292 | 1320 |
EDX = env->cpuid_vendor2; |
1293 | 1321 |
ECX = env->cpuid_vendor3; |
... | ... | |
1296 | 1324 |
EAX = env->cpuid_features; |
1297 | 1325 |
EBX = 0; |
1298 | 1326 |
ECX = 0; |
1299 |
/* long mode + syscall/sysret features */ |
|
1300 |
EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11); |
|
1327 |
EDX = env->cpuid_ext2_features; |
|
1328 |
break; |
|
1329 |
case 0x80000002: |
|
1330 |
case 0x80000003: |
|
1331 |
case 0x80000004: |
|
1332 |
EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0]; |
|
1333 |
EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1]; |
|
1334 |
ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2]; |
|
1335 |
EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3]; |
|
1301 | 1336 |
break; |
1302 | 1337 |
case 0x80000008: |
1303 | 1338 |
/* virtual & phys address size in low 2 bytes. */ |
... | ... | |
1306 | 1341 |
ECX = 0; |
1307 | 1342 |
EDX = 0; |
1308 | 1343 |
break; |
1309 |
#endif |
|
1344 |
default: |
|
1345 |
/* reserved values: zero */ |
|
1346 |
EAX = 0; |
|
1347 |
EBX = 0; |
|
1348 |
ECX = 0; |
|
1349 |
EDX = 0; |
|
1350 |
break; |
|
1310 | 1351 |
} |
1311 | 1352 |
} |
1312 | 1353 |
|
... | ... | |
1523 | 1564 |
} |
1524 | 1565 |
|
1525 | 1566 |
/* protected mode jump */ |
1526 |
void helper_ljmp_protected_T0_T1(int next_eip) |
|
1567 |
void helper_ljmp_protected_T0_T1(int next_eip_addend)
|
|
1527 | 1568 |
{ |
1528 | 1569 |
int new_cs, gate_cs, type; |
1529 | 1570 |
uint32_t e1, e2, cpl, dpl, rpl, limit; |
1530 |
target_ulong new_eip; |
|
1571 |
target_ulong new_eip, next_eip;
|
|
1531 | 1572 |
|
1532 | 1573 |
new_cs = T0; |
1533 | 1574 |
new_eip = T1; |
... | ... | |
1573 | 1614 |
case 5: /* task gate */ |
1574 | 1615 |
if (dpl < cpl || dpl < rpl) |
1575 | 1616 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1617 |
next_eip = env->eip + next_eip_addend; |
|
1576 | 1618 |
switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); |
1577 | 1619 |
break; |
1578 | 1620 |
case 4: /* 286 call gate */ |
... | ... | |
1638 | 1680 |
} |
1639 | 1681 |
|
1640 | 1682 |
/* protected mode call */ |
1641 |
void helper_lcall_protected_T0_T1(int shift, int next_eip) |
|
1683 |
void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
|
|
1642 | 1684 |
{ |
1643 | 1685 |
int new_cs, new_eip, new_stack, i; |
1644 | 1686 |
uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; |
1645 | 1687 |
uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask; |
1646 | 1688 |
uint32_t val, limit, old_sp_mask; |
1647 |
target_ulong ssp, old_ssp; |
|
1689 |
target_ulong ssp, old_ssp, next_eip;
|
|
1648 | 1690 |
|
1649 | 1691 |
new_cs = T0; |
1650 | 1692 |
new_eip = T1; |
1693 |
next_eip = env->eip + next_eip_addend; |
|
1651 | 1694 |
#ifdef DEBUG_PCALL |
1652 | 1695 |
if (loglevel & CPU_LOG_PCALL) { |
1653 | 1696 |
fprintf(logfile, "lcall %04x:%08x s=%d\n", |
... | ... | |
1684 | 1727 |
if (!(e2 & DESC_P_MASK)) |
1685 | 1728 |
raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
1686 | 1729 |
|
1687 |
sp = ESP; |
|
1688 |
sp_mask = get_sp_mask(env->segs[R_SS].flags); |
|
1689 |
ssp = env->segs[R_SS].base; |
|
1690 |
if (shift) { |
|
1691 |
PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector); |
|
1692 |
PUSHL(ssp, sp, sp_mask, next_eip); |
|
1693 |
} else { |
|
1694 |
PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector); |
|
1695 |
PUSHW(ssp, sp, sp_mask, next_eip); |
|
1730 |
#ifdef TARGET_X86_64 |
|
1731 |
/* XXX: check 16/32 bit cases in long mode */ |
|
1732 |
if (shift == 2) { |
|
1733 |
target_ulong rsp; |
|
1734 |
/* 64 bit case */ |
|
1735 |
rsp = ESP; |
|
1736 |
PUSHQ(rsp, env->segs[R_CS].selector); |
|
1737 |
PUSHQ(rsp, next_eip); |
|
1738 |
/* from this point, not restartable */ |
|
1739 |
ESP = rsp; |
|
1740 |
cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, |
|
1741 |
get_seg_base(e1, e2), |
|
1742 |
get_seg_limit(e1, e2), e2); |
|
1743 |
EIP = new_eip; |
|
1744 |
} else |
|
1745 |
#endif |
|
1746 |
{ |
|
1747 |
sp = ESP; |
|
1748 |
sp_mask = get_sp_mask(env->segs[R_SS].flags); |
|
1749 |
ssp = env->segs[R_SS].base; |
|
1750 |
if (shift) { |
|
1751 |
PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector); |
|
1752 |
PUSHL(ssp, sp, sp_mask, next_eip); |
|
1753 |
} else { |
|
1754 |
PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector); |
|
1755 |
PUSHW(ssp, sp, sp_mask, next_eip); |
|
1756 |
} |
|
1757 |
|
|
1758 |
limit = get_seg_limit(e1, e2); |
|
1759 |
if (new_eip > limit) |
|
1760 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
|
1761 |
/* from this point, not restartable */ |
|
1762 |
ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
|
1763 |
cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, |
|
1764 |
get_seg_base(e1, e2), limit, e2); |
|
1765 |
EIP = new_eip; |
|
1696 | 1766 |
} |
1697 |
|
|
1698 |
limit = get_seg_limit(e1, e2); |
|
1699 |
if (new_eip > limit) |
|
1700 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
|
1701 |
/* from this point, not restartable */ |
|
1702 |
ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
|
1703 |
cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, |
|
1704 |
get_seg_base(e1, e2), limit, e2); |
|
1705 |
EIP = new_eip; |
|
1706 | 1767 |
} else { |
1707 | 1768 |
/* check gate type */ |
1708 | 1769 |
type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; |
... | ... | |
2245 | 2306 |
case MSR_IA32_APICBASE: |
2246 | 2307 |
cpu_set_apic_base(env, val); |
2247 | 2308 |
break; |
2248 |
#ifdef TARGET_X86_64 |
|
2249 | 2309 |
case MSR_EFER: |
2250 |
#define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \ |
|
2251 |
MSR_EFER_NXE | MSR_EFER_FFXSR) |
|
2252 |
env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) | |
|
2253 |
(val & MSR_EFER_UPDATE_MASK); |
|
2310 |
{ |
|
2311 |
uint64_t update_mask; |
|
2312 |
update_mask = 0; |
|
2313 |
if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL) |
|
2314 |
update_mask |= MSR_EFER_SCE; |
|
2315 |
if (env->cpuid_ext2_features & CPUID_EXT2_LM) |
|
2316 |
update_mask |= MSR_EFER_LME; |
|
2317 |
if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) |
|
2318 |
update_mask |= MSR_EFER_FFXSR; |
|
2319 |
if (env->cpuid_ext2_features & CPUID_EXT2_NX) |
|
2320 |
update_mask |= MSR_EFER_NXE; |
|
2321 |
env->efer = (env->efer & ~update_mask) | |
|
2322 |
(val & update_mask); |
|
2323 |
} |
|
2254 | 2324 |
break; |
2255 | 2325 |
case MSR_STAR: |
2256 | 2326 |
env->star = val; |
2257 | 2327 |
break; |
2328 |
#ifdef TARGET_X86_64 |
|
2258 | 2329 |
case MSR_LSTAR: |
2259 | 2330 |
env->lstar = val; |
2260 | 2331 |
break; |
... | ... | |
2296 | 2367 |
case MSR_IA32_APICBASE: |
2297 | 2368 |
val = cpu_get_apic_base(env); |
2298 | 2369 |
break; |
2299 |
#ifdef TARGET_X86_64 |
|
2300 | 2370 |
case MSR_EFER: |
2301 | 2371 |
val = env->efer; |
2302 | 2372 |
break; |
2303 | 2373 |
case MSR_STAR: |
2304 | 2374 |
val = env->star; |
2305 | 2375 |
break; |
2376 |
#ifdef TARGET_X86_64 |
|
2306 | 2377 |
case MSR_LSTAR: |
2307 | 2378 |
val = env->lstar; |
2308 | 2379 |
break; |
Also available in: Unified diff