From 53d14c01b586f8219068bc9cfd6c11f636b3b804 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Wed, 6 Mar 2013 21:11:23 +0000 Subject: [PATCH] correctly signal bit 12 (nmi unblocking by iret) in vmx interruption info. todo: find how to implement it clean way --- bochs/cpu/cpu.h | 4 ++++ bochs/cpu/ctrl_xfer16.cc | 8 ++++++++ bochs/cpu/ctrl_xfer32.cc | 8 ++++++++ bochs/cpu/ctrl_xfer64.cc | 8 ++++++++ bochs/cpu/event.cc | 1 - bochs/cpu/init.cc | 5 ++++- bochs/cpu/paging.cc | 6 ++++-- bochs/cpu/vmexit.cc | 5 +++++ bochs/cpu/vmx.cc | 2 ++ 9 files changed, 43 insertions(+), 4 deletions(-) diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 3aa347370..6dc45e5ff 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -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 */ diff --git a/bochs/cpu/ctrl_xfer16.cc b/bochs/cpu/ctrl_xfer16.cc index 413ee2dd9..3c01bca61 100644 --- a/bochs/cpu/ctrl_xfer16.cc +++ b/bochs/cpu/ctrl_xfer16.cc @@ -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); diff --git a/bochs/cpu/ctrl_xfer32.cc b/bochs/cpu/ctrl_xfer32.cc index b851c9940..5ca1f822a 100644 --- a/bochs/cpu/ctrl_xfer32.cc +++ b/bochs/cpu/ctrl_xfer32.cc @@ -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); diff --git a/bochs/cpu/ctrl_xfer64.cc b/bochs/cpu/ctrl_xfer64.cc index 88fec9bdf..ca0367b72 100644 --- a/bochs/cpu/ctrl_xfer64.cc +++ b/bochs/cpu/ctrl_xfer64.cc @@ -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); diff --git a/bochs/cpu/event.cc b/bochs/cpu/event.cc index 61f5ebb33..56691cd57 100644 --- a/bochs/cpu/event.cc +++ b/bochs/cpu/event.cc @@ -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 { diff --git a/bochs/cpu/init.cc b/bochs/cpu/init.cc index a9e87633c..fc990060d 100644 --- a/bochs/cpu/init.cc +++ b/bochs/cpu/init.cc @@ -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 diff --git a/bochs/cpu/paging.cc b/bochs/cpu/paging.cc index ea14084ab..5f353533f 100644 --- a/bochs/cpu/paging.cc +++ b/bochs/cpu/paging.cc @@ -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) diff --git a/bochs/cpu/vmexit.cc b/bochs/cpu/vmexit.cc index 66c33d39d..77c27f2ce 100644 --- a/bochs/cpu/vmexit.cc +++ b/bochs/cpu/vmexit.cc @@ -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); diff --git a/bochs/cpu/vmx.cc b/bochs/cpu/vmx.cc index 82eb2b717..a404809ef 100644 --- a/bochs/cpu/vmx.cc +++ b/bochs/cpu/vmx.cc @@ -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;