implementation of virtual NMI
This commit is contained in:
parent
e9a8ef1d65
commit
1a770dd260
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user