Index: trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp	(revision 74258)
+++ trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp	(revision 74287)
@@ -769,2 +769,70 @@
 }
 
+
+/**
+ * Injects an event using TRPM given a VM-entry interruption info. and related
+ * fields.
+ *
+ * @returns VBox status code.
+ * @param   uEntryIntInfo       The VM-entry interruption info.
+ * @param   uErrCode            The error code associated with the event if any.
+ * @param   cbInstr             The VM-entry instruction length (for software
+ *                              interrupts and software exceptions). Pass 0
+ *                              otherwise.
+ * @param   GCPtrFaultAddress   The guest CR2 if this is a \#PF event.
+ */
+VMM_INT_DECL(int) HMVmxEntryIntInfoInjectTrpmEvent(PVMCPU pVCpu, uint32_t uEntryIntInfo, uint32_t uErrCode, uint32_t cbInstr,
+                                                   RTGCUINTPTR GCPtrFaultAddress)
+{
+    Assert(VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
+
+    uint8_t const uType         = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
+    uint8_t const uVector       = VMX_ENTRY_INT_INFO_VECTOR(uEntryIntInfo);
+    bool const    fErrCodeValid = VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(uEntryIntInfo);
+
+    TRPMEVENT enmTrapType;
+    switch (uType)
+    {
+        case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
+           enmTrapType = TRPM_HARDWARE_INT;
+           break;
+
+        case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
+            enmTrapType = TRPM_SOFTWARE_INT;
+            break;
+
+        case VMX_ENTRY_INT_INFO_TYPE_NMI:
+        case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:  /* ICEBP. */
+        case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:       /* #BP and #OF */
+        case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
+            enmTrapType = TRPM_TRAP;
+            break;
+
+        default:
+            /* Shouldn't really happen. */
+            AssertMsgFailedReturn(("Invalid trap type %#x\n", uType), VERR_VMX_IPE_4);
+            break;
+    }
+
+    int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
+    AssertRCReturn(rc, rc);
+
+    if (fErrCodeValid)
+        TRPMSetErrorCode(pVCpu, uErrCode);
+
+    if (   uType   == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
+        && uVector == X86_XCPT_PF)
+        TRPMSetFaultAddress(pVCpu, GCPtrFaultAddress);
+    else if (   uType == VMX_ENTRY_INT_INFO_TYPE_SW_INT
+             || uType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT
+             || uType == VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT)
+    {
+        AssertMsg(   uType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
+                  || (uVector == X86_XCPT_BP || uVector == X86_XCPT_OF),
+                  ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uType));
+        TRPMSetInstrLength(pVCpu, cbInstr);
+    }
+
+    return VINF_SUCCESS;
+}
+
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74258)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74287)
@@ -2966,5 +2966,5 @@
                             || uVector == X86_XCPT_MC))
                     || (   uIntType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT
-                        && uVector == 0))
+                        && uVector  == VMX_ENTRY_INT_INFO_VECTOR_MTF))
                 { /* likely */ }
                 else
@@ -3480,5 +3480,5 @@
         uint8_t const uVector = RT_BF_GET(uIntInfo, VMX_BF_ENTRY_INT_INFO_VECTOR);
         uint8_t const uRsvd   = RT_BF_GET(uIntInfo, VMX_BF_ENTRY_INT_INFO_RSVD_12_30);
