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.
|
// 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
|
// Help for OS/2
|
||||||
BX_CPU_THIS_PTR except_chk = 0;
|
BX_CPU_THIS_PTR except_chk = 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// CALL GATE TO SAME PRIVILEGE
|
else // CALL GATE TO SAME PRIVILEGE
|
||||||
else {
|
{
|
||||||
BX_DEBUG(("CALL GATE TO SAME PRIVILEGE"));
|
BX_DEBUG(("CALL GATE TO SAME PRIVILEGE"));
|
||||||
|
|
||||||
#if BX_SUPPORT_X86_64
|
#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
|
// load code segment descriptor into CS register
|
||||||
// set RPL of CS to CPL
|
// set RPL of CS to CPL
|
||||||
branch_far64(&cs_selector, &cs_descriptor, new_EIP, CPL);
|
branch_far64(&cs_selector, &cs_descriptor, new_EIP, CPL);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BX_PANIC(("call_protected: call gate: should not get here"));
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
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.
|
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||||
@ -2796,7 +2796,6 @@ public: // for now...
|
|||||||
#if BX_SUPPORT_X86_64
|
#if BX_SUPPORT_X86_64
|
||||||
BX_SMF void fetch_raw_descriptor64(bx_selector_t *selector,
|
BX_SMF void fetch_raw_descriptor64(bx_selector_t *selector,
|
||||||
Bit32u *dword1, Bit32u *dword2, Bit32u *dword3, Bit8u exception_no);
|
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_SMF void loadSRegLMNominal(unsigned seg, unsigned selector,
|
||||||
bx_address base, unsigned dpl);
|
bx_address base, unsigned dpl);
|
||||||
#endif
|
#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.
|
// 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 &&
|
if (gate_descriptor.type != BX_386_INTERRUPT_GATE &&
|
||||||
gate_descriptor.type != BX_386_TRAP_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));
|
(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,
|
// 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
|
// selector must be within its descriptor table limits
|
||||||
// else #GP(selector+EXT)
|
// else #GP(selector+EXT)
|
||||||
fetch_raw_descriptor(&cs_selector, &dword1, &dword2,
|
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||||
BX_GP_EXCEPTION);
|
|
||||||
parse_descriptor(dword1, dword2, &cs_descriptor);
|
parse_descriptor(dword1, dword2, &cs_descriptor);
|
||||||
|
|
||||||
// descriptor AR byte must indicate code seg
|
// 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
|
// check that it's a 64 bit segment
|
||||||
if ( cs_descriptor.u.segment.l == 0 ||
|
if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_descriptor.u.segment.d_b)
|
||||||
cs_descriptor.u.segment.d_b == 1)
|
|
||||||
{
|
{
|
||||||
BX_ERROR(("interrupt(long mode): must be 64 bit segment"));
|
BX_ERROR(("interrupt(long mode): must be 64 bit segment"));
|
||||||
exception(BX_GP_EXCEPTION, vector, 0);
|
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);
|
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;
|
Bit16u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
|
||||||
Bit64u old_RSP = RSP;
|
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
|
// 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;
|
RSP = RSP_for_cpl_x;
|
||||||
|
|
||||||
// load new CS:IP values from gate
|
/* the size of the gate controls the size of the stack pushes */
|
||||||
// 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
|
|
||||||
|
|
||||||
|
// push old stack long pointer onto new stack
|
||||||
push_64(old_SS);
|
push_64(old_SS);
|
||||||
push_64(old_RSP);
|
push_64(old_RSP);
|
||||||
|
|
||||||
// push EFLAGS
|
|
||||||
push_64(read_eflags());
|
push_64(read_eflags());
|
||||||
|
|
||||||
// push long pointer to return address onto new stack
|
// push long pointer to return address onto new stack
|
||||||
push_64(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
|
push_64(old_CS);
|
||||||
push_64(RIP);
|
push_64(old_RIP);
|
||||||
if ( is_error_code )
|
if ( is_error_code )
|
||||||
push_64(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 INTERRUPT GATE set IF to 0
|
||||||
if ( !(gate_descriptor.type & 1) ) // even is int-gate
|
if ( !(gate_descriptor.type & 1) ) // even is int-gate
|
||||||
BX_CPU_THIS_PTR clear_IF ();
|
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 )
|
if ( is_error_code )
|
||||||
push_64(error_code);
|
push_64(error_code);
|
||||||
|
|
||||||
// load CS:IP from gate
|
|
||||||
// load CS descriptor
|
|
||||||
// set the RPL field of CS to CPL
|
// set the RPL field of CS to CPL
|
||||||
load_cs(&cs_selector, &cs_descriptor, CPL);
|
branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, CPL);
|
||||||
RIP = gate_dest_offset;
|
|
||||||
|
|
||||||
// if interrupt gate then set IF to 0
|
// if interrupt gate then set IF to 0
|
||||||
if ( !(gate_descriptor.type & 1) ) // even is int-gate
|
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.
|
// 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;
|
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)
|
void BX_CPP_AttrRegparmN(3)
|
||||||
BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl)
|
BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user