diff --git a/bochs/cpu/io.cc b/bochs/cpu/io.cc index a96b4e6c6..d2a2717a4 100644 --- a/bochs/cpu/io.cc +++ b/bochs/cpu/io.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: io.cc,v 1.43 2007-12-16 21:03:45 sshwarts Exp $ +// $Id: io.cc,v 1.44 2007-12-17 21:13:55 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -329,11 +329,9 @@ void BX_CPU_C::INSB_YbDX(bxInstruction_c *i) { Bit8u value8=0; - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { - BX_DEBUG(("INSB_YbDX: I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("INSB_YbDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } #if BX_SUPPORT_X86_64 @@ -391,140 +389,138 @@ void BX_CPU_C::INSB_YbDX(bxInstruction_c *i) // input word from port to string void BX_CPU_C::INSW_YwDX(bxInstruction_c *i) { - bx_address edi; - unsigned int incr = 2; - -#if BX_SUPPORT_X86_64 - if (i->as64L()) - edi = RDI; - else -#endif - if (i->as32L()) - edi = EDI; - else - edi = DI; - + bx_address rdi; + Bit32u incr = 2; Bit16u value16=0; -#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0) - /* If conditions are right, we can transfer IO to physical memory - * in a batch, rather than one instruction at a time. - */ - if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) { - Bit32u wordCount; - #if BX_SUPPORT_X86_64 - if (i->as64L()) - wordCount = RCX; // Truncated to 32bits. (we're only doing 1 page) + if (i->as64L()) { + rdi = RDI; + + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_word(BX_SEG_REG_ES, rdi, &value16); + + value16 = BX_INP(DX, 2); + + /* no seg override allowed */ + write_virtual_word(BX_SEG_REG_ES, rdi, &value16); + + if (BX_CPU_THIS_PTR get_DF()) + rdi -= 2; else -#endif - if (i->as32L()) - wordCount = ECX; - else - wordCount = CX; + rdi += 2; - BX_ASSERT(wordCount > 0); - wordCount = FastRepINSW(i, edi, DX, wordCount); - if (wordCount) - { - // Decrement the ticks count by the number of iterations, minus - // one, since the main cpu loop will decrement one. Also, - // the count is predecremented before examined, so defintely - // don't roll it under zero. - BX_TICKN(wordCount-1); - -#if BX_SUPPORT_X86_64 - if (i->as64L()) - RCX -= (wordCount-1); - else -#endif - if (i->as32L()) - RCX = ECX - (wordCount-1); - else - CX -= (wordCount-1); - - incr = wordCount << 1; // count * 2. - goto doIncr; - } + RDI = rdi; } + else +#endif + { + if (i->as32L()) + rdi = EDI; + else + rdi = DI; + +#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0) + /* If conditions are right, we can transfer IO to physical memory + * in a batch, rather than one instruction at a time. + */ + if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) + { + Bit32u wordCount; + + if (i->as32L()) + wordCount = ECX; + else + wordCount = CX; + + BX_ASSERT(wordCount > 0); + + wordCount = FastRepINSW(i, rdi, DX, wordCount); + if (wordCount) + { + // Decrement the ticks count by the number of iterations, minus + // one, since the main cpu loop will decrement one. Also, + // the count is predecremented before examined, so defintely + // don't roll it under zero. + BX_TICKN(wordCount-1); + + if (i->as32L()) + RCX = ECX - (wordCount-1); + else + CX -= (wordCount-1); + + incr = wordCount << 1; // count * 2. + goto doIncr; + } + } #endif - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_word(BX_SEG_REG_ES, edi, &value16); + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_word(BX_SEG_REG_ES, rdi, &value16); - value16 = BX_INP(DX, 2); + value16 = BX_INP(DX, 2); - /* no seg override allowed */ - write_virtual_word(BX_SEG_REG_ES, edi, &value16); - incr = 2; + /* no seg override allowed */ + write_virtual_word(BX_SEG_REG_ES, rdi, &value16); #if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0) doIncr: #endif -#if BX_SUPPORT_X86_64 - if (i->as64L()) { - if (BX_CPU_THIS_PTR get_DF()) - RDI = RDI - incr; - else - RDI = RDI + incr; - } - else -#endif - if (i->as32L()) { - if (BX_CPU_THIS_PTR get_DF()) - RDI = EDI - incr; - else - RDI = EDI + incr; - } - else { - if (BX_CPU_THIS_PTR get_DF()) - DI = DI - incr; - else - DI = DI + incr; + if (i->as32L()) { + if (BX_CPU_THIS_PTR get_DF()) + RDI = EDI - incr; + else + RDI = EDI + incr; + } + else { + if (BX_CPU_THIS_PTR get_DF()) + DI -= incr; + else + DI += incr; + } } } // input doubleword from port to string void BX_CPU_C::INSD_YdDX(bxInstruction_c *i) { - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { - BX_DEBUG(("INSD_YdDX: I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("INSD_YdDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } - bx_address edi; + bx_address rdi; #if BX_SUPPORT_X86_64 if (i->as64L()) - edi = RDI; + rdi = RDI; else #endif if (i->as32L()) - edi = EDI; + rdi = EDI; else - edi = DI; + rdi = DI; Bit32u value32=0; // Write a zero to memory, to trigger any segment or page // faults before reading from IO port. - write_virtual_dword(BX_SEG_REG_ES, edi, &value32); + write_virtual_dword(BX_SEG_REG_ES, rdi, &value32); value32 = BX_INP(DX, 4); /* no seg override allowed */ - write_virtual_dword(BX_SEG_REG_ES, edi, &value32); + write_virtual_dword(BX_SEG_REG_ES, rdi, &value32); #if BX_SUPPORT_X86_64 if (i->as64L()) { if (BX_CPU_THIS_PTR get_DF()) - RDI = RDI - 4; + RDI -= 4; else - RDI = RDI + 4; + RDI += 4; } else #endif @@ -536,9 +532,9 @@ void BX_CPU_C::INSD_YdDX(bxInstruction_c *i) } else { if (BX_CPU_THIS_PTR get_DF()) - DI = DI - 4; + DI -= 4; else - DI = DI + 4; + DI += 4; } } @@ -570,11 +566,9 @@ void BX_CPU_C::OUTSB_DXXb(bxInstruction_c *i) Bit8u value8; bx_address esi; - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { - BX_DEBUG(("OUTSB_DXXb: I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("OUTSB_DXXb: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } #if BX_SUPPORT_X86_64 @@ -618,13 +612,11 @@ void BX_CPU_C::OUTSB_DXXb(bxInstruction_c *i) void BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i) { bx_address esi; - unsigned incr = 2; + Bit32u incr = 2; - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { - BX_DEBUG(("OUTSW_DXXw: I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { + BX_DEBUG(("OUTSW_DXXw: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } #if BX_SUPPORT_X86_64 @@ -711,11 +703,9 @@ void BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i) // output doubleword string to port void BX_CPU_C::OUTSD_DXXd(bxInstruction_c *i) { - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { - BX_DEBUG(("OUTSD_DXXd: I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("OUTSD_DXXd: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } bx_address esi; diff --git a/bochs/cpu/io_pro.cc b/bochs/cpu/io_pro.cc index bd9e82c7a..84e543d0f 100644 --- a/bochs/cpu/io_pro.cc +++ b/bochs/cpu/io_pro.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: io_pro.cc,v 1.25 2007-11-29 21:45:10 sshwarts Exp $ +// $Id: io_pro.cc,v 1.26 2007-12-17 21:13:55 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -35,31 +35,21 @@ Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::inp16(Bit16u addr) { - Bit16u ret16; - - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(addr, 2)) { - BX_DEBUG(("inp16(): I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(addr, 2)) { + BX_DEBUG(("inp16(): I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } - ret16 = BX_INP(addr, 2); + Bit16u ret16 = BX_INP(addr, 2); return ret16; } void BX_CPP_AttrRegparmN(2) BX_CPU_C::outp16(Bit16u addr, Bit16u value) { - /* If CPL <= IOPL, then all IO addresses are accessible. - * Otherwise, must check the IO permission map on >286. - * On the 286, there is no IO permissions map */ - - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(addr, 2)) { - BX_DEBUG(("outp16(): I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(addr, 2)) { + BX_DEBUG(("outp16(): I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } BX_OUTP(addr, value, 2); @@ -68,31 +58,21 @@ BX_CPU_C::outp16(Bit16u addr, Bit16u value) Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::inp32(Bit16u addr) { - Bit32u ret32; - - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(addr, 4)) { - BX_DEBUG(("inp32(): I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(addr, 4)) { + BX_DEBUG(("inp32(): I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } - ret32 = BX_INP(addr, 4); + Bit32u ret32 = BX_INP(addr, 4); return ret32; } void BX_CPP_AttrRegparmN(2) BX_CPU_C::outp32(Bit16u addr, Bit32u value) { - /* If CPL <= IOPL, then all IO addresses are accessible. - * Otherwise, must check the IO permission map on >286. - * On the 286, there is no IO permissions map */ - - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(addr, 4)) { - BX_DEBUG(("outp32(): I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(addr, 4)) { + BX_DEBUG(("outp32(): I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } BX_OUTP(addr, value, 4); @@ -101,32 +81,21 @@ BX_CPU_C::outp32(Bit16u addr, Bit32u value) Bit8u BX_CPP_AttrRegparmN(1) BX_CPU_C::inp8(Bit16u addr) { - Bit8u ret8; - - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(addr, 1)) { - BX_DEBUG(("inp8(): I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(addr, 1)) { + BX_DEBUG(("inp8(): I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } - ret8 = BX_INP(addr, 1); + Bit8u ret8 = BX_INP(addr, 1); return ret8; } - void BX_CPP_AttrRegparmN(2) BX_CPU_C::outp8(Bit16u addr, Bit8u value) { - /* If CPL <= IOPL, then all IO addresses are accessible. - * Otherwise, must check the IO permission map on >286. - * On the 286, there is no IO permissions map */ - - if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - if (! BX_CPU_THIS_PTR allow_io(addr, 1)) { - BX_DEBUG(("outp8(): I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } + if (! BX_CPU_THIS_PTR allow_io(addr, 1)) { + BX_DEBUG(("outp8(): I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); } BX_OUTP(addr, value, 1); @@ -136,41 +105,48 @@ bx_bool BX_CPU_C::allow_io(Bit16u addr, unsigned len) { Bit16u io_base, permission16; - if (BX_CPU_THIS_PTR tr.cache.valid==0 || - BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS) + /* If CPL <= IOPL, then all IO addresses are accessible. + * Otherwise, must check the IO permission map on >286. + * On the 286, there is no IO permissions map */ + + if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) { - BX_ERROR(("allow_io(): TR doesn't point to a valid 32bit TSS")); - return(0); - } + if (BX_CPU_THIS_PTR tr.cache.valid==0 || + BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS) + { + BX_ERROR(("allow_io(): TR doesn't point to a valid 32bit TSS")); + return(0); + } - if (BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled < 103) { - BX_ERROR(("allow_io(): TR.limit < 103")); - return(0); - } + if (BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled < 103) { + BX_ERROR(("allow_io(): TR.limit < 103")); + return(0); + } - access_linear(BX_CPU_THIS_PTR tr.cache.u.system.base + 102, + access_linear(BX_CPU_THIS_PTR tr.cache.u.system.base + 102, 2, 0, BX_READ, &io_base); - if (io_base <= 103) { - BX_ERROR(("allow_io(): TR:io_base (%u) <= 103", io_base)); - return(0); - } + if (io_base <= 103) { + BX_ERROR(("allow_io(): TR:io_base (%u) <= 103", io_base)); + return(0); + } - if ( (Bit32s) (addr/8) >= (Bit32s) (BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled - io_base)) { - BX_ERROR(("allow_io(): IO addr %x (len %d) outside TSS IO permission map (base=%x, limit=%x) #GP(0)", - addr, len, io_base, BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled)); - return(0); - } + if ( (Bit32s) (addr/8) >= (Bit32s) (BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled - io_base)) { + BX_ERROR(("allow_io(): IO addr %x (len %d) outside TSS IO permission map (base=%x, limit=%x) #GP(0)", + addr, len, io_base, BX_CPU_THIS_PTR tr.cache.u.system.limit_scaled)); + return(0); + } - access_linear(BX_CPU_THIS_PTR tr.cache.u.system.base + io_base + addr/8, + access_linear(BX_CPU_THIS_PTR tr.cache.u.system.base + io_base + addr/8, 2, 0, BX_READ, &permission16); - unsigned bit_index = addr & 0x07; - permission16 >>= bit_index; - for (unsigned i=0; i>= 1; + unsigned bit_index = addr & 0x07; + permission16 >>= bit_index; + for (unsigned i=0; i>= 1; + } } return(1);