|
|
| version 1.16, 2004/03/12 13:34:08 | version 1.19, 2008/01/25 17:49:46 |
|---|---|
| Line 12 | Line 12 |
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products | |
| * derived from this software without specific prior written permission. | |
| * | * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| Line 37 | Line 35 |
| /*------------------------------------------------------------------------------ | /*------------------------------------------------------------------------------ |
| * JMPfar_pm | * JMPfar_pm |
| */ | */ |
| static void JMPfar_pm_code_segment(selector_t *cs_sel, UINT32 new_ip); | static void JMPfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip); |
| static void JMPfar_pm_call_gate(selector_t *callgate_sel); | static void JMPfar_pm_call_gate(const selector_t *callgate_sel); |
| static void JMPfar_pm_task_gate(selector_t *taskgate_sel); | static void JMPfar_pm_task_gate(selector_t *taskgate_sel); |
| static void JMPfar_pm_tss(selector_t *tss_sel); | static void JMPfar_pm_tss(selector_t *tss_sel); |
| Line 106 JMPfar_pm(UINT16 selector, UINT32 new_ip | Line 104 JMPfar_pm(UINT16 selector, UINT32 new_ip |
| * JMPfar: code segment | * JMPfar: code segment |
| */ | */ |
| static void | static void |
| JMPfar_pm_code_segment(selector_t *cs_sel, UINT32 new_ip) | JMPfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip) |
| { | { |
| VERBOSE(("JMPfar_pm: CODE-SEGMENT")); | VERBOSE(("JMPfar_pm: CODE-SEGMENT")); |
| Line 152 JMPfar_pm_code_segment(selector_t *cs_se | Line 150 JMPfar_pm_code_segment(selector_t *cs_se |
| * JMPfar: call gate | * JMPfar: call gate |
| */ | */ |
| static void | static void |
| JMPfar_pm_call_gate(selector_t *callgate_sel) | JMPfar_pm_call_gate(const selector_t *callgate_sel) |
| { | { |
| selector_t cs_sel; | selector_t cs_sel; |
| int rv; | int rv; |
| Line 318 JMPfar_pm_tss(selector_t *tss_sel) | Line 316 JMPfar_pm_tss(selector_t *tss_sel) |
| /*------------------------------------------------------------------------------ | /*------------------------------------------------------------------------------ |
| * CALLfar_pm | * CALLfar_pm |
| */ | */ |
| static void CALLfar_pm_code_segment(selector_t *cs_sel, UINT32 new_ip); | static void CALLfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip); |
| static void CALLfar_pm_call_gate(selector_t *callgate_sel); | static void CALLfar_pm_call_gate(const selector_t *callgate_sel); |
| static void CALLfar_pm_task_gate(selector_t *taskgate_sel); | static void CALLfar_pm_task_gate(selector_t *taskgate_sel); |
| static void CALLfar_pm_tss(selector_t *tss_sel); | static void CALLfar_pm_tss(selector_t *tss_sel); |
| Line 387 CALLfar_pm(UINT16 selector, UINT32 new_i | Line 385 CALLfar_pm(UINT16 selector, UINT32 new_i |
| * CALLfar_pm: code segment | * CALLfar_pm: code segment |
| */ | */ |
| static void | static void |
| CALLfar_pm_code_segment(selector_t *cs_sel, UINT32 new_ip) | CALLfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip) |
| { | { |
| UINT32 sp; | UINT32 sp; |
| Line 456 CALLfar_pm_code_segment(selector_t *cs_s | Line 454 CALLfar_pm_code_segment(selector_t *cs_s |
| /*--- | /*--- |
| * CALLfar_pm: call gate | * CALLfar_pm: call gate |
| */ | */ |
| static void CALLfar_pm_call_gate_same_privilege(selector_t *call_sel, selector_t *cs_sel); | static void CALLfar_pm_call_gate_same_privilege(const selector_t *call_sel, selector_t *cs_sel); |
| static void CALLfar_pm_call_gate_more_privilege(selector_t *call_sel, selector_t *cs_sel); | static void CALLfar_pm_call_gate_more_privilege(const selector_t *call_sel, selector_t *cs_sel); |
| static void | static void |
| CALLfar_pm_call_gate(selector_t *callgate_sel) | CALLfar_pm_call_gate(const selector_t *callgate_sel) |
| { | { |
| selector_t cs_sel; | selector_t cs_sel; |
| int rv; | int rv; |
| Line 529 CALLfar_pm_call_gate(selector_t *callgat | Line 527 CALLfar_pm_call_gate(selector_t *callgat |
| * CALLfar_pm: call gate (SAME-PRIVILEGE) | * CALLfar_pm: call gate (SAME-PRIVILEGE) |
| */ | */ |
| static void | static void |
| CALLfar_pm_call_gate_same_privilege(selector_t *callgate_sel, selector_t *cs_sel) | CALLfar_pm_call_gate_same_privilege(const selector_t *callgate_sel, selector_t *cs_sel) |
| { | { |
| UINT32 sp; | UINT32 sp; |
| Line 564 CALLfar_pm_call_gate_same_privilege(sele | Line 562 CALLfar_pm_call_gate_same_privilege(sele |
| * CALLfar_pm: call gate (MORE-PRIVILEGE) | * CALLfar_pm: call gate (MORE-PRIVILEGE) |
| */ | */ |
| static void | static void |
| CALLfar_pm_call_gate_more_privilege(selector_t *callgate_sel, selector_t *cs_sel) | CALLfar_pm_call_gate_more_privilege(const selector_t *callgate_sel, selector_t *cs_sel) |
| { | { |
| UINT32 param[32]; /* copy param */ | UINT32 param[32]; /* copy param */ |
| selector_t ss_sel; | selector_t ss_sel; |
| Line 990 RETfar_pm(UINT nbytes) | Line 988 RETfar_pm(UINT nbytes) |
| */ | */ |
| static void IRET_pm_nested_task(void); | static void IRET_pm_nested_task(void); |
| static void IRET_pm_protected_mode_return(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); | static void IRET_pm_protected_mode_return(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); |
| static void IRET_pm_protected_mode_return_same_privilege(selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); | static void IRET_pm_protected_mode_return_same_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); |
| static void IRET_pm_protected_mode_return_outer_privilege(selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); | static void IRET_pm_protected_mode_return_outer_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); |
| static void IRET_pm_return_to_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); | static void IRET_pm_return_to_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); |
| static void IRET_pm_return_from_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); | static void IRET_pm_return_from_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); |
| Line 1147 IRET_pm_protected_mode_return(UINT16 new | Line 1145 IRET_pm_protected_mode_return(UINT16 new |
| * IRET_pm: SAME-PRIVILEGE | * IRET_pm: SAME-PRIVILEGE |
| */ | */ |
| static void | static void |
| IRET_pm_protected_mode_return_same_privilege(selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) | IRET_pm_protected_mode_return_same_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) |
| { | { |
| UINT32 mask; | UINT32 mask; |
| UINT stacksize; | UINT stacksize; |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| UINT32 old_flags = CPU_EFLAG; | |
| #endif | |
| VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); | VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); |
| Line 1163 IRET_pm_protected_mode_return_same_privi | Line 1158 IRET_pm_protected_mode_return_same_privi |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| mask = ALL_EFLAG; | |
| if (CPU_STAT_CPL > CPU_STAT_IOPL) | |
| mask &= ~I_FLAG; | |
| if (CPU_STAT_CPL > 0) { | |
| mask &= ~IOPL_FLAG; | |
| if (CPU_INST_OP32) { | |
| mask &= ~(VM_FLAG|VIF_FLAG|VIP_FLAG); | |
| } | |
| } | |
| #else | |
| mask = 0; | mask = 0; |
| if (CPU_INST_OP32) | if (CPU_INST_OP32) |
| mask |= RF_FLAG; | mask |= RF_FLAG; |
| Line 1185 IRET_pm_protected_mode_return_same_privi | Line 1169 IRET_pm_protected_mode_return_same_privi |
| mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; | mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; |
| } | } |
| } | } |
| #endif | |
| if (CPU_INST_OP32) { | if (CPU_INST_OP32) { |
| stacksize = 12; | stacksize = 12; |
| Line 1197 IRET_pm_protected_mode_return_same_privi | Line 1180 IRET_pm_protected_mode_return_same_privi |
| load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); | load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| CPU_EFLAG = (new_flags & mask) | (CPU_EFLAG & ~mask); | |
| CPU_OV = CPU_FLAG & O_FLAG; | |
| CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); | |
| if ((old_flags ^ CPU_EFLAG) & VM_FLAG) { | |
| if (CPU_EFLAG & VM_FLAG) { | |
| change_vm(1); | |
| } else { | |
| change_vm(0); | |
| } | |
| } | |
| #else | |
| set_eflags(new_flags, mask); | set_eflags(new_flags, mask); |
| #endif | |
| if (CPU_STAT_SS32) { | if (CPU_STAT_SS32) { |
| CPU_ESP += stacksize; | CPU_ESP += stacksize; |
| Line 1223 IRET_pm_protected_mode_return_same_privi | Line 1193 IRET_pm_protected_mode_return_same_privi |
| * IRET_pm: OUTER-PRIVILEGE | * IRET_pm: OUTER-PRIVILEGE |
| */ | */ |
| static void | static void |
| IRET_pm_protected_mode_return_outer_privilege(selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) | IRET_pm_protected_mode_return_outer_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) |
| { | { |
| descriptor_t *dp; | descriptor_t *dp; |
| selector_t ss_sel; | selector_t ss_sel; |
| Line 1233 IRET_pm_protected_mode_return_outer_priv | Line 1203 IRET_pm_protected_mode_return_outer_priv |
| UINT16 new_ss; | UINT16 new_ss; |
| int rv; | int rv; |
| int i; | int i; |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| UINT32 old_flags = CPU_EFLAG; | |
| #endif | |
| VERBOSE(("IRET_pm: RETURN-OUTER-PRIVILEGE-LEVEL")); | VERBOSE(("IRET_pm: RETURN-OUTER-PRIVILEGE-LEVEL")); |
| Line 1297 IRET_pm_protected_mode_return_outer_priv | Line 1264 IRET_pm_protected_mode_return_outer_priv |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| mask = ALL_EFLAG; | |
| if (CPU_STAT_CPL > CPU_STAT_IOPL) | |
| mask &= ~I_FLAG; | |
| if (CPU_STAT_CPL > 0) { | |
| mask &= ~IOPL_FLAG; | |
| if (CPU_INST_OP32) { | |
| mask &= ~(VM_FLAG|VIF_FLAG|VIP_FLAG); | |
| } | |
| } | |
| #else | |
| mask = 0; | mask = 0; |
| if (CPU_INST_OP32) | if (CPU_INST_OP32) |
| mask |= RF_FLAG; | mask |= RF_FLAG; |
| Line 1319 IRET_pm_protected_mode_return_outer_priv | Line 1275 IRET_pm_protected_mode_return_outer_priv |
| mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; | mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; |
| } | } |
| } | } |
| #endif | |
| /* set new register */ | /* set new register */ |
| load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->rpl); | load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->rpl); |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| CPU_EFLAG = (new_flags & mask) | (CPU_EFLAG & ~mask); | |
| CPU_OV = CPU_FLAG & O_FLAG; | |
| CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); | |
| if ((old_flags ^ CPU_EFLAG) & VM_FLAG) { | |
| if (CPU_EFLAG & VM_FLAG) { | |
| change_vm(1); | |
| } else { | |
| change_vm(0); | |
| } | |
| } | |
| #else | |
| set_eflags(new_flags, mask); | set_eflags(new_flags, mask); |
| #endif | |
| load_ss(ss_sel.selector, &ss_sel.desc, cs_sel->rpl); | load_ss(ss_sel.selector, &ss_sel.desc, cs_sel->rpl); |
| if (CPU_STAT_SS32) { | if (CPU_STAT_SS32) { |
| Line 1371 IRET_pm_return_to_vm86(UINT16 new_cs, UI | Line 1313 IRET_pm_return_to_vm86(UINT16 new_cs, UI |
| UINT32 sp; | UINT32 sp; |
| UINT32 new_sp; | UINT32 new_sp; |
| int i; | int i; |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| UINT32 old_flags = CPU_EFLAG; | |
| #endif | |
| VERBOSE(("IRET_pm: Interrupt procedure was in virtual-8086 mode: PE=1, VM=1 in flags image")); | VERBOSE(("IRET_pm: Interrupt procedure was in virtual-8086 mode: PE=1, VM=1 in flags image")); |
| Line 1405 IRET_pm_return_to_vm86(UINT16 new_cs, UI | Line 1344 IRET_pm_return_to_vm86(UINT16 new_cs, UI |
| } | } |
| /* to VM86 mode */ | /* to VM86 mode */ |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| CPU_EFLAG = new_flags; | |
| CPU_OV = CPU_FLAG & O_FLAG; | |
| CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); | |
| if ((old_flags ^ CPU_EFLAG) & VM_FLAG) { | |
| if (CPU_EFLAG & VM_FLAG) { | |
| change_vm(1); | |
| } else { | |
| change_vm(0); | |
| } | |
| } | |
| #else | |
| set_eflags(new_flags, IOPL_FLAG|I_FLAG|VM_FLAG|RF_FLAG); | set_eflags(new_flags, IOPL_FLAG|I_FLAG|VM_FLAG|RF_FLAG); |
| #endif | |
| new_sp &= 0xffff; | new_sp &= 0xffff; |
| new_ip &= 0xffff; | new_ip &= 0xffff; |
| Line 1450 IRET_pm_return_from_vm86(UINT16 new_cs, | Line 1376 IRET_pm_return_from_vm86(UINT16 new_cs, |
| CPU_SP += (UINT16)stacksize; | CPU_SP += (UINT16)stacksize; |
| } | } |
| #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION) | |
| CPU_EFLAG = (new_flags & ~(IOPL_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG)) | (CPU_EFLAG & (IOPL_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG)); | |
| CPU_OV = CPU_FLAG & O_FLAG; | |
| CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); | |
| #else | |
| set_eflags(new_flags, I_FLAG|RF_FLAG); | set_eflags(new_flags, I_FLAG|RF_FLAG); |
| #endif | |
| CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); | CPU_SET_SEGREG(CPU_CS_INDEX, new_cs); |
| SET_EIP(new_ip); | SET_EIP(new_ip); |