Fixes for VMX emulation

This commit is contained in:
Stanislav Shwartsman 2009-02-02 18:59:44 +00:00
parent 3a470c9d11
commit f6cb9e529f
5 changed files with 35 additions and 31 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.265 2009-02-01 20:47:06 sshwarts Exp $
// $Id: cpu.cc,v 1.266 2009-02-02 18:59:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -505,15 +505,6 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
// Priority 4: Traps on Previous Instruction
// Breakpoints
// Debug Trap Exceptions (TF flag set or data/IO breakpoint)
if (BX_CPU_THIS_PTR debug_trap &&
!(BX_CPU_THIS_PTR inhibit_mask & BX_INHIBIT_DEBUG))
{
// A trap may be inhibited on this boundary due to an instruction
// which loaded SS. If so we clear the inhibit_mask below
// and don't execute this code until the next boundary.
// Commit debug events to DR6
exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
}
// Priority 5: External Interrupts
// NMI Interrupts
@ -525,6 +516,20 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
// an opportunity to check interrupts on the next instruction
// boundary.
}
#if BX_SUPPORT_VMX
else if (BX_CPU_THIS_PTR intr_pending_vmx && BX_CPU_THIS_PTR get_IF())
{
// interrupt-window exiting
BX_ERROR(("VMEXIT: Interrupt window exiting"));
VMexit(0, VMX_VMEXIT_INTERRUPT_WINDOW, 0);
}
#endif
else if (BX_CPU_THIS_PTR debug_trap) {
// A trap may be inhibited on this boundary due to an instruction
// which loaded SS. If so we clear the inhibit_mask below
// and don't execute this code until the next boundary.
exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
}
else if (BX_CPU_THIS_PTR pending_NMI) {
BX_CPU_THIS_PTR pending_NMI = 0;
BX_CPU_THIS_PTR disable_NMI = 1;
@ -536,14 +541,6 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
BX_INSTR_HWINTERRUPT(BX_CPU_ID, 2, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP);
interrupt(2, BX_NMI, 0, 0);
}
#if BX_SUPPORT_VMX
else if (BX_CPU_THIS_PTR intr_pending_vmx && BX_CPU_THIS_PTR get_IF())
{
// interrupt-window exiting
BX_ERROR(("VMEXIT: Interrupt window exiting"));
VMexit(0, VMX_VMEXIT_INTERRUPT_WINDOW, 0);
}
#endif
else if (BX_CPU_INTR && BX_CPU_THIS_PTR get_IF() && BX_DBG_ASYNC_INTR)
{
Bit8u vector;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.566 2009-02-01 20:47:06 sshwarts Exp $
// $Id: cpu.h,v 1.567 2009-02-02 18:59:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -3415,7 +3415,7 @@ public: // for now...
BX_SMF bx_bool VMexit_CLTS(bxInstruction_c *i) BX_CPP_AttrRegparmN(1);
BX_SMF void VMexit_MSR(bxInstruction_c *i, unsigned op, Bit32u msr) BX_CPP_AttrRegparmN(3);
BX_SMF void VMexit_IO(bxInstruction_c *i, unsigned port, unsigned len) BX_CPP_AttrRegparmN(3);
BX_SMF void VMexit_LMSW(bxInstruction_c *i, Bit32u msw) BX_CPP_AttrRegparmN(2);
BX_SMF Bit32u VMexit_LMSW(bxInstruction_c *i, Bit32u msw) BX_CPP_AttrRegparmN(2);
BX_SMF bx_address VMexit_CR0_Write(bxInstruction_c *i, bx_address) BX_CPP_AttrRegparmN(2);
BX_SMF void VMexit_CR3_Read(bxInstruction_c *i) BX_CPP_AttrRegparmN(1);
BX_SMF void VMexit_CR3_Write(bxInstruction_c *i, bx_address) BX_CPP_AttrRegparmN(2);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.280 2009-02-01 20:47:06 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.281 2009-02-02 18:59:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -870,7 +870,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LMSW_Ew(bxInstruction_c *i)
// LMSW does not affect PG,CD,NW,AM,WP,NE,ET bits, and cannot clear PE
#if BX_SUPPORT_VMX
VMexit_LMSW(i, msw);
msw = VMexit_LMSW(i, msw);
#endif
// LMSW cannot clear PE

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: vmexit.cc,v 1.2 2009-02-01 22:23:33 sshwarts Exp $
// $Id: vmexit.cc,v 1.3 2009-02-02 18:59:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009 Stanislav Shwartsman
@ -515,21 +515,22 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_CLTS(bxInstruction_c *i)
return 0;
}
void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_LMSW(bxInstruction_c *i, Bit32u msw)
Bit32u BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_LMSW(bxInstruction_c *i, Bit32u msw)
{
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
if (! BX_CPU_THIS_PTR in_vmx_guest) return msw;
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
Bit32u mask = vm->vm_cr0_mask & 0xF; /* LMSW affects only low 4 bits */
bx_bool vmexit = 0;
if ((vm->vm_cr0_mask & msw & 0x1) != 0 && (vm->vm_cr0_read_shadow & 0x1) == 0)
if ((mask & msw & 0x1) != 0 && (vm->vm_cr0_read_shadow & 0x1) == 0)
vmexit = 1;
if ((vm->vm_cr0_mask & vm->vm_cr0_read_shadow & 0xE) != (vm->vm_cr0_mask & msw & 0xE))
if ((mask & vm->vm_cr0_read_shadow & 0xE) != (mask & msw & 0xE))
vmexit = 1;
if (vmexit) {
BX_ERROR(("VMEXIT: CR0 write by LMSW"));
BX_ERROR(("VMEXIT: CR0 write by LMSW of value 0x%04x", msw));
Bit64u qualification = VMX_VMEXIT_CR_ACCESS_LMSW << 4;
qualification |= msw << 16;
@ -540,6 +541,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_LMSW(bxInstruction_c *i, Bit32u msw
VMexit(i, VMX_VMEXIT_CR_ACCESS, qualification);
}
// keep untouched all the bits set in CR0 mask
return (BX_CPU_THIS_PTR cr0.get32() & mask) | (msw & ~mask);
}
bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_CR0_Write(bxInstruction_c *i, bx_address val)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: vmx.cc,v 1.3 2009-02-01 22:23:33 sshwarts Exp $
// $Id: vmx.cc,v 1.4 2009-02-02 18:59:44 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009 Stanislav Shwartsman
@ -1049,7 +1049,7 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
guest.tmpDR6 = VMread64(VMCS_GUEST_PENDING_DBG_EXCEPTIONS);
if (guest.tmpDR6 & BX_CONST64(0xFFFFFFFFFFFFAFF0)) {
BX_ERROR(("VMENTER FAIL: VMCS guest tmpDR6 reserved bits %08x:%08x", GET32H(guest.tmpDR6), GET32L(guest.tmpDR6)));
BX_ERROR(("VMENTER FAIL: VMCS guest tmpDR6 reserved bits"));
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
}
@ -1180,7 +1180,10 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
BX_CPU_THIS_PTR debug_trap = 0;
}
else {
BX_CPU_THIS_PTR debug_trap = guest.tmpDR6 & 0x0000400f;
if (guest.tmpDR6 & (1 << 12))
BX_CPU_THIS_PTR debug_trap = guest.tmpDR6 & 0x0000400F;
else
BX_CPU_THIS_PTR debug_trap = guest.tmpDR6 & 0x00004000;
if (BX_CPU_THIS_PTR debug_trap)
BX_CPU_THIS_PTR async_event = 1;