Initial NMI virtualization for VMX, clean out CPU pins set/clear code
This commit is contained in:
parent
30fec77004
commit
592484408f
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.cc,v 1.266 2009-02-02 18:59:44 sshwarts Exp $
|
||||
// $Id: cpu.cc,v 1.267 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -436,7 +436,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
{
|
||||
if ((BX_CPU_INTR && (BX_CPU_THIS_PTR get_IF() ||
|
||||
(BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_MWAIT_IF))) ||
|
||||
BX_CPU_THIS_PTR pending_NMI || BX_CPU_THIS_PTR pending_SMI)
|
||||
BX_CPU_THIS_PTR pending_NMI || BX_CPU_THIS_PTR pending_SMI || BX_CPU_THIS_PTR pending_INIT)
|
||||
{
|
||||
// interrupt ends the HALT condition
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
@ -493,18 +493,35 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
// STOPCLK
|
||||
// SMI
|
||||
// INIT
|
||||
// (bochs doesn't support these)
|
||||
if (BX_CPU_THIS_PTR pending_SMI && ! BX_CPU_THIS_PTR smm_mode())
|
||||
{
|
||||
// clear SMI pending flag and disable NMI when SMM was accepted
|
||||
BX_CPU_THIS_PTR pending_SMI = 0;
|
||||
BX_CPU_THIS_PTR disable_NMI = 1;
|
||||
enter_system_management_mode();
|
||||
}
|
||||
|
||||
if (BX_CPU_THIS_PTR pending_INIT && ! BX_CPU_THIS_PTR disable_INIT) {
|
||||
#if BX_SUPPORT_VMX
|
||||
if (BX_CPU_THIS_PTR in_vmx_guest) {
|
||||
BX_ERROR(("VMEXIT: INIT pin asserted"));
|
||||
VMexit(0, VMX_VMEXIT_INIT, 0);
|
||||
}
|
||||
#endif
|
||||
// reset will clear pending INIT
|
||||
BX_CPU_THIS_PTR reset(BX_RESET_SOFTWARE);
|
||||
}
|
||||
|
||||
// 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.
|
||||
exception(BX_DB_EXCEPTION, 0, 0); // no error, not interrupt
|
||||
}
|
||||
|
||||
// Priority 5: External Interrupts
|
||||
// NMI Interrupts
|
||||
@ -517,20 +534,15 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
// boundary.
|
||||
}
|
||||
#if BX_SUPPORT_VMX
|
||||
else if (BX_CPU_THIS_PTR intr_pending_vmx && BX_CPU_THIS_PTR get_IF())
|
||||
else if (! BX_CPU_THIS_PTR disable_NMI && BX_CPU_THIS_PTR in_vmx_guest &&
|
||||
VMEXIT(VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT))
|
||||
{
|
||||
// interrupt-window exiting
|
||||
BX_ERROR(("VMEXIT: Interrupt window exiting"));
|
||||
VMexit(0, VMX_VMEXIT_INTERRUPT_WINDOW, 0);
|
||||
// NMI-window exiting
|
||||
BX_ERROR(("VMEXIT: NMI window exiting"));
|
||||
VMexit(0, VMX_VMEXIT_NMI_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) {
|
||||
else if (BX_CPU_THIS_PTR pending_NMI && ! BX_CPU_THIS_PTR disable_NMI) {
|
||||
BX_CPU_THIS_PTR pending_NMI = 0;
|
||||
BX_CPU_THIS_PTR disable_NMI = 1;
|
||||
BX_CPU_THIS_PTR errorno = 0;
|
||||
@ -541,6 +553,13 @@ 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 vmx_interrupt_window && 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;
|
||||
@ -648,7 +667,7 @@ unsigned BX_CPU_C::handleAsyncEvent(void)
|
||||
|| (BX_CPU_THIS_PTR dr7 & 0xff)
|
||||
#endif
|
||||
#if BX_SUPPORT_VMX
|
||||
|| (BX_CPU_THIS_PTR intr_pending_vmx)
|
||||
|| (BX_CPU_THIS_PTR vmx_interrupt_window)
|
||||
#endif
|
||||
))
|
||||
BX_CPU_THIS_PTR async_event = 0;
|
||||
@ -835,9 +854,8 @@ void BX_CPU_C::deliver_SIPI(unsigned vector)
|
||||
|
||||
void BX_CPU_C::deliver_INIT(void)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR disable_INIT) {
|
||||
BX_CPU_THIS_PTR reset(BX_RESET_SOFTWARE);
|
||||
}
|
||||
BX_CPU_THIS_PTR pending_INIT = 1;
|
||||
BX_CPU_THIS_PTR async_event = 1;
|
||||
}
|
||||
|
||||
void BX_CPU_C::deliver_NMI(void)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.567 2009-02-02 18:59:44 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.568 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -924,7 +924,7 @@ public: // for now...
|
||||
bx_bool in_event;
|
||||
bx_bool in_vmx;
|
||||
bx_bool in_vmx_guest;
|
||||
bx_bool intr_pending_vmx;
|
||||
bx_bool vmx_interrupt_window;
|
||||
Bit64u vmcsptr;
|
||||
VMCS_CACHE vmcs;
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ctrl_xfer16.cc,v 1.65 2009-01-16 18:18:58 sshwarts Exp $
|
||||
// $Id: ctrl_xfer16.cc,v 1.66 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -601,12 +601,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET16(bxInstruction_c *i)
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
|
||||
#endif
|
||||
BX_CPU_THIS_PTR disable_NMI = 0;
|
||||
|
||||
#if BX_DEBUGGER
|
||||
BX_CPU_THIS_PTR show_flag |= Flag_iret;
|
||||
#endif
|
||||
|
||||
BX_CPU_THIS_PTR disable_NMI = 0;
|
||||
|
||||
BX_CPU_THIS_PTR speculative_rsp = 1;
|
||||
BX_CPU_THIS_PTR prev_rsp = RSP;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ctrl_xfer32.cc,v 1.82 2009-01-16 18:18:58 sshwarts Exp $
|
||||
// $Id: ctrl_xfer32.cc,v 1.83 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -641,12 +641,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
|
||||
|
||||
invalidate_prefetch_q();
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
|
||||
#endif
|
||||
BX_CPU_THIS_PTR disable_NMI = 0;
|
||||
|
||||
#if BX_DEBUGGER
|
||||
BX_CPU_THIS_PTR show_flag |= Flag_iret;
|
||||
#endif
|
||||
|
||||
BX_CPU_THIS_PTR disable_NMI = 0;
|
||||
|
||||
BX_CPU_THIS_PTR speculative_rsp = 1;
|
||||
BX_CPU_THIS_PTR prev_rsp = ESP;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
////////c/////////////////////////////////////////////////////////////////
|
||||
// $Id: ctrl_xfer64.cc,v 1.76 2009-01-16 18:18:58 sshwarts Exp $
|
||||
// $Id: ctrl_xfer64.cc,v 1.77 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -462,12 +462,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET64(bxInstruction_c *i)
|
||||
{
|
||||
invalidate_prefetch_q();
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
|
||||
#endif
|
||||
BX_CPU_THIS_PTR disable_NMI = 0;
|
||||
|
||||
#if BX_DEBUGGER
|
||||
BX_CPU_THIS_PTR show_flag |= Flag_iret;
|
||||
#endif
|
||||
|
||||
BX_CPU_THIS_PTR disable_NMI = 0;
|
||||
|
||||
BX_ASSERT(protected_mode());
|
||||
|
||||
BX_CPU_THIS_PTR speculative_rsp = 1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: init.cc,v 1.195 2009-01-31 11:53:57 sshwarts Exp $
|
||||
// $Id: init.cc,v 1.196 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -1021,7 +1021,7 @@ void BX_CPU_C::reset(unsigned source)
|
||||
#if BX_SUPPORT_VMX
|
||||
BX_CPU_THIS_PTR in_vmx = BX_CPU_THIS_PTR in_vmx_guest = 0;
|
||||
BX_CPU_THIS_PTR in_event = 0;
|
||||
BX_CPU_THIS_PTR intr_pending_vmx = 0;
|
||||
BX_CPU_THIS_PTR vmx_interrupt_window = 0;
|
||||
BX_CPU_THIS_PTR vmcsptr = BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: smm.cc,v 1.55 2009-01-31 10:43:23 sshwarts Exp $
|
||||
// $Id: smm.cc,v 1.56 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2006 Stanislav Shwartsman
|
||||
@ -116,6 +116,7 @@ void BX_CPU_C::enter_system_management_mode(void)
|
||||
// debug(BX_CPU_THIS_PTR prev_rip);
|
||||
|
||||
BX_CPU_THIS_PTR in_smm = 1;
|
||||
BX_CPU_THIS_PTR disable_NMI = 1;
|
||||
|
||||
Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n;
|
||||
// reset reserved bits
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmexit.cc,v 1.3 2009-02-02 18:59:44 sshwarts Exp $
|
||||
// $Id: vmexit.cc,v 1.4 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -126,8 +126,6 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_Instruction(bxInstruction_c *i, Bit
|
||||
VMexit(i, reason, qualification);
|
||||
}
|
||||
|
||||
#define VMEXIT(ctrl) (BX_CPU_THIS_PTR vmcs.vmexec_ctrls2 & (ctrl))
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_HLT(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
@ -222,10 +220,8 @@ void BX_CPU_C::VMexit_ExtInterrupt(void)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
|
||||
|
||||
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT) {
|
||||
if (! (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT)) {
|
||||
if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT)) {
|
||||
if (! PIN_VMEXIT(VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT)) {
|
||||
// interrupt wasn't acknowledged and still pending, interruption info is invalid
|
||||
VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_INFO, 0);
|
||||
VMexit(0, VMX_VMEXIT_EXTERNAL_INTERRUPT, 0);
|
||||
@ -244,12 +240,12 @@ void BX_CPU_C::VMexit_Event(bxInstruction_c *i, unsigned type, unsigned vector,
|
||||
switch(type) {
|
||||
case BX_EXTERNAL_INTERRUPT:
|
||||
reason = VMX_VMEXIT_EXTERNAL_INTERRUPT;
|
||||
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT)
|
||||
if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT))
|
||||
vmexit = 1;
|
||||
break;
|
||||
|
||||
case BX_NMI:
|
||||
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_NMI_VMEXIT)
|
||||
if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
|
||||
vmexit = 1;
|
||||
break;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmx.cc,v 1.4 2009-02-02 18:59:44 sshwarts Exp $
|
||||
// $Id: vmx.cc,v 1.5 2009-02-03 19:17:15 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -1194,13 +1194,15 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
else BX_CPU_THIS_PTR inhibit_mask = 0;
|
||||
}
|
||||
|
||||
if (BX_CPU_THIS_PTR inhibit_mask) {
|
||||
if (BX_CPU_THIS_PTR inhibit_mask)
|
||||
BX_CPU_THIS_PTR async_event = 1;
|
||||
}
|
||||
|
||||
if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED)
|
||||
BX_CPU_THIS_PTR disable_NMI = 1;
|
||||
|
||||
if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_INTERRUPT_WINDOW_VMEXIT) {
|
||||
BX_CPU_THIS_PTR async_event = 1;
|
||||
BX_CPU_THIS_PTR intr_pending_vmx = 1; // set up interrupt window exiting
|
||||
BX_CPU_THIS_PTR vmx_interrupt_window = 1; // set up interrupt window exiting
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
@ -1633,8 +1635,9 @@ void BX_CPU_C::VMexit(bxInstruction_c *i, Bit32u reason, Bit64u qualification)
|
||||
// STEP 4: Go back to VMX host
|
||||
//
|
||||
|
||||
BX_CPU_THIS_PTR disable_INIT = 1; // INIT is disabled in VMX root mode
|
||||
BX_CPU_THIS_PTR in_vmx_guest = 0;
|
||||
BX_CPU_THIS_PTR intr_pending_vmx = 0;
|
||||
BX_CPU_THIS_PTR vmx_interrupt_window = 0;
|
||||
|
||||
longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop
|
||||
}
|
||||
@ -1684,7 +1687,7 @@ void BX_CPU_C::VMXON(bxInstruction_c *i)
|
||||
|
||||
BX_CPU_THIS_PTR vmcsptr = BX_INVALID_VMCSPTR;
|
||||
BX_CPU_THIS_PTR in_vmx = 1;
|
||||
BX_CPU_THIS_PTR disable_INIT = 1;
|
||||
BX_CPU_THIS_PTR disable_INIT = 1; // INIT is disabled in VMX root mode
|
||||
// block and disable A20M;
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
@ -1965,6 +1968,7 @@ void BX_CPU_C::VMLAUNCH(bxInstruction_c *i)
|
||||
*/
|
||||
|
||||
BX_CPU_THIS_PTR in_vmx_guest = 1;
|
||||
BX_CPU_THIS_PTR disable_INIT = 0;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// STEP 7: Inject events to the guest
|
||||
@ -2664,7 +2668,7 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent)
|
||||
BXRS_HEX_PARAM_FIELD(vmx, vmcsptr, BX_CPU_THIS_PTR vmcsptr);
|
||||
BXRS_PARAM_BOOL(vmx, in_vmx, BX_CPU_THIS_PTR in_vmx);
|
||||
BXRS_PARAM_BOOL(vmx, in_vmx_guest, BX_CPU_THIS_PTR in_vmx_guest);
|
||||
BXRS_PARAM_BOOL(vmx, intr_pending_vmx, BX_CPU_THIS_PTR intr_pending_vmx);
|
||||
BXRS_PARAM_BOOL(vmx, vmx_interrupt_window, BX_CPU_THIS_PTR vmx_interrupt_window);
|
||||
|
||||
bx_list_c *vmcache = new bx_list_c(vmx, "VMCS_CACHE", 5);
|
||||
|
||||
|
@ -471,8 +471,7 @@ typedef struct bx_VMCS
|
||||
|
||||
#define VMX_VM_EXEC_CRTL1_SUPPORTED_BITS \
|
||||
(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT | \
|
||||
VMX_VM_EXEC_CTRL1_NMI_VMEXIT | \
|
||||
VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)
|
||||
VMX_VM_EXEC_CTRL1_NMI_VMEXIT)
|
||||
|
||||
#endif
|
||||
|
||||
@ -658,6 +657,9 @@ enum VMX_Activity_State {
|
||||
BX_VMX_LAST_ACTIVITY_STATE
|
||||
};
|
||||
|
||||
#define PIN_VMEXIT(ctrl) (BX_CPU_THIS_PTR vmcs.vmexec_ctrls1 & (ctrl))
|
||||
#define VMEXIT(ctrl) (BX_CPU_THIS_PTR vmcs.vmexec_ctrls2 & (ctrl))
|
||||
|
||||
#define BX_VMX_INTERRUPTS_BLOCKED_BY_STI (1 << 0)
|
||||
#define BX_VMX_INTERRUPTS_BLOCKED_BY_MOV_SS (1 << 1)
|
||||
#define BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED (1 << 2)
|
||||
|
Loading…
Reference in New Issue
Block a user