From e812f81e7ba9776c925a9db4da7c0474a2bac8ee Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Tue, 25 Sep 2007 16:11:32 +0000 Subject: [PATCH] Fixes in zero upper ECX --- bochs/cpu/cpu.cc | 7 ++++--- bochs/cpu/ctrl_xfer64.cc | 13 ++++++++----- bochs/cpu/ctrl_xfer_pro.cc | 13 +++++++------ bochs/cpu/io.cc | 10 +++++----- bochs/cpu/proc_ctrl.cc | 13 ++++++++++--- bochs/cpu/protect_ctrl.cc | 9 ++++++++- bochs/cpu/ret_far.cc | 11 +++-------- bochs/cpu/segment_ctrl_pro.cc | 23 ++++++++++++----------- bochs/cpu/string.cc | 8 ++++---- 9 files changed, 61 insertions(+), 46 deletions(-) diff --git a/bochs/cpu/cpu.cc b/bochs/cpu/cpu.cc index 1c8d36fe1..647128f3c 100644 --- a/bochs/cpu/cpu.cc +++ b/bochs/cpu/cpu.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.cc,v 1.172 2007-07-09 15:16:10 sshwarts Exp $ +// $Id: cpu.cc,v 1.173 2007-09-25 16:11:31 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -116,6 +116,7 @@ static unsigned iCacheMisses=0; #if BX_SUPPORT_X86_64==0 #define RIP EIP #define RSP ESP +#define RCX ECX #endif BX_CPP_INLINE bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased) @@ -330,7 +331,7 @@ void BX_CPU_C::repeat(bxInstruction_c *i, BxExecutePtr_t execute) if (ECX != 0) { BX_CPU_CALL_METHOD(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); - ECX --; + RCX = ECX - 1; } if (ECX == 0) return; } @@ -381,7 +382,7 @@ void BX_CPU_C::repeat_ZFL(bxInstruction_c *i, BxExecutePtr_t execute) if (ECX != 0) { BX_CPU_CALL_METHOD(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); - ECX --; + RCX = ECX - 1; } if ((i->repUsedValue()==3) && (get_ZF()==0)) return; if ((i->repUsedValue()==2) && (get_ZF()!=0)) return; diff --git a/bochs/cpu/ctrl_xfer64.cc b/bochs/cpu/ctrl_xfer64.cc index 4448077cc..f157a7a7d 100644 --- a/bochs/cpu/ctrl_xfer64.cc +++ b/bochs/cpu/ctrl_xfer64.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: ctrl_xfer64.cc,v 1.47 2006-06-09 22:29:06 sshwarts Exp $ +// $Id: ctrl_xfer64.cc,v 1.48 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -330,7 +330,8 @@ void BX_CPU_C::LOOPNE64_Jb(bxInstruction_c *i) } } else { - if (((--ECX) != 0) && (get_ZF()==0)) { + RCX = ECX - 1; + if (RCX != 0 && (get_ZF()==0)) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP); return; @@ -343,14 +344,15 @@ void BX_CPU_C::LOOPNE64_Jb(bxInstruction_c *i) void BX_CPU_C::LOOPE64_Jb(bxInstruction_c *i) { if (i->as64L()) { - if (((--RCX)!=0) && (get_ZF())) { + if (((--RCX)!=0) && get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP); return; } } else { - if (((--ECX)!=0) && get_ZF()) { + RCX = ECX - 1; + if (RCX != 0 && get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP); return; @@ -370,7 +372,8 @@ void BX_CPU_C::LOOP64_Jb(bxInstruction_c *i) } } else { - if ((--ECX) != 0) { + RCX = ECX - 1; + if (RCX != 0) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP); return; diff --git a/bochs/cpu/ctrl_xfer_pro.cc b/bochs/cpu/ctrl_xfer_pro.cc index 4a838a755..0b93a8a1f 100644 --- a/bochs/cpu/ctrl_xfer_pro.cc +++ b/bochs/cpu/ctrl_xfer_pro.cc @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////// -// $Id: ctrl_xfer_pro.cc,v 1.57 2007-09-10 20:47:08 sshwarts Exp $ +// $Id: ctrl_xfer_pro.cc,v 1.58 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -49,8 +49,7 @@ void BX_CPU_C::check_cs(bx_descriptor_t *descriptor, Bit16u cs_raw, Bit8u check_ } #if BX_SUPPORT_X86_64 - if (descriptor->u.segment.l) - { + if (descriptor->u.segment.l) { if (! BX_CPU_THIS_PTR efer.lma) { BX_PANIC(("check_cs: attempt to jump to long mode without enabling EFER.LMA !")); } @@ -111,8 +110,11 @@ BX_CPU_C::load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cp loadSRegLMNominal(BX_SEG_REG_CS, selector->value, cpl); } else { - BX_DEBUG(("Compatibility Mode Activated")); BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT; + BX_DEBUG(("Compatibility Mode Activated")); + if (BX_CPU_THIS_PTR dword.rip_upper != 0) { + BX_PANIC(("handleCpuModeChange: leaving long mode with RIP upper != 0 !")); + } } } #endif @@ -178,8 +180,7 @@ void BX_CPU_C::branch_far64(bx_selector_t *selector, bx_descriptor_t *descriptor, bx_address rip, Bit8u cpl) { #if BX_SUPPORT_X86_64 - if (descriptor->u.segment.l) - { + if (descriptor->u.segment.l) { if (! IsCanonical(rip)) { BX_ERROR(("branch_far: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0, 0); diff --git a/bochs/cpu/io.cc b/bochs/cpu/io.cc index 754cff1cd..d97cf4c83 100644 --- a/bochs/cpu/io.cc +++ b/bochs/cpu/io.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: io.cc,v 1.38 2007-07-09 15:16:12 sshwarts Exp $ +// $Id: io.cc,v 1.39 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -423,9 +423,9 @@ void BX_CPU_C::INSW_YwDX(bxInstruction_c *i) else #endif if (i->as32L()) - ECX -= (wordCount-1); + RCX = ECX - (wordCount-1); else - CX -= (wordCount-1); + CX -= (wordCount-1); incr = wordCount << 1; // count * 2. goto doIncr; @@ -658,9 +658,9 @@ void BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i) else #endif if (i->as32L()) - ECX -= (wordCount-1); + RCX = ECX - (wordCount-1); else - CX -= (wordCount-1); + CX -= (wordCount-1); incr = wordCount << 1; // count * 2. goto doIncr; } diff --git a/bochs/cpu/proc_ctrl.cc b/bochs/cpu/proc_ctrl.cc index 7354b8727..52376726e 100644 --- a/bochs/cpu/proc_ctrl.cc +++ b/bochs/cpu/proc_ctrl.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: proc_ctrl.cc,v 1.169 2007-09-20 17:33:35 sshwarts Exp $ +// $Id: proc_ctrl.cc,v 1.170 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1223,6 +1223,9 @@ void BX_CPU_C::handleCpuModeChange(void) } else { BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT; + if (BX_CPU_THIS_PTR dword.rip_upper != 0) { + BX_PANIC(("handleCpuModeChange: leaving long mode with RIP upper != 0 !")); + } BX_DEBUG(("Compatibility Mode Activated")); } } @@ -1309,6 +1312,10 @@ void BX_CPU_C::SetCR0(Bit32u val_32) } } else if (prev_pg==1 && ! BX_CPU_THIS_PTR cr0.get_PG()) { + if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { + BX_ERROR(("SetCR0: attempt to leave 64 bit mode directly to legacy mode !")); + exception(BX_GP_EXCEPTION, 0, 0); + } if (BX_CPU_THIS_PTR efer.lma) { if (BX_CPU_THIS_PTR dword.rip_upper != 0) { BX_PANIC(("SetCR0: attempt to leave x86-64 LONG mode with RIP upper != 0 !!!")); @@ -1433,8 +1440,8 @@ void BX_CPU_C::RDPMC(bxInstruction_c *i) // writes. Misaligned etc... But to monitor bochs, this // is easier done from the host. - EAX = 0; - EDX = 0; // if P4 and ECX & 0x10000000, then always 0 (short read 32 bits) + RAX = 0; + RDX = 0; // if P4 and ECX & 0x10000000, then always 0 (short read 32 bits) BX_ERROR(("RDPMC: Performance Counters Support not reasonably implemented yet")); } else { diff --git a/bochs/cpu/protect_ctrl.cc b/bochs/cpu/protect_ctrl.cc index 15e1e2523..6aa9148cb 100644 --- a/bochs/cpu/protect_ctrl.cc +++ b/bochs/cpu/protect_ctrl.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: protect_ctrl.cc,v 1.58 2007-03-23 14:50:45 sshwarts Exp $ +// $Id: protect_ctrl.cc,v 1.59 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -452,6 +452,13 @@ void BX_CPU_C::LTR_Ew(bxInstruction_c *i) exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0); } +#if BX_SUPPORT_X86_64 + if (long_mode() && descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS) { + BX_ERROR(("LTR: doesn't point to an available TSS386 descriptor in long mode!")); + exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0); + } +#endif + /* #NP(selector) if TSS descriptor is not present */ if (! IS_PRESENT(descriptor)) { BX_ERROR(("LTR: LDT descriptor not present!")); diff --git a/bochs/cpu/ret_far.cc b/bochs/cpu/ret_far.cc index 276c32d0c..c17e0f480 100755 --- a/bochs/cpu/ret_far.cc +++ b/bochs/cpu/ret_far.cc @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////// -// $Id: ret_far.cc,v 1.9 2007-02-03 21:36:40 sshwarts Exp $ +// $Id: ret_far.cc,v 1.10 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -68,13 +68,8 @@ BX_CPU_C::return_protected(bxInstruction_c *i, Bit16u pop_bytes) #if BX_SUPPORT_X86_64 if (i->os64L()) { - /* operand size=64: 2nd qword on stack must be within stack limits, - * else #SS(0); */ - if (!can_pop(16)) - { - BX_ERROR(("return_protected: 2rd qword not in stack limits")); - exception(BX_SS_EXCEPTION, 0, 0); - } + /* operand size=64: in long mode 1st and 2nd quadword on the stack + must be in canonical address space */ read_virtual_word (BX_SEG_REG_SS, temp_RSP + 8, &raw_cs_selector); read_virtual_qword(BX_SEG_REG_SS, temp_RSP + 0, &return_RIP); diff --git a/bochs/cpu/segment_ctrl_pro.cc b/bochs/cpu/segment_ctrl_pro.cc index 283775352..b3ba085d3 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.70 2007-09-10 20:47:08 sshwarts Exp $ +// $Id: segment_ctrl_pro.cc,v 1.71 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -38,10 +38,16 @@ BX_CPU_C::load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value) { if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]) { + bx_selector_t ss_selector; + bx_descriptor_t descriptor; + Bit32u dword1, dword2; + + parse_selector(new_value, &ss_selector); + if ((new_value & 0xfffc) == 0) { /* null selector */ #if BX_SUPPORT_X86_64 - // allow SS = 0 in 64 bit mode with cpl != 3 - if (BX_CPU_THIS_PTR efer.lma && CPL != 3) { + // allow SS = 0 in 64 bit mode only with cpl != 3 and rpl=cpl + if (Is64BitMode() && CPL != 3 && ss_selector.rpl == CPL) { seg->selector.index = 0; seg->selector.ti = 0; seg->selector.rpl = 0; @@ -50,15 +56,10 @@ BX_CPU_C::load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value) return; } #endif - BX_ERROR(("load_seg_reg(SS): new_value == 0")); - exception(BX_GP_EXCEPTION, 0, 0); + BX_ERROR(("load_seg_reg(SS): loading null selector")); + exception(BX_GP_EXCEPTION, new_value & 0xfffc, 0); } - bx_descriptor_t descriptor; - Bit32u dword1, dword2; - bx_selector_t ss_selector; - - parse_selector(new_value, &ss_selector); fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); /* selector's RPL must = CPL, else #GP(selector) */ @@ -257,7 +258,7 @@ void BX_CPU_C::loadSRegLMNominal(unsigned segI, unsigned selector, unsigned dpl) // of type bx_addr and be maxed to 64bits, not 32. seg->cache.u.segment.limit_scaled = 0xffffffff; seg->cache.valid = 1; - seg->cache.dpl = dpl; // (KPL) Not sure if we need this. + seg->cache.dpl = dpl; seg->selector.value = selector; } diff --git a/bochs/cpu/string.cc b/bochs/cpu/string.cc index 4174ce16b..7f771d440 100644 --- a/bochs/cpu/string.cc +++ b/bochs/cpu/string.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: string.cc,v 1.37 2007-07-09 15:16:14 sshwarts Exp $ +// $Id: string.cc,v 1.38 2007-09-25 16:11:32 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1049,7 +1049,7 @@ void BX_CPU_C::MOVSD_XdYd(bxInstruction_c *i) // Decrement eCX. Note, the main loop will decrement 1 also, so // decrement by one less than expected, like the case above. - ECX -= (dwordCount-1); + RCX = ECX - (dwordCount-1); incr = dwordCount << 2; // count * 4 goto doIncr32; @@ -1843,9 +1843,9 @@ void BX_CPU_C::STOSB_YbAL(bxInstruction_c *i) // Decrement eCX. Note, the main loop will decrement 1 also, so // decrement by one less than expected, like the case above. if (i->as32L()) - ECX -= (byteCount-1); + RCX = ECX - (byteCount-1); else - CX -= (byteCount-1); + CX -= (byteCount-1); incr = byteCount; goto doIncr16;