implementation of virtual NMI

This commit is contained in:
Stanislav Shwartsman 2013-03-05 21:12:43 +00:00
parent e9a8ef1d65
commit 1a770dd260
8 changed files with 53 additions and 19 deletions

View File

@ -1111,7 +1111,7 @@ public: // for now...
#define BX_EVENT_VMX_MONITOR_TRAP_FLAG (1 << 4)
#define BX_EVENT_VMX_PREEMPTION_TIMER_EXPIRED (1 << 5)
#define BX_EVENT_VMX_INTERRUPT_WINDOW_EXITING (1 << 6)
#define BX_EVENT_VMX_NMI_WINDOW_EXITING (1 << 7)
#define BX_EVENT_VMX_VIRTUAL_NMI (1 << 7)
#define BX_EVENT_SVM_VIRQ_PENDING (1 << 8)
#define BX_EVENT_PENDING_VMX_VIRTUAL_INTR (1 << 9)
#define BX_EVENT_PENDING_INTR (1 << 10)

View File

@ -551,9 +551,12 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET16(bxInstruction_c *i)
#endif
#if BX_SUPPORT_VMX
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_EXITING))
if (BX_CPU_THIS_PTR in_vmx_guest && PIN_VMEXIT(VMX_VM_EXEC_CTRL1_NMI_EXITING)) {
if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)) unmask_event(BX_EVENT_VMX_VIRTUAL_NMI);
}
else
#endif
unmask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
unmask_event(BX_EVENT_NMI);
#if BX_DEBUGGER
BX_CPU_THIS_PTR show_flag |= Flag_iret;

View File

@ -594,9 +594,12 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
#endif
#if BX_SUPPORT_VMX
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_EXITING))
if (BX_CPU_THIS_PTR in_vmx_guest && PIN_VMEXIT(VMX_VM_EXEC_CTRL1_NMI_EXITING)) {
if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)) unmask_event(BX_EVENT_VMX_VIRTUAL_NMI);
}
else
#endif
unmask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
unmask_event(BX_EVENT_NMI);
#if BX_DEBUGGER
BX_CPU_THIS_PTR show_flag |= Flag_iret;

View File

@ -433,9 +433,12 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET64(bxInstruction_c *i)
#endif
#if BX_SUPPORT_VMX
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_EXITING))
if (BX_CPU_THIS_PTR in_vmx_guest && PIN_VMEXIT(VMX_VM_EXEC_CTRL1_NMI_EXITING)) {
if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)) unmask_event(BX_EVENT_VMX_VIRTUAL_NMI);
}
else
#endif
unmask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
unmask_event(BX_EVENT_NMI);
#if BX_DEBUGGER
BX_CPU_THIS_PTR show_flag |= Flag_iret;

View File

@ -40,7 +40,7 @@ bx_bool BX_CPU_C::handleWaitForEvent(void)
BX_EVENT_VMX_VIRTUAL_APIC_WRITE |
BX_EVENT_VMX_MONITOR_TRAP_FLAG |
BX_EVENT_VMX_PREEMPTION_TIMER_EXPIRED |
BX_EVENT_VMX_NMI_WINDOW_EXITING))
BX_EVENT_VMX_VIRTUAL_NMI))
{
// interrupt ends the HALT condition
#if BX_SUPPORT_MONITOR_MWAIT
@ -277,7 +277,7 @@ bx_bool BX_CPU_C::handleAsyncEvent(void)
}
#endif
#if BX_SUPPORT_VMX
else if (is_unmasked_event_pending(BX_EVENT_VMX_NMI_WINDOW_EXITING)) {
else if (is_unmasked_event_pending(BX_EVENT_VMX_VIRTUAL_NMI)) {
VMexit(VMX_VMEXIT_NMI_WINDOW, 0);
}
#endif
@ -288,7 +288,7 @@ bx_bool BX_CPU_C::handleAsyncEvent(void)
}
#endif
clear_event(BX_EVENT_NMI);
mask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
mask_event(BX_EVENT_NMI);
BX_CPU_THIS_PTR EXT = 1; /* external event */
#if BX_SUPPORT_VMX
VMexit_Event(BX_NMI, 2, 0, 0);

View File

@ -56,7 +56,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RSM(bxInstruction_c *i)
BX_INFO(("RSM: Resuming from System Management Mode"));
unmask_event(BX_EVENT_SMI | BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
unmask_event(BX_EVENT_SMI | BX_EVENT_NMI | BX_EVENT_VMX_VIRTUAL_NMI);
Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n;
// reset reserved bits
@ -120,7 +120,7 @@ void BX_CPU_C::enter_system_management_mode(void)
BX_CPU_THIS_PTR in_smm = 1;
mask_event(BX_EVENT_SMI | BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
mask_event(BX_EVENT_SMI | BX_EVENT_NMI | BX_EVENT_VMX_VIRTUAL_NMI);
Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n;
// reset reserved bits

View File

@ -686,7 +686,7 @@ bx_bool BX_CPU_C::SvmInjectEvents(void)
switch(type) {
case BX_NMI:
mask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
mask_event(BX_EVENT_NMI);
BX_CPU_THIS_PTR EXT = 1;
vector = 2;
break;

View File

@ -864,6 +864,15 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
BX_ERROR(("VMFAIL: VMENTRY bad injected event vector %d", vector));
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
}
/*
// injecting NMI
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VIRTUAL_NMI) {
if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED) {
BX_ERROR(("VMFAIL: VMENTRY injected NMI vector when blocked by NMI in interruptibility state", vector));
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
}
}
*/
break;
case BX_HARDWARE_EXCEPTION:
@ -1885,11 +1894,14 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
}
if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED) {
mask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)
mask_event(BX_EVENT_VMX_VIRTUAL_NMI);
else
mask_event(BX_EVENT_NMI);
}
if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_NMI_WINDOW_EXITING) {
signal_event(BX_EVENT_VMX_NMI_WINDOW_EXITING);
signal_event(BX_EVENT_VMX_VIRTUAL_NMI);
}
if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_INTERRUPT_WINDOW_VMEXIT) {
@ -1935,7 +1947,11 @@ void BX_CPU_C::VMenterInjectEvents(void)
break;
case BX_NMI:
mask_event(BX_EVENT_NMI | BX_EVENT_VMX_NMI_WINDOW_EXITING);
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)
mask_event(BX_EVENT_VMX_VIRTUAL_NMI);
else
mask_event(BX_EVENT_NMI);
BX_CPU_THIS_PTR EXT = 1;
break;
@ -2137,10 +2153,19 @@ void BX_CPU_C::VMexitSaveGuestState(void)
else
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_BY_STI;
}
if (is_masked_event(BX_EVENT_SMI))
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED;
if (is_masked_event(BX_EVENT_NMI))
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED;
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VIRTUAL_NMI) {
if (is_masked_event(BX_EVENT_VMX_VIRTUAL_NMI))
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED;
}
else {
if (is_masked_event(BX_EVENT_NMI))
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED;
}
VMwrite32(VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE, interruptibility_state);
#if BX_SUPPORT_VMX >= 2
@ -2421,7 +2446,7 @@ void BX_CPU_C::VMexit(Bit32u reason, Bit64u qualification)
BX_EVENT_VMX_MONITOR_TRAP_FLAG |
BX_EVENT_VMX_INTERRUPT_WINDOW_EXITING |
BX_EVENT_VMX_PREEMPTION_TIMER_EXPIRED |
BX_EVENT_VMX_NMI_WINDOW_EXITING |
BX_EVENT_VMX_VIRTUAL_NMI |
BX_EVENT_PENDING_VMX_VIRTUAL_INTR);
//