correctly signal bit 12 (nmi unblocking by iret) in vmx interruption info. todo: find how to implement it clean way

This commit is contained in:
Stanislav Shwartsman 2013-03-06 21:11:23 +00:00
parent 1a770dd260
commit 53d14c01b5
9 changed files with 43 additions and 4 deletions

View File

@ -1092,6 +1092,10 @@ public: // for now...
bx_bool in_event;
#endif
#if BX_SUPPORT_VMX
bx_bool nmi_unblocking_iret;
#endif
bx_bool EXT; /* 1 if processing external interrupt or exception
* or if not related to current instruction,
* 0 if current CS:IP caused exception */

View File

@ -551,6 +551,10 @@ 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)
if (is_masked_event(PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VIRTUAL_NMI) ? BX_EVENT_VMX_VIRTUAL_NMI : BX_EVENT_NMI))
BX_CPU_THIS_PTR nmi_unblocking_iret = 1;
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);
}
@ -593,6 +597,10 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET16(bxInstruction_c *i)
done:
#if BX_SUPPORT_VMX
BX_CPU_THIS_PTR nmi_unblocking_iret = 0;
#endif
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);

View File

@ -594,6 +594,10 @@ 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)
if (is_masked_event(PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VIRTUAL_NMI) ? BX_EVENT_VMX_VIRTUAL_NMI : BX_EVENT_NMI))
BX_CPU_THIS_PTR nmi_unblocking_iret = 1;
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);
}
@ -636,6 +640,10 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
done:
#if BX_SUPPORT_VMX
BX_CPU_THIS_PTR nmi_unblocking_iret = 0;
#endif
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);

View File

@ -433,6 +433,10 @@ 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)
if (is_masked_event(PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VIRTUAL_NMI) ? BX_EVENT_VMX_VIRTUAL_NMI : BX_EVENT_NMI))
BX_CPU_THIS_PTR nmi_unblocking_iret = 1;
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);
}
@ -448,6 +452,10 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET64(bxInstruction_c *i)
long_iret(i);
#if BX_SUPPORT_VMX
BX_CPU_THIS_PTR nmi_unblocking_iret = 0;
#endif
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP);

View File

@ -381,7 +381,6 @@ void BX_CPU_C::deliver_SIPI(unsigned vector)
BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_ACTIVE;
RIP = 0;
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], vector*0x100);
unmask_event(BX_EVENT_INIT); // enable INIT pin back
BX_INFO(("CPU %d started up at %04X:%08X by APIC",
BX_CPU_THIS_PTR bx_cpuid, vector*0x100, EIP));
} else {

View File

@ -899,6 +899,10 @@ void BX_CPU_C::reset(unsigned source)
BX_CPU_THIS_PTR in_event = 0;
#endif
#if BX_SUPPORT_VMX
BX_CPU_THIS_PTR nmi_unblocking_iret = 0;
#endif
#if BX_SUPPORT_SMP
// notice if I'm the bootstrap processor. If not, do the equivalent of
// a HALT instruction.
@ -912,7 +916,6 @@ void BX_CPU_C::reset(unsigned source)
BX_CPU_THIS_PTR msr.apicbase &= ~0x0100; /* clear bit 8 BSP */
BX_INFO(("CPU[%d] is an application processor. Halting until IPI.", apic_id));
activity_state = BX_ACTIVITY_STATE_WAIT_FOR_SIPI;
mask_event(BX_EVENT_INIT); // INIT is disabled when CPU is waiting for SIPI
async_event = 1;
}
#endif

View File

@ -1620,9 +1620,11 @@ bx_phy_address BX_CPU_C::translate_guest_physical(bx_phy_address guest_paddr, bx
// no VMExit qualification for EPT Misconfiguration VMExit
vmexit_qualification = access_mask | (combined_access << 3);
if (guest_laddr_valid) {
vmexit_qualification |= 0x80;
if (! is_page_walk) vmexit_qualification |= 0x100;
vmexit_qualification |= (1<<7);
if (! is_page_walk) vmexit_qualification |= (1<<8);
}
if (BX_CPU_THIS_PTR nmi_unblocking_iret)
vmexit_qualification |= (1 << 12);
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_VIOLATION_EXCEPTION)) {
if ((entry[leaf] & BX_SUPPRESS_EPT_VIOLATION_EXCEPTION) == 0)

View File

@ -236,6 +236,8 @@ void BX_CPU_C::VMexit_Event(unsigned type, unsigned vector, Bit16u errcode, bx_b
vm->idt_vector_info = vector | (type << 8);
if (errcode_valid)
vm->idt_vector_info |= (1 << 11); // error code delivered
BX_CPU_THIS_PTR nmi_unblocking_iret = 0;
return;
}
@ -260,6 +262,9 @@ void BX_CPU_C::VMexit_Event(unsigned type, unsigned vector, Bit16u errcode, bx_b
interruption_info |= (1 << 11); // error code delivered
interruption_info |= (1 << 31); // valid
if (BX_CPU_THIS_PTR nmi_unblocking_iret)
interruption_info |= (1 << 12);
VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_INFO, interruption_info);
VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_ERR_CODE, errcode);

View File

@ -2414,6 +2414,8 @@ void BX_CPU_C::VMexit(Bit32u reason, Bit64u qualification)
VMwrite32(VMCS_32BIT_IDT_VECTORING_INFO, 0);
}
BX_CPU_THIS_PTR nmi_unblocking_iret = 0;
// VMEXITs are FAULT-like: restore RIP/RSP to value before VMEXIT occurred
if (! IS_TRAP_LIKE_VMEXIT(reason)) {
RIP = BX_CPU_THIS_PTR prev_rip;