933 |
} |
} |
934 |
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); |
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); |
935 |
} |
} |
936 |
|
#endif |
937 |
|
|
938 |
void helper_syscall(int next_eip_addend) |
void helper_syscall(int next_eip_addend) |
939 |
{ |
{ |
943 |
raise_exception_err(EXCP06_ILLOP, 0); |
raise_exception_err(EXCP06_ILLOP, 0); |
944 |
} |
} |
945 |
selector = (env->star >> 32) & 0xffff; |
selector = (env->star >> 32) & 0xffff; |
946 |
|
#ifdef TARGET_X86_64 |
947 |
if (env->hflags & HF_LMA_MASK) { |
if (env->hflags & HF_LMA_MASK) { |
948 |
ECX = env->eip + next_eip_addend; |
ECX = env->eip + next_eip_addend; |
949 |
env->regs[11] = compute_eflags(); |
env->regs[11] = compute_eflags(); |
964 |
env->eip = env->lstar; |
env->eip = env->lstar; |
965 |
else |
else |
966 |
env->eip = env->cstar; |
env->eip = env->cstar; |
967 |
} else { |
} else |
968 |
|
#endif |
969 |
|
{ |
970 |
ECX = (uint32_t)(env->eip + next_eip_addend); |
ECX = (uint32_t)(env->eip + next_eip_addend); |
971 |
|
|
972 |
cpu_x86_set_cpl(env, 0); |
cpu_x86_set_cpl(env, 0); |
989 |
{ |
{ |
990 |
int cpl, selector; |
int cpl, selector; |
991 |
|
|
992 |
|
if (!(env->efer & MSR_EFER_SCE)) { |
993 |
|
raise_exception_err(EXCP06_ILLOP, 0); |
994 |
|
} |
995 |
cpl = env->hflags & HF_CPL_MASK; |
cpl = env->hflags & HF_CPL_MASK; |
996 |
if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) { |
if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) { |
997 |
raise_exception_err(EXCP0D_GPF, 0); |
raise_exception_err(EXCP0D_GPF, 0); |
998 |
} |
} |
999 |
selector = (env->star >> 48) & 0xffff; |
selector = (env->star >> 48) & 0xffff; |
1000 |
|
#ifdef TARGET_X86_64 |
1001 |
if (env->hflags & HF_LMA_MASK) { |
if (env->hflags & HF_LMA_MASK) { |
1002 |
if (dflag == 2) { |
if (dflag == 2) { |
1003 |
cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, |
cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, |
1023 |
load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | |
load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | |
1024 |
IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK); |
IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK); |
1025 |
cpu_x86_set_cpl(env, 3); |
cpu_x86_set_cpl(env, 3); |
1026 |
} else { |
} else |
1027 |
|
#endif |
1028 |
|
{ |
1029 |
cpu_x86_load_seg_cache(env, R_CS, selector | 3, |
cpu_x86_load_seg_cache(env, R_CS, selector | 3, |
1030 |
0, 0xffffffff, |
0, 0xffffffff, |
1031 |
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
1040 |
env->eflags |= IF_MASK; |
env->eflags |= IF_MASK; |
1041 |
cpu_x86_set_cpl(env, 3); |
cpu_x86_set_cpl(env, 3); |
1042 |
} |
} |
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 |
|
} |
1050 |
#endif |
#endif |
1051 |
|
} |
1052 |
|
|
1053 |
/* real mode interrupt */ |
/* real mode interrupt */ |
1054 |
static void do_interrupt_real(int intno, int is_int, int error_code, |
static void do_interrupt_real(int intno, int is_int, int error_code, |
1282 |
|
|
1283 |
void helper_cpuid(void) |
void helper_cpuid(void) |
1284 |
{ |
{ |
1285 |
switch((uint32_t)EAX) { |
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) { |
1298 |
case 0: |
case 0: |
1299 |
EAX = 2; /* max EAX index supported */ |
EAX = env->cpuid_level; |
1300 |
EBX = env->cpuid_vendor1; |
EBX = env->cpuid_vendor1; |
1301 |
EDX = env->cpuid_vendor2; |
EDX = env->cpuid_vendor2; |
1302 |
ECX = env->cpuid_vendor3; |
ECX = env->cpuid_vendor3; |
1307 |
ECX = env->cpuid_ext_features; |
ECX = env->cpuid_ext_features; |
1308 |
EDX = env->cpuid_features; |
EDX = env->cpuid_features; |
1309 |
break; |
break; |
1310 |
default: |
case 2: |
1311 |
/* cache info: needed for Pentium Pro compatibility */ |
/* cache info: needed for Pentium Pro compatibility */ |
1312 |
EAX = 0x410601; |
EAX = 0x410601; |
1313 |
EBX = 0; |
EBX = 0; |
1314 |
ECX = 0; |
ECX = 0; |
1315 |
EDX = 0; |
EDX = 0; |
1316 |
break; |
break; |
|
#ifdef TARGET_X86_64 |
|
1317 |
case 0x80000000: |
case 0x80000000: |
1318 |
EAX = 0x80000008; |
EAX = env->cpuid_xlevel; |
1319 |
EBX = env->cpuid_vendor1; |
EBX = env->cpuid_vendor1; |
1320 |
EDX = env->cpuid_vendor2; |
EDX = env->cpuid_vendor2; |
1321 |
ECX = env->cpuid_vendor3; |
ECX = env->cpuid_vendor3; |
1324 |
EAX = env->cpuid_features; |
EAX = env->cpuid_features; |
1325 |
EBX = 0; |
EBX = 0; |
1326 |
ECX = 0; |
ECX = 0; |
1327 |
/* long mode + syscall/sysret features */ |
EDX = env->cpuid_ext2_features; |
1328 |
EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11); |
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]; |
1336 |
break; |
break; |
1337 |
case 0x80000008: |
case 0x80000008: |
1338 |
/* virtual & phys address size in low 2 bytes. */ |
/* virtual & phys address size in low 2 bytes. */ |
1341 |
ECX = 0; |
ECX = 0; |
1342 |
EDX = 0; |
EDX = 0; |
1343 |
break; |
break; |
1344 |
#endif |
default: |
1345 |
|
/* reserved values: zero */ |
1346 |
|
EAX = 0; |
1347 |
|
EBX = 0; |
1348 |
|
ECX = 0; |
1349 |
|
EDX = 0; |
1350 |
|
break; |
1351 |
} |
} |
1352 |
} |
} |
1353 |
|
|
1564 |
} |
} |
1565 |
|
|
1566 |
/* protected mode jump */ |
/* protected mode jump */ |
1567 |
void helper_ljmp_protected_T0_T1(int next_eip) |
void helper_ljmp_protected_T0_T1(int next_eip_addend) |
1568 |
{ |
{ |
1569 |
int new_cs, gate_cs, type; |
int new_cs, gate_cs, type; |
1570 |
uint32_t e1, e2, cpl, dpl, rpl, limit; |
uint32_t e1, e2, cpl, dpl, rpl, limit; |
1571 |
target_ulong new_eip; |
target_ulong new_eip, next_eip; |
1572 |
|
|
1573 |
new_cs = T0; |
new_cs = T0; |
1574 |
new_eip = T1; |
new_eip = T1; |
1614 |
case 5: /* task gate */ |
case 5: /* task gate */ |
1615 |
if (dpl < cpl || dpl < rpl) |
if (dpl < cpl || dpl < rpl) |
1616 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1617 |
|
next_eip = env->eip + next_eip_addend; |
1618 |
switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); |
switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); |
1619 |
break; |
break; |
1620 |
case 4: /* 286 call gate */ |
case 4: /* 286 call gate */ |
1680 |
} |
} |
1681 |
|
|
1682 |
/* protected mode call */ |
/* protected mode call */ |
1683 |
void helper_lcall_protected_T0_T1(int shift, int next_eip) |
void helper_lcall_protected_T0_T1(int shift, int next_eip_addend) |
1684 |
{ |
{ |
1685 |
int new_cs, new_eip, new_stack, i; |
int new_cs, new_eip, new_stack, i; |
1686 |
uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; |
uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; |
1687 |
uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask; |
uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask; |
1688 |
uint32_t val, limit, old_sp_mask; |
uint32_t val, limit, old_sp_mask; |
1689 |
target_ulong ssp, old_ssp; |
target_ulong ssp, old_ssp, next_eip; |
1690 |
|
|
1691 |
new_cs = T0; |
new_cs = T0; |
1692 |
new_eip = T1; |
new_eip = T1; |
1693 |
|
next_eip = env->eip + next_eip_addend; |
1694 |
#ifdef DEBUG_PCALL |
#ifdef DEBUG_PCALL |
1695 |
if (loglevel & CPU_LOG_PCALL) { |
if (loglevel & CPU_LOG_PCALL) { |
1696 |
fprintf(logfile, "lcall %04x:%08x s=%d\n", |
fprintf(logfile, "lcall %04x:%08x s=%d\n", |
1727 |
if (!(e2 & DESC_P_MASK)) |
if (!(e2 & DESC_P_MASK)) |
1728 |
raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
1729 |
|
|
1730 |
sp = ESP; |
#ifdef TARGET_X86_64 |
1731 |
sp_mask = get_sp_mask(env->segs[R_SS].flags); |
/* XXX: check 16/32 bit cases in long mode */ |
1732 |
ssp = env->segs[R_SS].base; |
if (shift == 2) { |
1733 |
if (shift) { |
target_ulong rsp; |
1734 |
PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector); |
/* 64 bit case */ |
1735 |
PUSHL(ssp, sp, sp_mask, next_eip); |
rsp = ESP; |
1736 |
} else { |
PUSHQ(rsp, env->segs[R_CS].selector); |
1737 |
PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector); |
PUSHQ(rsp, next_eip); |
1738 |
PUSHW(ssp, sp, sp_mask, next_eip); |
/* 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; |
1766 |
} |
} |
|
|
|
|
limit = get_seg_limit(e1, e2); |
|
|
if (new_eip > limit) |
|
|
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
|
|
/* from this point, not restartable */ |
|
|
ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
|
|
cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, |
|
|
get_seg_base(e1, e2), limit, e2); |
|
|
EIP = new_eip; |
|
1767 |
} else { |
} else { |
1768 |
/* check gate type */ |
/* check gate type */ |
1769 |
type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; |
type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; |
2306 |
case MSR_IA32_APICBASE: |
case MSR_IA32_APICBASE: |
2307 |
cpu_set_apic_base(env, val); |
cpu_set_apic_base(env, val); |
2308 |
break; |
break; |
|
#ifdef TARGET_X86_64 |
|
2309 |
case MSR_EFER: |
case MSR_EFER: |
2310 |
#define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \ |
{ |
2311 |
MSR_EFER_NXE | MSR_EFER_FFXSR) |
uint64_t update_mask; |
2312 |
env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) | |
update_mask = 0; |
2313 |
(val & MSR_EFER_UPDATE_MASK); |
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 |
|
} |
2324 |
break; |
break; |
2325 |
case MSR_STAR: |
case MSR_STAR: |
2326 |
env->star = val; |
env->star = val; |
2327 |
break; |
break; |
2328 |
|
#ifdef TARGET_X86_64 |
2329 |
case MSR_LSTAR: |
case MSR_LSTAR: |
2330 |
env->lstar = val; |
env->lstar = val; |
2331 |
break; |
break; |
2367 |
case MSR_IA32_APICBASE: |
case MSR_IA32_APICBASE: |
2368 |
val = cpu_get_apic_base(env); |
val = cpu_get_apic_base(env); |
2369 |
break; |
break; |
|
#ifdef TARGET_X86_64 |
|
2370 |
case MSR_EFER: |
case MSR_EFER: |
2371 |
val = env->efer; |
val = env->efer; |
2372 |
break; |
break; |
2373 |
case MSR_STAR: |
case MSR_STAR: |
2374 |
val = env->star; |
val = env->star; |
2375 |
break; |
break; |
2376 |
|
#ifdef TARGET_X86_64 |
2377 |
case MSR_LSTAR: |
case MSR_LSTAR: |
2378 |
val = env->lstar; |
val = env->lstar; |
2379 |
break; |
break; |