Initial NMI virtualization for VMX, clean out CPU pins set/clear code

This commit is contained in:
Stanislav Shwartsman 2009-02-03 19:17:15 +00:00
parent 30fec77004
commit 592484408f
10 changed files with 81 additions and 51 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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)