-        if (   uRsvd == 0
+        if (   !uRsvd
             && HMVmxIsEntryIntInfoTypeValid(IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmxMonitorTrapFlag, uType)
             && HMVmxIsEntryIntInfoVectorValid(uVector, uType))
@@ -3709,5 +3709,5 @@
         /* TPR threshold and VTPR. */
         uint8_t const *pbVirtApic = (uint8_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage);
-        uint8_t const u8VTpr = *(pbVirtApic + XAPIC_OFF_TPR);
+        uint8_t const  u8VTpr     = *(pbVirtApic + XAPIC_OFF_TPR);
         if (   !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
             && !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)
@@ -3989,4 +3989,5 @@
  * Loads the guest auto-load MSRs area as part of VM-entry.
  *
+ * @returns VBox status code.
  * @param   pVCpu       The cross context virtual CPU structure.
  * @param   pszInstr    The VMX instruction name (for logging purposes).
@@ -4071,4 +4072,5 @@
  * Loads the guest-state as part of VM-entry.
  *
+ * @returns VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   pszInstr        The VMX instruction name (for logging purposes).
@@ -4079,4 +4081,7 @@
 IEM_STATIC int iemVmxVmentryLoadGuestState(PVMCPU pVCpu, const char *pszInstr)
 {
+    /*
+     * Load control, debug, segment, descriptor-table registers and some MSRs.
+     */
     iemVmxVmentryLoadGuestControlRegsMsr(pVCpu);
     iemVmxVmentryLoadGuestSegRegs(pVCpu);
@@ -4105,4 +4110,79 @@
 
 /**
+ * Performs event injection (if any) as part of VM-entry.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pszInstr    The VMX instruction name (for logging purposes).
+ */
+IEM_STATIC int iemVmxVmentryInjectEvent(PVMCPU pVCpu, const char *pszInstr)
+{
+    /*
+     * Inject events.
+     * See Intel spec. 26.5 "Event Injection".
+     */
+    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    uint32_t const uEntryIntInfo = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->u32EntryIntInfo;
+    if (VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
+    {
+        uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
+        if (uType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT)
+        {
+            Assert(VMX_ENTRY_INT_INFO_VECTOR(uEntryIntInfo) == VMX_ENTRY_INT_INFO_VECTOR_MTF);
+            VMCPU_FF_SET(pVCpu, VMCPU_FF_MTF);
+            return VINF_SUCCESS;
+        }
+
+        /** @todo NSTVMX: Is it safe to update IDT-vectoring information in the VMCS
+         *        here? */
+
+        pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = false;
+        int rc = HMVmxEntryIntInfoInjectTrpmEvent(pVCpu, uEntryIntInfo, pVmcs->u32EntryXcptErrCode, pVmcs->u32EntryInstrLen,
+                                                  pVCpu->cpum.GstCtx.cr2);
+        AssertRCReturn(rc, rc);
+    }
+
+    NOREF(pszInstr);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Perform a VMX transition updated PGM, IEM and CPUM.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ */
+IEM_STATIC int iemVmxWorldSwitch(PVMCPU pVCpu)
+{
+    /*
+     * Inform PGM about paging mode changes.
+     * We include X86_CR0_PE because PGM doesn't handle paged-real mode yet,
+     * see comment in iemMemPageTranslateAndCheckAccess().
+     */
+    int rc = PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0 | X86_CR0_PE, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER);
+# ifdef IN_RING3
+    Assert(rc != VINF_PGM_CHANGE_MODE);
+# endif
+    AssertRCReturn(rc, rc);
+
+    /* Inform CPUM (recompiler), can later be removed. */
+    CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL);
+
+    /*
+     * Flush the TLB with new CR3. This is required in case the PGM mode change
+     * above doesn't actually change anything.
+     */
+    if (rc == VINF_SUCCESS)
+    {
+        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true);
+        AssertRCReturn(rc, rc);
+    }
+
+    /* Re-initialize IEM cache/state after the drastic mode switch. */
+    iemReInitExec(pVCpu);
+    return rc;
+}
+
+
+/**
  * VMLAUNCH/VMRESUME instruction execution worker.
  *
@@ -4163,5 +4243,7 @@
     {
         /* VMLAUNCH with non-clear VMCS. */
-        if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState != VMX_V_VMCS_STATE_CLEAR)
+        if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState == VMX_V_VMCS_STATE_CLEAR)
+        { /* likely */ }
+        else
         {
             Log(("vmlaunch: VMLAUNCH with non-clear VMCS -> VMFail\n"));
@@ -4175,5 +4257,7 @@
     {
         /* VMRESUME with non-launched VMCS. */
-        if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState != VMX_V_VMCS_STATE_LAUNCHED)
+        if (pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState == VMX_V_VMCS_STATE_LAUNCHED)
+        { /* likely */ }
+        else
         {
             Log(("vmresume: VMRESUME with non-launched VMCS -> VMFail\n"));
@@ -4228,4 +4312,30 @@
                                 Assert(rc != VINF_CPUM_R3_MSR_WRITE);
 
+                                /* VMLAUNCH instruction must update the VMCS launch state. */
+                                if (uInstrId == VMXINSTRID_VMLAUNCH)
+                                    pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState = VMX_V_VMCS_STATE_LAUNCHED;
+
+                                /* Perform the VMX transition (PGM updates). */
+                                VBOXSTRICTRC rcStrict = iemVmxWorldSwitch(pVCpu);
+                                if (rcStrict == VINF_SUCCESS)
+                                { /* likely */ }
+                                else if (RT_SUCCESS(rcStrict))
+                                {
+                                    Log3(("%s: iemVmxWorldSwitch returns %Rrc -> Setting passup status\n", pszInstr,
+                                          VBOXSTRICTRC_VAL(rcStrict)));
+                                    rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
+                                }
+                                else
+                                {
+                                    Log3(("%s: iemVmxWorldSwitch failed! rc=%Rrc\n", pszInstr, VBOXSTRICTRC_VAL(rcStrict)));
+                                    return rcStrict;
+                                }
+
+                                /* Event injection. */
+                                iemVmxVmentryInjectEvent(pVCpu, pszInstr);
+
+                                /** @todo NSTVMX: Setup VMX preemption timer */
+                                /** @todo NSTVMX: TPR thresholding. */
+
                                 iemVmxVmSucceed(pVCpu);
                                 iemRegAddToRipAndClearRF(pVCpu, cbInstr);
Index: trunk/src/VBox/VMM/testcase/tstVMStruct.h
===================================================================
--- trunk/src/VBox/VMM/testcase/tstVMStruct.h	(revision 74258)
+++ trunk/src/VBox/VMM/testcase/tstVMStruct.h	(revision 74287)
@@ -151,4 +151,5 @@
     GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxRootMode);
     GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxNonRootMode);
+    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInterceptEvents);
     GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR0);
     GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR3);
