- sysenter/exit should be supported in v8086 mode as well
- fixed missed CS.LIMIT check in all far calls/jmps in real/v8086 mode
This commit is contained in:
parent
280617288c
commit
24f1507fa9
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ctrl_xfer32.cc,v 1.68 2008-03-22 21:29:39 sshwarts Exp $
|
||||
// $Id: ctrl_xfer32.cc,v 1.69 2008-04-20 21:44:13 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -95,8 +95,6 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32(bxInstruction_c *i)
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32_Iw(bxInstruction_c *i)
|
||||
{
|
||||
Bit32u eip, cs_raw;
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
#if BX_DEBUGGER
|
||||
@ -113,10 +111,17 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32_Iw(bxInstruction_c *i)
|
||||
goto done;
|
||||
}
|
||||
|
||||
eip = pop_32();
|
||||
cs_raw = pop_32();
|
||||
Bit32u eip = pop_32();
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) cs_raw);
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (eip > 0xffff) {
|
||||
BX_ERROR(("RETfar32_Iw: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit16u cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = eip;
|
||||
|
||||
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
|
||||
@ -133,8 +138,6 @@ done:
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32(bxInstruction_c *i)
|
||||
{
|
||||
Bit32u eip, cs_raw;
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
#if BX_DEBUGGER
|
||||
@ -149,10 +152,17 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32(bxInstruction_c *i)
|
||||
goto done;
|
||||
}
|
||||
|
||||
eip = pop_32();
|
||||
cs_raw = pop_32(); /* 32bit pop, MSW discarded */
|
||||
Bit32u eip = pop_32();
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) cs_raw);
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (eip > 0xffff) {
|
||||
BX_ERROR(("RETfar32: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
Bit16u cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = eip;
|
||||
|
||||
done:
|
||||
@ -204,6 +214,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ap(bxInstruction_c *i)
|
||||
goto done;
|
||||
}
|
||||
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (disp32 > 0xffff) {
|
||||
BX_ERROR(("CALL32_Ap: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
|
||||
push_32(EIP);
|
||||
|
||||
@ -284,11 +300,17 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ep(bxInstruction_c *i)
|
||||
goto done;
|
||||
}
|
||||
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (op1_32 > 0xffff) {
|
||||
BX_ERROR(("CALL32_Ep: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
|
||||
push_32(EIP);
|
||||
|
||||
EIP = op1_32;
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = op1_32;
|
||||
|
||||
done:
|
||||
BX_CPU_THIS_PTR speculative_rsp = 0;
|
||||
@ -524,12 +546,19 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Ap(bxInstruction_c *i)
|
||||
// jump_protected doesn't affect RSP so it is RSP safe
|
||||
if (protected_mode()) {
|
||||
BX_CPU_THIS_PTR jump_protected(i, cs_raw, disp32);
|
||||
}
|
||||
else {
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = disp32;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (disp32 > 0xffff) {
|
||||
BX_ERROR(("JMP_Ap: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = disp32;
|
||||
|
||||
done:
|
||||
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
|
||||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
|
||||
}
|
||||
@ -584,21 +613,25 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP32_Ep(bxInstruction_c *i)
|
||||
// jump_protected doesn't affect RSP so it is RSP safe
|
||||
if (protected_mode()) {
|
||||
BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_32);
|
||||
}
|
||||
else {
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = op1_32;
|
||||
goto done;
|
||||
}
|
||||
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (op1_32 > 0xffff) {
|
||||
BX_ERROR(("JMP32_Ep: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
|
||||
EIP = op1_32;
|
||||
|
||||
done:
|
||||
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
|
||||
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
|
||||
{
|
||||
Bit32u eip, eflags32;
|
||||
Bit16u cs;
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
#if BX_DEBUGGER
|
||||
@ -621,18 +654,18 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
|
||||
goto done;
|
||||
}
|
||||
|
||||
eip = pop_32();
|
||||
Bit32u eip = pop_32();
|
||||
|
||||
// CS.LIMIT in real mode is 0xffff
|
||||
// CS.LIMIT in real/v8086 mode is 0xffff
|
||||
if (eip > 0xffff) {
|
||||
BX_ERROR(("IRETD: instruction pointer not within code segment limits"));
|
||||
BX_ERROR(("IRET32: instruction pointer not within code segment limits"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
cs = pop_32() & 0xffff;
|
||||
eflags32 = pop_32();
|
||||
Bit16u cs = (Bit16u) pop_32();
|
||||
Bit32u eflags32 = pop_32();
|
||||
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) cs);
|
||||
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs);
|
||||
EIP = eip;
|
||||
writeEFlags(eflags32, 0x00257fd5); // VIF, VIP, VM unchanged
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// $Id: iret.cc,v 1.31 2008-04-14 21:48:37 sshwarts Exp $
|
||||
// $Id: iret.cc,v 1.32 2008-04-20 21:44:13 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005 Stanislav Shwartsman
|
||||
@ -56,7 +56,7 @@ BX_CPU_C::iret_protected(bxInstruction_c *i)
|
||||
if (BX_CPU_THIS_PTR get_VM())
|
||||
BX_PANIC(("iret_protected: VM sholdn't be set here !"));
|
||||
|
||||
//BX_INFO(("IRET: nested task return"));
|
||||
BX_DEBUG(("IRET: nested task return"));
|
||||
|
||||
if (BX_CPU_THIS_PTR tr.cache.valid==0)
|
||||
BX_PANIC(("IRET: TR not valid"));
|
||||
@ -137,9 +137,9 @@ BX_CPU_C::iret_protected(bxInstruction_c *i)
|
||||
temp_ESP = SP;
|
||||
|
||||
if (i->os32L()) {
|
||||
new_eflags = read_virtual_dword(BX_SEG_REG_SS, temp_ESP + 8);
|
||||
raw_cs_selector = (Bit16u) read_virtual_dword(BX_SEG_REG_SS, temp_ESP + 4);
|
||||
new_eip = read_virtual_dword(BX_SEG_REG_SS, temp_ESP + 0);
|
||||
new_eflags = read_virtual_dword(BX_SEG_REG_SS, temp_ESP + 8);
|
||||
|
||||
// if VM=1 in flags image on stack then STACK_RETURN_TO_V86
|
||||
if (new_eflags & EFlagsVMMask) {
|
||||
@ -151,9 +151,9 @@ BX_CPU_C::iret_protected(bxInstruction_c *i)
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_flags = read_virtual_word(BX_SEG_REG_SS, temp_ESP + 4);
|
||||
raw_cs_selector = read_virtual_word(BX_SEG_REG_SS, temp_ESP + 2);
|
||||
new_ip = read_virtual_word(BX_SEG_REG_SS, temp_ESP + 0);
|
||||
new_flags = read_virtual_word(BX_SEG_REG_SS, temp_ESP + 4);
|
||||
}
|
||||
|
||||
parse_selector(raw_cs_selector, &cs_selector);
|
||||
@ -364,21 +364,21 @@ BX_CPU_C::long_iret(bxInstruction_c *i)
|
||||
unsigned top_nbytes_same = 0; /* stop compiler warnings */
|
||||
|
||||
if (i->os64L()) {
|
||||
new_eflags = (Bit32u) read_virtual_qword(BX_SEG_REG_SS, temp_RSP + 16);
|
||||
raw_cs_selector = (Bit16u) read_virtual_qword(BX_SEG_REG_SS, temp_RSP + 8);
|
||||
new_rip = read_virtual_qword(BX_SEG_REG_SS, temp_RSP + 0);
|
||||
new_eflags = (Bit32u) read_virtual_qword(BX_SEG_REG_SS, temp_RSP + 16);
|
||||
top_nbytes_same = 24;
|
||||
}
|
||||
else if (i->os32L()) {
|
||||
new_eflags = read_virtual_dword(BX_SEG_REG_SS, temp_RSP + 8);
|
||||
raw_cs_selector = (Bit16u) read_virtual_dword(BX_SEG_REG_SS, temp_RSP + 4);
|
||||
new_rip = (Bit64u) read_virtual_dword(BX_SEG_REG_SS, temp_RSP + 0);
|
||||
new_eflags = read_virtual_dword(BX_SEG_REG_SS, temp_RSP + 8);
|
||||
top_nbytes_same = 12;
|
||||
}
|
||||
else {
|
||||
new_eflags = read_virtual_word(BX_SEG_REG_SS, temp_RSP + 4);
|
||||
raw_cs_selector = read_virtual_word(BX_SEG_REG_SS, temp_RSP + 2);
|
||||
new_rip = (Bit64u) read_virtual_word(BX_SEG_REG_SS, temp_RSP + 0);
|
||||
new_eflags = read_virtual_word(BX_SEG_REG_SS, temp_RSP + 4);
|
||||
top_nbytes_same = 6;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.217 2008-04-20 18:17:14 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.218 2008-04-20 21:44:13 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -2049,8 +2049,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i)
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSENTER(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_SUPPORT_SEP
|
||||
if (!protected_mode()) {
|
||||
BX_ERROR(("SYSENTER not from protected mode !"));
|
||||
if (real_mode()) {
|
||||
BX_ERROR(("SYSENTER not recognized in real mode !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) {
|
||||
@ -2148,8 +2148,8 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSENTER(bxInstruction_c *i)
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSEXIT(bxInstruction_c *i)
|
||||
{
|
||||
#if BX_SUPPORT_SEP
|
||||
if (!protected_mode() || CPL != 0) {
|
||||
BX_ERROR(("SYSEXIT not from protected mode with CPL=0 !"));
|
||||
if (real_mode() || CPL != 0) {
|
||||
BX_ERROR(("SYSEXIT from real mode or with CPL<>0 !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ret_far.cc,v 1.15 2008-03-26 16:25:05 sshwarts Exp $
|
||||
// $Id: ret_far.cc,v 1.16 2008-04-20 21:44:13 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005 Stanislav Shwartsman
|
||||
@ -141,6 +141,8 @@ BX_CPU_C::return_protected(bxInstruction_c *i, Bit16u pop_bytes)
|
||||
/* + 2: CS | + 4: CS | + 8: CS */
|
||||
/* + 0: IP | + 0: EIP | + 0: RIP */
|
||||
|
||||
BX_DEBUG(("return_protected: return to OUTER PRIVILEGE LEVEL"));
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (i->os64L()) {
|
||||
/* top 32+immediate bytes on stack must be within stack limits, else #SS(0) */
|
||||
|
Loading…
Reference in New Issue
Block a user