From f6cb9e529fc820239a6a8cdde9923247a0e29b90 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Mon, 2 Feb 2009 18:59:44 +0000 Subject: [PATCH] Fixes for VMX emulation --- bochs/cpu/cpu.cc | 33 +++++++++++++++------------------ bochs/cpu/cpu.h | 4 ++-- bochs/cpu/proc_ctrl.cc | 4 ++-- bochs/cpu/vmexit.cc | 16 ++++++++++------ bochs/cpu/vmx.cc | 9 ++++++--- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/bochs/cpu/cpu.cc b/bochs/cpu/cpu.cc index a0622c5fc..60045dbfd 100644 --- a/bochs/cpu/cpu.cc +++ b/bochs/cpu/cpu.cc @@ -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; diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index af5813f3d..ad4b2683a 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -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); diff --git a/bochs/cpu/proc_ctrl.cc b/bochs/cpu/proc_ctrl.cc index 8f6cc4457..4b7e97c43 100644 --- a/bochs/cpu/proc_ctrl.cc +++ b/bochs/cpu/proc_ctrl.cc @@ -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 diff --git a/bochs/cpu/vmexit.cc b/bochs/cpu/vmexit.cc index 59d8e5e3d..a5fe57555 100755 --- a/bochs/cpu/vmexit.cc +++ b/bochs/cpu/vmexit.cc @@ -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) diff --git a/bochs/cpu/vmx.cc b/bochs/cpu/vmx.cc index 81dc92f99..5f6cc1534 100755 --- a/bochs/cpu/vmx.cc +++ b/bochs/cpu/vmx.cc @@ -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;