CLFLUSH do not fault when checking execute only segment
This commit is contained in:
parent
ed3fdad74d
commit
82b7eaabd5
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: access.cc,v 1.69 2007-07-31 20:25:52 sshwarts Exp $
|
||||
// $Id: access.cc,v 1.70 2007-10-10 21:48:46 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -23,6 +23,8 @@
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define NEED_CPU_REG_SHORTCUTS 1
|
||||
#include "bochs.h"
|
||||
@ -45,7 +47,7 @@ BX_CPU_C::write_virtual_checks(bx_segment_reg_t *seg, bx_address offset,
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
// do canonical checks
|
||||
if (!IsCanonical(offset)) {
|
||||
BX_ERROR(("write_virtual_checks(): canonical Failure 0x%08x:%08x", GET32H(offset), GET32L(offset)));
|
||||
BX_ERROR(("write_virtual_checks(): canonical failure 0x%08x:%08x", GET32H(offset), GET32L(offset)));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
seg->cache.valid |= SegAccessWOK;
|
||||
@ -132,7 +134,7 @@ BX_CPU_C::read_virtual_checks(bx_segment_reg_t *seg, bx_address offset,
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
// do canonical checks
|
||||
if (!IsCanonical(offset)) {
|
||||
BX_ERROR(("read_virtual_checks(): canonical Failure 0x%08x:%08x", GET32H(offset), GET32L(offset)));
|
||||
BX_ERROR(("read_virtual_checks(): canonical failure 0x%08x:%08x", GET32H(offset), GET32L(offset)));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
seg->cache.valid |= SegAccessROK;
|
||||
@ -205,6 +207,93 @@ BX_CPU_C::read_virtual_checks(bx_segment_reg_t *seg, bx_address offset,
|
||||
}
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(3)
|
||||
BX_CPU_C::execute_virtual_checks(bx_segment_reg_t *seg, bx_address offset,
|
||||
unsigned length)
|
||||
{
|
||||
Bit32u upper_limit;
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
// do canonical checks
|
||||
if (!IsCanonical(offset)) {
|
||||
BX_ERROR(("execute_virtual_checks(): canonical failure 0x%08x:%08x", GET32H(offset), GET32L(offset)));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
seg->cache.valid |= SegAccessROK;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (protected_mode()) {
|
||||
if (seg->cache.valid==0) {
|
||||
BX_DEBUG(("execute_virtual_checks(): segment descriptor not valid"));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
|
||||
if (seg->cache.p == 0) { /* not present */
|
||||
BX_ERROR(("execute_virtual_checks(): segment not present"));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
|
||||
switch (seg->cache.type) {
|
||||
case 0: case 1: /* read only */
|
||||
case 2: case 3: /* read/write */
|
||||
case 10: case 11: /* execute/read */
|
||||
case 14: case 15: /* execute/read-only, conforming */
|
||||
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
||||
|| (length-1 > seg->cache.u.segment.limit_scaled))
|
||||
{
|
||||
BX_ERROR(("execute_virtual_checks(): read beyond limit"));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
if (seg->cache.u.segment.limit_scaled >= 7) {
|
||||
// Mark cache as being OK type for succeeding reads. See notes for
|
||||
// write checks; similar code.
|
||||
seg->cache.valid |= SegAccessROK;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8: case 9: /* execute only */
|
||||
case 12: case 13: /* execute only, conforming */
|
||||
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
||||
|| (length-1 > seg->cache.u.segment.limit_scaled))
|
||||
{
|
||||
BX_ERROR(("execute_virtual_checks(): read beyond limit"));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: case 5: /* read only, expand down */
|
||||
case 6: case 7: /* read/write, expand down */
|
||||
if (seg->cache.u.segment.d_b)
|
||||
upper_limit = 0xffffffff;
|
||||
else
|
||||
upper_limit = 0x0000ffff;
|
||||
if ((offset <= seg->cache.u.segment.limit_scaled) ||
|
||||
(offset > upper_limit) || ((upper_limit - offset) < (length - 1)))
|
||||
{
|
||||
BX_ERROR(("read_virtual_checks(): read beyond limit"));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else { /* real mode */
|
||||
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
||||
|| (length-1 > seg->cache.u.segment.limit_scaled))
|
||||
{
|
||||
BX_DEBUG(("execute_virtual_checks(): read beyond limit (real mode)"));
|
||||
exception(int_number(seg), 0, 0);
|
||||
}
|
||||
if (seg->cache.u.segment.limit_scaled >= 7) {
|
||||
// Mark cache as being OK type for succeeding reads. See notes for
|
||||
// write checks; similar code.
|
||||
seg->cache.valid |= SegAccessROK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char * BX_CPP_AttrRegparmN(1)
|
||||
BX_CPU_C::strseg(bx_segment_reg_t *seg)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.330 2007-10-09 19:49:23 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.331 2007-10-10 21:48:46 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -2745,6 +2745,7 @@ public: // for now...
|
||||
|
||||
BX_SMF void write_virtual_checks(bx_segment_reg_t *seg, bx_address offset, unsigned length) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void read_virtual_checks(bx_segment_reg_t *seg, bx_address offset, unsigned length) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void execute_virtual_checks(bx_segment_reg_t *seg, bx_address offset, unsigned length) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void write_virtual_byte(unsigned seg, bx_address offset, Bit8u *data) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void write_virtual_word(unsigned seg, bx_address offset, Bit16u *data) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void write_virtual_dword(unsigned seg, bx_address offset, Bit32u *data) BX_CPP_AttrRegparmN(3);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.171 2007-09-28 19:51:44 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.172 2007-10-10 21:48:46 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -190,7 +190,7 @@ void BX_CPU_C::CLFLUSH(bxInstruction_c *i)
|
||||
|
||||
#if BX_SUPPORT_CLFLUSH
|
||||
// check if we could access the memory
|
||||
read_virtual_checks(&BX_CPU_THIS_PTR sregs[i->seg()], RMAddr(i), 1);
|
||||
execute_virtual_checks(&BX_CPU_THIS_PTR sregs[i->seg()], RMAddr(i), 1);
|
||||
#else
|
||||
BX_INFO(("CLFLUSH: not supported, enable with SSE2"));
|
||||
UndefinedOpcode(i);
|
||||
|
@ -35,9 +35,6 @@ TODO (know issues in CPU model):
|
||||
This processor should yield to the other one, as we are anyhow waiting
|
||||
for a lock, and any other processor is responsible for this.
|
||||
|
||||
[!] CLFLUSH instructin should not crash in case of EXECUTE-ONLY segment
|
||||
access (according to AMD manuals)
|
||||
|
||||
[!] AMD and Intel x86_64 implementations are different.
|
||||
Currently Bochs emulation is according to Intel version.
|
||||
Do we need to support both ?
|
||||
|
Loading…
x
Reference in New Issue
Block a user