Fixed ugly load_ss64/mode changing workaround in exception.cc

This commit is contained in:
Stanislav Shwartsman 2005-08-03 21:10:42 +00:00
parent a096472646
commit 3681126235
4 changed files with 34 additions and 72 deletions

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: call_far.cc,v 1.4 2005-08-02 20:20:21 sshwarts Exp $
// $Id: call_far.cc,v 1.5 2005-08-03 21:10:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -449,10 +449,9 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
// Help for OS/2
BX_CPU_THIS_PTR except_chk = 0;
return;
}
// CALL GATE TO SAME PRIVILEGE
else {
else // CALL GATE TO SAME PRIVILEGE
{
BX_DEBUG(("CALL GATE TO SAME PRIVILEGE"));
#if BX_SUPPORT_X86_64
@ -478,10 +477,7 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
// load code segment descriptor into CS register
// set RPL of CS to CPL
branch_far64(&cs_selector, &cs_descriptor, new_EIP, CPL);
return;
}
BX_PANIC(("call_protected: call gate: should not get here"));
return;
default:

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.230 2005-08-02 18:44:15 sshwarts Exp $
// $Id: cpu.h,v 1.231 2005-08-03 21:10:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2796,7 +2796,6 @@ public: // for now...
#if BX_SUPPORT_X86_64
BX_SMF void fetch_raw_descriptor64(bx_selector_t *selector,
Bit32u *dword1, Bit32u *dword2, Bit32u *dword3, Bit8u exception_no);
BX_SMF void load_ss64(Bit8u cpl) BX_CPP_AttrRegparmN(1);
BX_SMF void loadSRegLMNominal(unsigned seg, unsigned selector,
bx_address base, unsigned dpl);
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.60 2005-08-02 20:20:21 sshwarts Exp $
// $Id: exception.cc,v 1.61 2005-08-03 21:10:41 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -90,9 +90,9 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
if (gate_descriptor.type != BX_386_INTERRUPT_GATE &&
gate_descriptor.type != BX_386_TRAP_GATE)
{
BX_ERROR(("interrupt(long mode): unsupported gate type %u",
BX_ERROR(("interrupt(long mode): unsupported gate type %u",
(unsigned) gate_descriptor.type));
exception(BX_GP_EXCEPTION, vector*16 + 2, 0);
exception(BX_GP_EXCEPTION, vector*16 + 2, 0);
}
// if software interrupt, then gate descripor DPL must be >= CPL,
@ -126,8 +126,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
// selector must be within its descriptor table limits
// else #GP(selector+EXT)
fetch_raw_descriptor(&cs_selector, &dword1, &dword2,
BX_GP_EXCEPTION);
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
parse_descriptor(dword1, dword2, &cs_descriptor);
// descriptor AR byte must indicate code seg
@ -142,8 +141,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
}
// check that it's a 64 bit segment
if ( cs_descriptor.u.segment.l == 0 ||
cs_descriptor.u.segment.d_b == 1)
if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_descriptor.u.segment.d_b)
{
BX_ERROR(("interrupt(long mode): must be 64 bit segment"));
exception(BX_GP_EXCEPTION, vector, 0);
@ -172,53 +170,44 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
get_RSP_from_TSS(cs_descriptor.dpl, &RSP_for_cpl_x);
}
if (! IsCanonical(RSP)) {
BX_ERROR(("interrupt(long mode): canonical address failure %08x%08x",
(Bit32u)(RSP >> 32), (Bit32u)(RSP & 0xffffffff)));
exception(BX_GP_EXCEPTION, 0, 0);
}
Bit16u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_RIP = RIP;
Bit16u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
bx_selector_t ss_selector;
bx_descriptor_t ss_descriptor;
// set up a null descriptor
parse_selector(0, &ss_selector);
parse_descriptor(0, 0, &ss_descriptor);
// load CS:RIP (guaranteed to be in 64 bit mode)
branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, cs_descriptor.dpl);
// set up null SS descriptor
load_ss64(cs_descriptor.dpl);
load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
// === WORKAROUND ===
// need to switch to 64 bit mode temporarily here.
// this means that any exception after here might be delivered
// a little insanely. Like faults are page faults..
unsigned savemode = BX_CPU_THIS_PTR cpu_mode;
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_64;
// load new RSP values from TSS
RSP = RSP_for_cpl_x;
// load new CS:IP values from gate
// set CPL to new code segment DPL
CPL = cs_descriptor.dpl;
// set RPL of CS to CPL
// push long pointer to old stack onto new stack
// skip segmentation checks
// align ESP
/* the size of the gate controls the size of the stack pushes */
// push old stack long pointer onto new stack
push_64(old_SS);
push_64(old_RSP);
// push EFLAGS
push_64(read_eflags());
// push long pointer to return address onto new stack
push_64(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
push_64(RIP);
push_64(old_CS);
push_64(old_RIP);
if ( is_error_code )
push_64(error_code);
// restore the original cpu mode
BX_CPU_THIS_PTR cpu_mode = savemode;
load_cs(&cs_selector, &cs_descriptor, cs_descriptor.dpl);
RIP = gate_dest_offset;
// if INTERRUPT GATE set IF to 0
if ( !(gate_descriptor.type & 1) ) // even is int-gate
BX_CPU_THIS_PTR clear_IF ();
@ -257,11 +246,8 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
if ( is_error_code )
push_64(error_code);
// load CS:IP from gate
// load CS descriptor
// set the RPL field of CS to CPL
load_cs(&cs_selector, &cs_descriptor, CPL);
RIP = gate_dest_offset;
branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, CPL);
// if interrupt gate then set IF to 0
if ( !(gate_descriptor.type & 1) ) // even is int-gate

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: segment_ctrl_pro.cc,v 1.46 2005-08-02 20:20:22 sshwarts Exp $
// $Id: segment_ctrl_pro.cc,v 1.47 2005-08-03 21:10:42 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -562,25 +562,6 @@ BX_CPU_C::load_ldtr(bx_selector_t *selector, bx_descriptor_t *descriptor)
BX_CPU_THIS_PTR ldtr.cache.valid = 1;
}
#if BX_SUPPORT_X86_64
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::load_ss64(Bit8u cpl)
{
bx_selector_t selector;
bx_descriptor_t descriptor;
// set up a null descriptor
parse_selector(0, &selector);
parse_descriptor(0, 0, &descriptor);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector = selector;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache = descriptor;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = cpl;
loadSRegLMNominal(BX_SEG_REG_SS, selector.value, 0, cpl);
}
#endif
void BX_CPP_AttrRegparmN(3)
BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl)
{