|
|
| version 1.3, 2004/01/23 14:33:26 | version 1.4, 2004/01/26 15:23:21 |
|---|---|
| Line 706 CALLfar_pm_call_gate_more_privilege(sele | Line 706 CALLfar_pm_call_gate_more_privilege(sele |
| } | } |
| load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl); | load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl); |
| CPU_SP = tss_esp; | CPU_ESP = tss_esp; |
| load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl); | load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl); |
| SET_EIP(callgate_sel->desc.u.gate.offset); | SET_EIP(callgate_sel->desc.u.gate.offset); |
| Line 981 RETfar_pm(DWORD nbytes) | Line 981 RETfar_pm(DWORD nbytes) |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| load_ss(ss_sel.selector, &ss_sel.desc, ret_sel.rpl); | load_ss(ss_sel.selector, &ss_sel.desc, ret_sel.rpl); |
| if (CPU_STAT_SS32) { | CPU_ESP = new_sp + nbytes; |
| CPU_ESP = new_sp + nbytes; | |
| } else { | |
| CPU_SP = new_sp + nbytes; | |
| } | |
| /* check segment register */ | /* check segment register */ |
| check_segreg(); | check_segreg(); |
| Line 999 RETfar_pm(DWORD nbytes) | Line 995 RETfar_pm(DWORD nbytes) |
| * IRET_pm | * IRET_pm |
| */ | */ |
| #undef RETURN_FROM_VM86 | #undef IA32_RETURN_FROM_VM86 |
| static void IRET_pm_nested_task(void); | static void IRET_pm_nested_task(void); |
| static void IRET_pm_return_to_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags); | static void IRET_pm_return_to_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags); |
| #ifdef RETURN_FROM_VM86 | #if defined(IA32_RETURN_FROM_VM86) |
| static void IRET_pm_return_from_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags); | static void IRET_pm_return_from_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags); |
| #endif /* RETURN_FROM_VM86 */ | #endif /* IA32_RETURN_FROM_VM86 */ |
| void | void |
| IRET_pm(void) | IRET_pm(void) |
| Line 1016 IRET_pm(void) | Line 1012 IRET_pm(void) |
| DWORD mask = 0; | DWORD mask = 0; |
| DWORD new_ip, new_sp, new_flags; | DWORD new_ip, new_sp, new_flags; |
| WORD new_cs, new_ss; | WORD new_cs, new_ss; |
| int old_cpl; | |
| int rv; | int rv; |
| VERBOSE(("IRET_pm: old EIP = %04x:%08x, old ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); | VERBOSE(("IRET_pm: old EIP = %04x:%08x, old ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); |
| Line 1024 IRET_pm(void) | Line 1021 IRET_pm(void) |
| /* TASK-RETURN: PE=1, VM=0, NT=1 */ | /* TASK-RETURN: PE=1, VM=0, NT=1 */ |
| IRET_pm_nested_task(); | IRET_pm_nested_task(); |
| VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); | VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); |
| CPU_STAT_NERROR = 0; | |
| return; | return; |
| } | } |
| Line 1035 IRET_pm(void) | Line 1033 IRET_pm(void) |
| if (CPU_INST_OP32) { | if (CPU_INST_OP32) { |
| CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 12); | CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 12); |
| new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp); | new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp); |
| new_cs = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 4); | new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); |
| new_flags = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 8); | new_flags = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 8); |
| } else { | } else { |
| CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 6); | CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 6); |
| Line 1045 IRET_pm(void) | Line 1043 IRET_pm(void) |
| } | } |
| VERBOSE(("IRET_pm: new_ip = %08x, new_cs = %04x, new_eflags = %08x", new_ip, new_cs, new_flags)); | VERBOSE(("IRET_pm: new_ip = %08x, new_cs = %04x, new_eflags = %08x", new_ip, new_cs, new_flags)); |
| #ifdef RETURN_FROM_VM86 | #ifdef IA32_RETURN_FROM_VM86 |
| if (CPU_EFLAG & VM_FLAG) { | if (CPU_EFLAG & VM_FLAG) { |
| /* RETURN-FROM-VIRTUAL-8086-MODE */ | /* RETURN-FROM-VIRTUAL-8086-MODE */ |
| IRET_pm_return_from_vm86(new_ip, new_cs, new_flags); | IRET_pm_return_from_vm86(new_ip, new_cs, new_flags); |
| VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); | VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); |
| CPU_STAT_NERROR = 0; | |
| return; | return; |
| } | } |
| #endif /* RETURN_FROM_VM86 */ | #endif /* IA32_RETURN_FROM_VM86 */ |
| if (new_flags & VM_FLAG) { | if (new_flags & VM_FLAG) { |
| /* RETURN-TO-VIRTUAL-8086-MODE */ | /* RETURN-TO-VIRTUAL-8086-MODE */ |
| IRET_pm_return_to_vm86(new_ip, new_cs, new_flags); | IRET_pm_return_to_vm86(new_ip, new_cs, new_flags); |
| VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); | VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); |
| CPU_STAT_NERROR = 0; | |
| return; | return; |
| } | } |
| Line 1102 IRET_pm(void) | Line 1102 IRET_pm(void) |
| if (CPU_INST_OP32) { | if (CPU_INST_OP32) { |
| CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 20); | CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 20); |
| new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); | new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); |
| new_ss = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 16); | new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16); |
| } else { | } else { |
| CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 10); | CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 10); |
| new_sp = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 6); | new_sp = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 6); |
| Line 1146 IRET_pm(void) | Line 1146 IRET_pm(void) |
| EXCEPTION(SS_EXCEPTION, ss_sel.idx); | EXCEPTION(SS_EXCEPTION, ss_sel.idx); |
| } | } |
| /* compiler happy :-) */ | |
| stacksize = 0; | stacksize = 0; |
| } else { | } else { |
| VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); | VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); |
| Line 1167 IRET_pm(void) | Line 1168 IRET_pm(void) |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| /* set new register */ | |
| old_cpl = CPU_STAT_CPL; | |
| load_cs(iret_sel.selector, &iret_sel.desc, iret_sel.rpl); | |
| SET_EIP(new_ip); | |
| /* set new eflags */ | |
| mask = 0; | mask = 0; |
| if (CPU_INST_OP32) | if (CPU_INST_OP32) |
| mask |= RF_FLAG; | mask |= RF_FLAG; |
| Line 1178 IRET_pm(void) | Line 1185 IRET_pm(void) |
| mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; | mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; |
| } | } |
| } | } |
| /* set new register */ | |
| load_cs(iret_sel.selector, &iret_sel.desc, iret_sel.rpl); | |
| SET_EIP(new_ip); | |
| set_eflags(new_flags, mask); | set_eflags(new_flags, mask); |
| if (iret_sel.rpl != CPU_STAT_CPL) { | if (iret_sel.rpl > old_cpl) { |
| /* RETURN-OUTER-PRIVILEGE-LEVEL */ | /* RETURN-OUTER-PRIVILEGE-LEVEL */ |
| load_ss(new_ss, &ss_sel.desc, iret_sel.rpl); | load_ss(ss_sel.selector, &ss_sel.desc, iret_sel.rpl); |
| CPU_ESP = new_sp; | CPU_ESP = new_sp; |
| /* check segment register */ | /* check segment register */ |
| Line 1200 IRET_pm(void) | Line 1202 IRET_pm(void) |
| CPU_SP += stacksize; | CPU_SP += stacksize; |
| } | } |
| } | } |
| CPU_STAT_NERROR = 0; | |
| VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); | VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); |
| } | } |
| Line 1285 IRET_pm_return_to_vm86(DWORD new_ip, DWO | Line 1288 IRET_pm_return_to_vm86(DWORD new_ip, DWO |
| CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 36); | CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 36); |
| new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); | new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); |
| segsel[CPU_SS_INDEX] = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 16); | segsel[CPU_SS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16); |
| segsel[CPU_ES_INDEX] = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 20); | segsel[CPU_ES_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 20); |
| segsel[CPU_DS_INDEX] = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 24); | segsel[CPU_DS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 24); |
| segsel[CPU_FS_INDEX] = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 28); | segsel[CPU_FS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 28); |
| segsel[CPU_GS_INDEX] = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 32); | segsel[CPU_GS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 32); |
| segsel[CPU_CS_INDEX] = new_cs; | segsel[CPU_CS_INDEX] = new_cs; |
| for (i = 0; i < CPU_SEGREG_NUM; i++) { | for (i = 0; i < CPU_SEGREG_NUM; i++) { |
| Line 1302 IRET_pm_return_to_vm86(DWORD new_ip, DWO | Line 1305 IRET_pm_return_to_vm86(DWORD new_ip, DWO |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| } | } |
| #ifdef RETURN_FROM_VM86 | #ifdef IA32_RETURN_FROM_VM86 |
| /*--- | /*--- |
| * IRET_pm: VM_FLAG | * IRET_pm: VM_FLAG |
| */ | */ |
| Line 1335 IRET_pm_return_from_vm86(DWORD new_ip, D | Line 1338 IRET_pm_return_from_vm86(DWORD new_ip, D |
| VERBOSE(("IRET_pm: trap to virtual-8086 monitor: VM=1, IOPL<3")); | VERBOSE(("IRET_pm: trap to virtual-8086 monitor: VM=1, IOPL<3")); |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| #endif /* RETURN_FROM_VM86 */ | #endif /* IA32_RETURN_FROM_VM86 */ |
| /*----- | /*----- |