|
|
| version 1.1, 2003/12/08 00:55:31 | version 1.2, 2004/01/13 16:37:42 |
|---|---|
| Line 41 JMPfar_pm(WORD selector, DWORD new_ip) | Line 41 JMPfar_pm(WORD selector, DWORD new_ip) |
| selector_t sel2; | selector_t sel2; |
| int rv; | int rv; |
| VERBOSE(("JMPfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip)); | VERBOSE(("JMPfar_pm: EIP = 0x%08x, selector = 0x%04x, new_ip = 0x%08x", CPU_PREV_EIP, selector, new_ip)); |
| /* | /* |
| * IF effective address in the CS, DS, ES, FS, GS, or SS segment is illegal | * IF effective address in the CS, DS, ES, FS, GS, or SS segment is illegal |
| Line 53 JMPfar_pm(WORD selector, DWORD new_ip) | Line 53 JMPfar_pm(WORD selector, DWORD new_ip) |
| rv = parse_selector(&jmp_sel, selector); | rv = parse_selector(&jmp_sel, selector); |
| if (rv < 0) { | if (rv < 0) { |
| VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv)); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| } | } |
| if (jmp_sel.desc.s) { | if (jmp_sel.desc.s) { |
| /* code segment descriptor */ | /* code segment descriptor */ |
| VERBOSE(("JMPfar_pm: code or data segment descriptor")); | |
| if (!jmp_sel.desc.u.seg.c) { | if (!jmp_sel.desc.u.seg.c) { |
| /* data segment */ | /* data segment */ |
| VERBOSE(("JMPfar_pm: data segment")); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| } | } |
| Line 69 JMPfar_pm(WORD selector, DWORD new_ip) | Line 73 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* 布船 p.119 4.8.1.1. */ | /* 布船 p.119 4.8.1.1. */ |
| if ((jmp_sel.rpl > CPU_STAT_CPL) | if ((jmp_sel.rpl > CPU_STAT_CPL) |
| || (jmp_sel.desc.dpl != CPU_STAT_CPL)) { | || (jmp_sel.desc.dpl != CPU_STAT_CPL)) { |
| VERBOSE(("JMPfar_pm: RPL(%d) > CPL(%d) or DPL(%d) != CPL(%d)", jmp_sel.rpl, CPU_STAT_CPL, jmp_sel.desc.dpl, CPU_STAT_CPL)); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| } | } |
| } else { | } else { |
| VERBOSE(("CONFORMING-CODE-SEGMENT")); | VERBOSE(("CONFORMING-CODE-SEGMENT")); |
| /* 布船 p.120 4.8.1.2. */ | /* 布船 p.120 4.8.1.2. */ |
| if (jmp_sel.desc.dpl > CPU_STAT_CPL) { | if (jmp_sel.desc.dpl > CPU_STAT_CPL) { |
| VERBOSE(("JMPfar_pm: DPL(%d) > CPL(%d)", jmp_sel.desc.dpl, CPU_STAT_CPL)); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| } | } |
| } | } |
| /* not present */ | /* not present */ |
| if (selector_is_not_present(&jmp_sel)) { | if (selector_is_not_present(&jmp_sel)) { |
| VERBOSE(("JMPfar_pm: selector is not present")); | |
| EXCEPTION(NP_EXCEPTION, jmp_sel.idx); | EXCEPTION(NP_EXCEPTION, jmp_sel.idx); |
| } | } |
| Line 90 JMPfar_pm(WORD selector, DWORD new_ip) | Line 97 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* out of range */ | /* out of range */ |
| if (new_ip > jmp_sel.desc.u.seg.limit) { | if (new_ip > jmp_sel.desc.u.seg.limit) { |
| VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, jmp_sel.desc.u.seg.limit)); | |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| VERBOSE(("JMPfar_pm: new CS = %04x, EIP = %08x", jmp_sel.selector, new_ip)); | |
| load_cs(jmp_sel.selector, &jmp_sel.desc, CPU_STAT_CPL); | load_cs(jmp_sel.selector, &jmp_sel.desc, CPU_STAT_CPL); |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| } else { | } else { |
| /* system descriptor */ | /* system descriptor */ |
| VERBOSE(("JMPfar_pm: system descriptor")); | |
| switch (jmp_sel.desc.type) { | switch (jmp_sel.desc.type) { |
| case CPU_SYSDESC_TYPE_CALL_16: | case CPU_SYSDESC_TYPE_CALL_16: |
| case CPU_SYSDESC_TYPE_CALL_32: | case CPU_SYSDESC_TYPE_CALL_32: |
| Line 105 JMPfar_pm(WORD selector, DWORD new_ip) | Line 116 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* check privilege level */ | /* check privilege level */ |
| if ((jmp_sel.desc.dpl < CPU_STAT_CPL) | if ((jmp_sel.desc.dpl < CPU_STAT_CPL) |
| || (jmp_sel.desc.dpl < jmp_sel.rpl)) { | || (jmp_sel.desc.dpl < jmp_sel.rpl)) { |
| VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d) or DPL(%d) < RPL(%d)", jmp_sel.desc.dpl, CPU_STAT_CPL, jmp_sel.desc.dpl, jmp_sel.rpl)); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| } | } |
| /* not present */ | /* not present */ |
| if (selector_is_not_present(&jmp_sel)) { | if (selector_is_not_present(&jmp_sel)) { |
| VERBOSE(("JMPfar_pm: selector is not present")); | |
| EXCEPTION(NP_EXCEPTION, jmp_sel.idx); | EXCEPTION(NP_EXCEPTION, jmp_sel.idx); |
| } | } |
| /* parse call gate selector */ | /* parse call gate selector */ |
| rv = parse_selector(&sel2, jmp_sel.desc.u.gate.selector); | rv = parse_selector(&sel2, jmp_sel.desc.u.gate.selector); |
| if (rv < 0) { | if (rv < 0) { |
| VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", jmp_sel.desc.u.gate.selector, rv)); | |
| EXCEPTION(GP_EXCEPTION, sel2.idx); | EXCEPTION(GP_EXCEPTION, sel2.idx); |
| } | } |
| /* check code segment descriptor */ | /* check code segment descriptor */ |
| if (!sel2.desc.s || !sel2.desc.u.seg.c) { | if (!sel2.desc.s || !sel2.desc.u.seg.c) { |
| VERBOSE(("JMPfar_pm: not code segment (%s, %s)", sel2.desc.s ? "code/data" : "system", sel2.desc.u.seg.c ? "code" : "data")); | |
| EXCEPTION(GP_EXCEPTION, sel2.idx); | EXCEPTION(GP_EXCEPTION, sel2.idx); |
| } | } |
| Line 129 JMPfar_pm(WORD selector, DWORD new_ip) | Line 144 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* 布船 p.119 4.8.1.1. */ | /* 布船 p.119 4.8.1.1. */ |
| if ((sel2.rpl > CPU_STAT_CPL) | if ((sel2.rpl > CPU_STAT_CPL) |
| || (sel2.desc.dpl != CPU_STAT_CPL)) { | || (sel2.desc.dpl != CPU_STAT_CPL)) { |
| VERBOSE(("JMPfar_pm: RPL(%d) > CPL(%d) or DPL(%d) != CPL(%d)", sel2.rpl, CPU_STAT_CPL, sel2.desc.dpl, CPU_STAT_CPL)); | |
| EXCEPTION(GP_EXCEPTION, sel2.idx); | EXCEPTION(GP_EXCEPTION, sel2.idx); |
| } | } |
| } else { | } else { |
| /* 布船 p.120 4.8.1.2. */ | /* 布船 p.120 4.8.1.2. */ |
| if (sel2.desc.dpl > CPU_STAT_CPL) { | if (sel2.desc.dpl > CPU_STAT_CPL) { |
| VERBOSE(("JMPfar_pm: DPL(%d) > CPL(%d)", sel2.desc.dpl, CPU_STAT_CPL)); | |
| EXCEPTION(GP_EXCEPTION, sel2.idx); | EXCEPTION(GP_EXCEPTION, sel2.idx); |
| } | } |
| } | } |
| /* not present */ | /* not present */ |
| if (selector_is_not_present(&sel2)) { | if (selector_is_not_present(&sel2)) { |
| VERBOSE(("JMPfar_pm: selector is not present")); | |
| EXCEPTION(NP_EXCEPTION, sel2.idx); | EXCEPTION(NP_EXCEPTION, sel2.idx); |
| } | } |
| Line 150 JMPfar_pm(WORD selector, DWORD new_ip) | Line 168 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* out of range */ | /* out of range */ |
| if (new_ip > sel2.desc.u.seg.limit) { | if (new_ip > sel2.desc.u.seg.limit) { |
| VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, sel2.desc.u.seg.limit)); | |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| VERBOSE(("JMPfar_pm: new CS = %04x, EIP = %08x", sel2.selector, new_ip)); | |
| load_cs(sel2.selector, &sel2.desc, CPU_STAT_CPL); | load_cs(sel2.selector, &sel2.desc, CPU_STAT_CPL); |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| break; | break; |
| Line 176 JMPfar_pm(WORD selector, DWORD new_ip) | Line 196 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* check privilege level */ | /* check privilege level */ |
| if ((jmp_sel.desc.dpl < CPU_STAT_CPL) | if ((jmp_sel.desc.dpl < CPU_STAT_CPL) |
| || (jmp_sel.desc.dpl < jmp_sel.rpl)) { | || (jmp_sel.desc.dpl < jmp_sel.rpl)) { |
| VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d) or DPL(%d) < RPL(%d)", jmp_sel.desc.dpl, CPU_STAT_CPL, jmp_sel.desc.dpl, jmp_sel.rpl)); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| } | } |
| /* not present */ | /* not present */ |
| if (selector_is_not_present(&jmp_sel)) { | if (selector_is_not_present(&jmp_sel)) { |
| VERBOSE(("JMPfar_pm: selector is not present")); | |
| EXCEPTION(NP_EXCEPTION, jmp_sel.idx); | EXCEPTION(NP_EXCEPTION, jmp_sel.idx); |
| } | } |
| /* parse call tss selector */ | /* parse call tss selector */ |
| rv = parse_selector(&sel2, jmp_sel.desc.u.gate.selector); | rv = parse_selector(&sel2, jmp_sel.desc.u.gate.selector); |
| if (rv < 0 || sel2.ldt) { | if (rv < 0 || sel2.ldt) { |
| VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d, %s)", jmp_sel.desc.u.gate.selector, rv, sel2.ldt ? "LDT" : "GDT")); | |
| EXCEPTION(GP_EXCEPTION, sel2.idx); | EXCEPTION(GP_EXCEPTION, sel2.idx); |
| } | } |
| Line 197 JMPfar_pm(WORD selector, DWORD new_ip) | Line 220 JMPfar_pm(WORD selector, DWORD new_ip) |
| break; | break; |
| default: | default: |
| VERBOSE(("JMPfar_pm: invalid descriptor type (type = %d)", sel2.desc.type)); | |
| EXCEPTION(GP_EXCEPTION, sel2.idx); | EXCEPTION(GP_EXCEPTION, sel2.idx); |
| break; | break; |
| } | } |
| /* not present */ | /* not present */ |
| if (selector_is_not_present(&sel2)) { | if (selector_is_not_present(&sel2)) { |
| VERBOSE(("JMPfar_pm: selector is not present")); | |
| EXCEPTION(NP_EXCEPTION, sel2.idx); | EXCEPTION(NP_EXCEPTION, sel2.idx); |
| } | } |
| Line 210 JMPfar_pm(WORD selector, DWORD new_ip) | Line 235 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* out of range */ | /* out of range */ |
| if (CPU_EIP > CPU_STAT_CS_LIMIT) { | if (CPU_EIP > CPU_STAT_CS_LIMIT) { |
| VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); | |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| break; | break; |
| Line 221 JMPfar_pm(WORD selector, DWORD new_ip) | Line 247 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* check privilege level */ | /* check privilege level */ |
| if ((jmp_sel.desc.dpl < CPU_STAT_CPL) | if ((jmp_sel.desc.dpl < CPU_STAT_CPL) |
| || (jmp_sel.desc.dpl < jmp_sel.rpl)) { | || (jmp_sel.desc.dpl < jmp_sel.rpl)) { |
| VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d) or DPL(%d) < RPL(%d)", jmp_sel.desc.dpl, CPU_STAT_CPL, jmp_sel.desc.dpl, jmp_sel.rpl)); | |
| EXCEPTION(TS_EXCEPTION, jmp_sel.idx); | EXCEPTION(TS_EXCEPTION, jmp_sel.idx); |
| } | } |
| /* not present */ | /* not present */ |
| if (selector_is_not_present(&jmp_sel)) { | if (selector_is_not_present(&jmp_sel)) { |
| VERBOSE(("JMPfar_pm: selector is not present")); | |
| EXCEPTION(NP_EXCEPTION, jmp_sel.idx); | EXCEPTION(NP_EXCEPTION, jmp_sel.idx); |
| } | } |
| Line 233 JMPfar_pm(WORD selector, DWORD new_ip) | Line 261 JMPfar_pm(WORD selector, DWORD new_ip) |
| /* out of range */ | /* out of range */ |
| if (CPU_EIP > CPU_STAT_CS_LIMIT) { | if (CPU_EIP > CPU_STAT_CS_LIMIT) { |
| VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); | |
| EXCEPTION(GP_EXCEPTION, 0); | EXCEPTION(GP_EXCEPTION, 0); |
| } | } |
| break; | break; |
| Line 242 JMPfar_pm(WORD selector, DWORD new_ip) | Line 271 JMPfar_pm(WORD selector, DWORD new_ip) |
| VERBOSE(("JMPfar_pm: task is busy")); | VERBOSE(("JMPfar_pm: task is busy")); |
| /*FALLTHROUGH*/ | /*FALLTHROUGH*/ |
| default: | default: |
| VERBOSE(("JMPfar_pm: invalid descriptor type (type = %d)", sel2.desc.type)); | |
| EXCEPTION(GP_EXCEPTION, jmp_sel.idx); | EXCEPTION(GP_EXCEPTION, jmp_sel.idx); |
| break; | break; |
| } | } |
| Line 274 CALLfar_pm(WORD selector, DWORD new_ip) | Line 304 CALLfar_pm(WORD selector, DWORD new_ip) |
| selector_t sel2; | selector_t sel2; |
| int rv; | int rv; |
| VERBOSE(("CALLfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip)); | VERBOSE(("CALLfar_pm: EIP = 0x%08x, selector = 0x%04x, new_ip = 0x%08x", CPU_PREV_EIP, selector, new_ip)); |
| rv = parse_selector(&call_sel, selector); | rv = parse_selector(&call_sel, selector); |
| if (rv < 0) { | if (rv < 0) { |
| Line 329 CALLfar_pm(WORD selector, DWORD new_ip) | Line 359 CALLfar_pm(WORD selector, DWORD new_ip) |
| PUSH0_16(CPU_CS); | PUSH0_16(CPU_CS); |
| PUSH0_16(CPU_IP); | PUSH0_16(CPU_IP); |
| } | |
| if (!call_sel.desc.d) { | |
| new_ip &= 0xffff; | new_ip &= 0xffff; |
| } | } |
| load_cs(call_sel.selector, &call_sel.desc, CPU_STAT_CPL); | load_cs(call_sel.selector, &call_sel.desc, CPU_STAT_CPL); |
| SET_EIP(new_ip); | SET_EIP(new_ip); |
| } else { | } else { |
| Line 603 RETfar_pm(DWORD nbytes) | Line 637 RETfar_pm(DWORD nbytes) |
| DWORD new_ip; | DWORD new_ip; |
| WORD selector; | WORD selector; |
| VERBOSE(("RETfar_pm: nbytes = %d", nbytes)); | VERBOSE(("RETfar_pm: EIP = 0x%08x, nbytes = %d", CPU_PREV_EIP, nbytes)); |
| if (CPU_INST_OP32) { | if (CPU_INST_OP32) { |
| CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), CPU_ESP, 8 + nbytes); | CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), CPU_ESP, 8 + nbytes); |
| Line 759 IRET_pm() | Line 793 IRET_pm() |
| DWORD new_ip, new_flags; | DWORD new_ip, new_flags; |
| WORD new_cs; | WORD new_cs; |
| VERBOSE(("IRET_pm")); | VERBOSE(("IRET_pm: EIP = 0x%08x", CPU_PREV_EIP)); |
| if (CPU_STAT_VM86) { | if (CPU_STAT_VM86) { |
| /* RETURN-FROM-VIRTUAL-8086-MODE */ | /* RETURN-FROM-VIRTUAL-8086-MODE */ |