Fixed ugly load_ss64/mode changing workaround in exception.cc
This commit is contained in:
parent
a096472646
commit
3681126235
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user