- 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:
Stanislav Shwartsman 2008-04-20 21:44:13 +00:00
parent 280617288c
commit 24f1507fa9
4 changed files with 77 additions and 42 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) */