From 368112623547e6a7497927c781f3f19e8510e0ad Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Wed, 3 Aug 2005 21:10:42 +0000 Subject: [PATCH] Fixed ugly load_ss64/mode changing workaround in exception.cc --- bochs/cpu/call_far.cc | 10 ++--- bochs/cpu/cpu.h | 3 +- bochs/cpu/exception.cc | 72 ++++++++++++++--------------------- bochs/cpu/segment_ctrl_pro.cc | 21 +--------- 4 files changed, 34 insertions(+), 72 deletions(-) diff --git a/bochs/cpu/call_far.cc b/bochs/cpu/call_far.cc index 9116f1730..5791cfdc2 100755 --- a/bochs/cpu/call_far.cc +++ b/bochs/cpu/call_far.cc @@ -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: diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 4a170b33a..6da250b4a 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -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 diff --git a/bochs/cpu/exception.cc b/bochs/cpu/exception.cc index 7ae72706a..63f92cf9e 100644 --- a/bochs/cpu/exception.cc +++ b/bochs/cpu/exception.cc @@ -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 diff --git a/bochs/cpu/segment_ctrl_pro.cc b/bochs/cpu/segment_ctrl_pro.cc index ec11f9a90..76c191bd1 100644 --- a/bochs/cpu/segment_ctrl_pro.cc +++ b/bochs/cpu/segment_ctrl_pro.cc @@ -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) {