Index: /trunk/include/VBox/vmm/hm_vmx.h
===================================================================
--- /trunk/include/VBox/vmm/hm_vmx.h	(revision 74467)
+++ /trunk/include/VBox/vmm/hm_vmx.h	(revision 74468)
@@ -2296,7 +2296,7 @@
 #define VMX_BF_EXIT_REASON_ENCLAVE_MODE_SHIFT                   27
 #define VMX_BF_EXIT_REASON_ENCLAVE_MODE_MASK                    UINT32_C(0x08000000)
-/** Pending MTF (Monitor Trap Flag) VM-exit. */
-#define VMX_BF_EXIT_REASON_PENDING_MTF_SHIFT                    28
-#define VMX_BF_EXIT_REASON_PENDING_MTF_MASK                     UINT32_C(0x10000000)
+/** Pending MTF (Monitor Trap Flag) during VM-exit (only applicable in SMM mode). */
+#define VMX_BF_EXIT_REASON_SMM_PENDING_MTF_SHIFT                28
+#define VMX_BF_EXIT_REASON_SMM_PENDING_MTF_MASK                 UINT32_C(0x10000000)
 /** VM-exit from VMX root operation (only possible with SMM). */
 #define VMX_BF_EXIT_REASON_VMX_ROOT_MODE_SHIFT                  29
@@ -2310,5 +2310,5 @@
 #define VMX_BF_EXIT_REASON_ENTRY_FAILED_MASK                    UINT32_C(0x80000000)
 RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_REASON_, UINT32_C(0), UINT32_MAX,
-                            (BASIC, RSVD_16_26, ENCLAVE_MODE, PENDING_MTF, VMX_ROOT_MODE, RSVD_30, ENTRY_FAILED));
+                            (BASIC, RSVD_16_26, ENCLAVE_MODE, SMM_PENDING_MTF, VMX_ROOT_MODE, RSVD_30, ENTRY_FAILED));
 /** @} */
 
@@ -3330,5 +3330,5 @@
      * @{ */
     /** 0x320 - Guest-physical address. */
-    RTUINT64U       u64GuestPhysAddr;
+    RTUINT64U       u64RoGuestPhysAddr;
     /** 0x328 - Reserved for future. */
     RTUINT64U       au64Reserved1[8];
@@ -3397,15 +3397,15 @@
     /** @name Natural-width Read-only Data fields. */
     /** 0x610 - Exit qualification. */
-    RTUINT64U       u64ExitQual;
+    RTUINT64U       u64RoExitQual;
     /** 0x618 - I/O RCX. */
-    RTUINT64U       u64IoRcx;
+    RTUINT64U       u64RoIoRcx;
     /** 0x620 - I/O RSI. */
-    RTUINT64U       u64IoRsi;
+    RTUINT64U       u64RoIoRsi;
     /** 0x628 - I/O RDI. */
-    RTUINT64U       u64IoRdi;
+    RTUINT64U       u64RoIoRdi;
     /** 0x630 - I/O RIP. */
-    RTUINT64U       u64IoRip;
+    RTUINT64U       u64RoIoRip;
     /** 0x638 - Guest-linear address. */
-    RTUINT64U       u64GuestLinearAddr;
+    RTUINT64U       u64RoGuestLinearAddr;
     /** 0x640 - Reserved for future. */
     RTUINT64U       au64Reserved5[16];
@@ -3509,9 +3509,9 @@
 AssertCompileMemberOffset(VMXVVMCS, u32HostSysenterCs,  0x1a8);
 AssertCompileMemberOffset(VMXVVMCS, u64AddrIoBitmapA,   0x1d8);
-AssertCompileMemberOffset(VMXVVMCS, u64GuestPhysAddr,   0x320);
+AssertCompileMemberOffset(VMXVVMCS, u64RoGuestPhysAddr, 0x320);
 AssertCompileMemberOffset(VMXVVMCS, u64VmcsLinkPtr,     0x368);
 AssertCompileMemberOffset(VMXVVMCS, u64HostPatMsr,      0x438);
 AssertCompileMemberOffset(VMXVVMCS, u64Cr0Mask,         0x4d0);
-AssertCompileMemberOffset(VMXVVMCS, u64ExitQual,        0x610);
+AssertCompileMemberOffset(VMXVVMCS, u64RoExitQual,      0x610);
 AssertCompileMemberOffset(VMXVVMCS, u64GuestCr0,        0x6c0);
 AssertCompileMemberOffset(VMXVVMCS, u64HostCr0,         0x860);
@@ -3967,4 +3967,7 @@
      * See Intel spec. 29.1.2 "TPR Virtualization".
      */
+    /** @todo NSTVMX: r=ramshankar: What about VM-exits due to debug traps (single-step,
+     *        I/O breakpoints, data breakpoints), debug exceptions (data breakpoint)
+     *        delayed by MovSS blocking, machine-check exceptions. */
     switch (uExitReason)
     {
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74467)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74468)
@@ -113,5 +113,5 @@
     /* VMX_VMCS_ENC_WIDTH_64BIT | VMX_VMCS_ENC_TYPE_VMEXIT_INFO: */
     {
-        /*     0 */ RT_OFFSETOF(VMXVVMCS, u64GuestPhysAddr),
+        /*     0 */ RT_OFFSETOF(VMXVVMCS, u64RoGuestPhysAddr),
         /*   1-8 */ UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX,
         /*  9-16 */ UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX,
@@ -231,10 +231,10 @@
     /* VMX_VMCS_ENC_WIDTH_NATURAL | VMX_VMCS_ENC_TYPE_VMEXIT_INFO: */
     {
-        /*     0 */ RT_OFFSETOF(VMXVVMCS, u64ExitQual),
-        /*     1 */ RT_OFFSETOF(VMXVVMCS, u64IoRcx),
-        /*     2 */ RT_OFFSETOF(VMXVVMCS, u64IoRsi),
-        /*     3 */ RT_OFFSETOF(VMXVVMCS, u64IoRdi),
-        /*     4 */ RT_OFFSETOF(VMXVVMCS, u64IoRip),
-        /*     5 */ RT_OFFSETOF(VMXVVMCS, u64GuestLinearAddr),
+        /*     0 */ RT_OFFSETOF(VMXVVMCS, u64RoExitQual),
+        /*     1 */ RT_OFFSETOF(VMXVVMCS, u64RoIoRcx),
+        /*     2 */ RT_OFFSETOF(VMXVVMCS, u64RoIoRsi),
+        /*     3 */ RT_OFFSETOF(VMXVVMCS, u64RoIoRdi),
+        /*     4 */ RT_OFFSETOF(VMXVVMCS, u64RoIoRip),
+        /*     5 */ RT_OFFSETOF(VMXVVMCS, u64RoGuestLinearAddr),
         /*  6-13 */ UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX,
         /* 14-21 */ UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX,
@@ -1229,4 +1229,43 @@
 
 /**
+ * Sets the VM-exit qualification VMCS field.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   uExitQual   The VM-exit qualification field.
+ */
+DECL_FORCE_INLINE(void) iemVmxVmcsSetExitQual(PVMCPU pVCpu, uint64_t uExitQual)
+{
+    PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    pVmcs->u64RoExitQual.u = uExitQual;
+}
+
+
+/**
+ * Sets the VM-exit instruction length VMCS field.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   cbInstr     The VM-exit instruction length (in bytes).
+ */
+DECL_FORCE_INLINE(void) iemVmxVmcsSetExitInstrLen(PVMCPU pVCpu, uint32_t cbInstr)
+{
+    PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    pVmcs->u32RoExitInstrLen = cbInstr;
+}
+
+
+/**
+ * Sets the VM-exit instruction info. VMCS field.
+ *
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   uExitInstrInfo  The VM-exit instruction info. field.
+ */
+DECL_FORCE_INLINE(void) iemVmxVmcsSetExitInstrInfo(PVMCPU pVCpu, uint32_t uExitInstrInfo)
+{
+    PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    pVmcs->u32RoExitInstrInfo = uExitInstrInfo;
+}
+
+
+/**
  * Implements VMSucceed for VMX instruction success.
  *
@@ -2475,30 +2514,37 @@
 IEM_STATIC void iemVmxVmentrySaveForceFlags(PVMCPU pVCpu)
 {
-    /* Assert that we are not called multiple times during VM-entry. */
+    /* We shouldn't be called multiple times during VM-entry. */
     Assert(pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions == 0);
+
+    /* MTF should not be set outside VMX non-root mode. */
+    Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_MTF));
 
     /*
      * Preserve the required force-flags.
      *
-     * We only preserve the force-flags that would affect the execution of the
-     * nested-guest (or the guest).
+     * We cache and clear force-flags that would affect the execution of the
+     * nested-guest. Cached flags are then restored while returning to the guest
+     * if necessary.
      *
-     *   - VMCPU_FF_INHIBIT_INTERRUPTS need not be preserved as VM-exit explicitly
-     *     clears interrupt-inhibition and on VM-entry the guest-interruptibility
-     *     state provides the inhibition if any.
+     *   - VMCPU_FF_INHIBIT_INTERRUPTS need not be cached as it only affects
+     *     interrupts until the completion of the current VMLAUNCH/VMRESUME
+     *     instruction. Interrupt inhibition for any nested-guest instruction
+     *     will be set later while loading the guest-interruptibility state.
      *
-     *   - VMCPU_FF_BLOCK_NMIS needs not be preserved as VM-entry does not discard
-     *     any NMI blocking. VM-exits caused directly by NMIs (intercepted by the
-     *     exception bitmap) do block subsequent NMIs.
+     *   - VMCPU_FF_BLOCK_NMIS needs to be cached as VM-exits caused before
+     *     successful VM-entry needs to continue blocking NMIs if it was in effect
+     *     during VM-entry.
      *
      *   - MTF need not be preserved as it's used only in VMX non-root mode and
      *     is supplied on VM-entry through the VM-execution controls.
      *
-     * The remaining FFs (e.g. timers) can stay in place so that we will be able to
-     * generate interrupts that should cause #VMEXITs for the nested-guest.
+     * The remaining FFs (e.g. timers, APIC updates) must stay in place so that
+     * we will be able to generate interrupts that may cause VM-exits for
+     * the nested-guest.
      */
-    uint32_t const fDiscardMask = VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_MTF | VMCPU_FF_BLOCK_NMIS;
-    pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions = pVCpu->fLocalForcedActions & fDiscardMask;
-    VMCPU_FF_CLEAR(pVCpu, fDiscardMask);
+    pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions = pVCpu->fLocalForcedActions & VMCPU_FF_BLOCK_NMIS;
+
+    if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_BLOCK_NMIS))
+        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_BLOCK_NMIS);
 }
 
@@ -2672,8 +2718,5 @@
     PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
 
-    /*
-     * Activity-state: VM-exits occur before changing the activity state
-     * of the processor and hence we shouldn't need to change it.
-     */
+    /* Activity-state: VM-exits occur before changing the activity state, nothing further to do */
 
     /* Interruptibility-state. */
@@ -2729,7 +2772,4 @@
     Assert(pVmcs);
 
-    /*
-     * Save guest control, debug, segment, descriptor-table registers and some MSRs.
-     */
     iemVmxVmexitSaveGuestControlRegsMsrs(pVCpu);
     iemVmxVmexitSaveGuestSegRegs(pVCpu);
@@ -2737,4 +2777,5 @@
     /*
      * Save guest RIP, RSP and RFLAGS.
+     * See Intel spec. 27.3.3 "Saving RIP, RSP and RFLAGS".
      */
     /* We don't support enclave mode yet. */
@@ -2743,5 +2784,4 @@
     pVmcs->u64GuestRFlags.u = pVCpu->cpum.GstCtx.rflags.u;  /** @todo NSTVMX: Check RFLAGS.RF handling. */
 
-    /* Save guest non-register state. */
     iemVmxVmexitSaveGuestNonRegState(pVCpu, uExitReason);
 }
@@ -2789,6 +2829,6 @@
     {
         if (   !pMsr->u32Reserved
-            &&  pMsr->u32Msr >> 8 != MSR_IA32_X2APIC_START >> 8
-            &&  pMsr->u32Msr != MSR_IA32_SMBASE)
+            &&  pMsr->u32Msr != MSR_IA32_SMBASE
+            &&  pMsr->u32Msr >> 8 != MSR_IA32_X2APIC_START >> 8)
         {
             VBOXSTRICTRC rcStrict = CPUMQueryGuestMsr(pVCpu, pMsr->u32Msr, &pMsr->u64Value);
@@ -2836,9 +2876,9 @@
  * Performs a VMX abort (due to an fatal error during VM-exit).
  *
- * @returns VBox status code.
+ * @returns Strict VBox status code.
  * @param   pVCpu       The cross context virtual CPU structure.
  * @param   enmAbort    The VMX abort reason.
  */
-IEM_STATIC int iemVmxAbort(PVMCPU pVCpu, VMXABORT enmAbort)
+IEM_STATIC VBOXSTRICTRC iemVmxAbort(PVMCPU pVCpu, VMXABORT enmAbort)
 {
     /*
@@ -3079,5 +3119,5 @@
     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     const char *const pszFailure = "VMX-abort";
-    bool const fHostInLongMode = RT_BOOL(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE);
+    bool const fHostInLongMode   = RT_BOOL(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE);
 
     if (   (pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE)
@@ -3160,6 +3200,6 @@
                 &&  pMsr->u32Msr != MSR_K8_GS_BASE
                 &&  pMsr->u32Msr != MSR_K6_EFER
-                &&  pMsr->u32Msr >> 8 != MSR_IA32_X2APIC_START >> 8
-                &&  pMsr->u32Msr != MSR_IA32_SMM_MONITOR_CTL)
+                &&  pMsr->u32Msr != MSR_IA32_SMM_MONITOR_CTL
+                &&  pMsr->u32Msr >> 8 != MSR_IA32_X2APIC_START >> 8)
             {
                 VBOXSTRICTRC rcStrict = CPUMSetGuestMsr(pVCpu, pMsr->u32Msr, pMsr->u64Value);
@@ -3199,9 +3239,9 @@
  * Loads the host state as part of VM-exit.
  *
- * @returns VBox status code.
+ * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   uExitReason     The VM-exit reason (for logging purposes).
  */
-IEM_STATIC int iemVmxVmexitLoadHostState(PVMCPU pVCpu, uint32_t uExitReason)
+IEM_STATIC VBOXSTRICTRC iemVmxVmexitLoadHostState(PVMCPU pVCpu, uint32_t uExitReason)
 {
     /*
@@ -3220,7 +3260,4 @@
     }
 
-    /*
-     * Load host control, debug, segment, descriptor-table registers and some MSRs.
-     */
     iemVmxVmexitLoadHostControlRegsMsrs(pVCpu);
     iemVmxVmexitLoadHostSegRegs(pVCpu);
@@ -3244,5 +3281,5 @@
     if (rcStrict == VINF_SUCCESS)
     {
-        /* Check host PDPTEs. */
+        /* Check host PDPTEs (only when we've fully switched page tables_. */
         /** @todo r=ramshankar: I don't know if PGM does this for us already or not... */
         int rc = iemVmxVmexitCheckHostPdptes(pVCpu, uExitReason);
@@ -3262,5 +3299,5 @@
     {
         Log3(("VM-exit: iemVmxWorldSwitch failed! rc=%Rrc (uExitReason=%u)\n", VBOXSTRICTRC_VAL(rcStrict), uExitReason));
-        return rcStrict;
+        return VBOXSTRICTRC_VAL(rcStrict);
     }
 
@@ -3275,5 +3312,5 @@
     }
 
-    return VINF_SUCCESS;
+    return rcStrict;
 }
 
@@ -3291,5 +3328,5 @@
     Assert(pVmcs);
 
-    pVmcs->u32RoExitReason   = uExitReason;
+    pVmcs->u32RoExitReason = uExitReason;
 
     /** @todo NSTVMX: Update VM-exit instruction length for instruction VM-exits. */
@@ -3313,14 +3350,19 @@
     }
 
-    int rc = iemVmxVmexitLoadHostState(pVCpu, uExitReason);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    /** @todo NSTVMX: rest of VM-exit. */
+    /*
+     * The high bits of the VM-exit reason are only relevant when the VM-exit occurs in
+     * enclave mode/SMM which we don't support yet. If we ever add support for it, we can
+     * pass just the lower bits, till then an assert should suffice.
+     */
+    Assert(!RT_HI_U16(uExitReason));
+
+    VBOXSTRICTRC rcStrict = iemVmxVmexitLoadHostState(pVCpu, uExitReason);
+    if (RT_FAILURE(rcStrict))
+        LogFunc(("Loading host-state failed. uExitReason=%u rc=%Rrc\n", uExitReason, VBOXSTRICTRC_VAL(rcStrict)));
 
     /* We're no longer in nested-guest execution mode. */
     pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxNonRootMode = false;
 
-    return VINF_SUCCESS;
+    return rcStrict;
 }
 
@@ -3339,6 +3381,6 @@
      */
     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    const char *const pszFailure  = "VM-exit";
     bool const fUnrestrictedGuest = RT_BOOL(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST);
-    const char *const pszFailure = "VM-exit";
 
     /* CR0 reserved bits. */
@@ -3468,8 +3510,8 @@
      */
     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    const char *const pszFailure  = "VM-exit";
     bool const fGstInV86Mode      = RT_BOOL(pVmcs->u64GuestRFlags.u & X86_EFL_VM);
     bool const fUnrestrictedGuest = RT_BOOL(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST);
     bool const fGstInLongMode     = RT_BOOL(pVmcs->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
-    const char *const pszFailure = "VM-exit";
 
     /* Selectors. */
@@ -3857,4 +3899,5 @@
     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     const char *const pszFailure = "VM-exit";
+
     if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fLongMode)
     {
@@ -3902,5 +3945,5 @@
     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     const char *const pszFailure = "VM-exit";
-    bool const fGstInLongMode = RT_BOOL(pVmcs->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
+    bool const fGstInLongMode    = RT_BOOL(pVmcs->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
 
     /* RIP. */
@@ -4077,5 +4120,15 @@
             { /* likely */ }
             else
+            {
+                /*
+                 * We don't support injecting NMIs when blocking-by-STI would be in effect.
+                 * We update the VM-exit qualification only when blocking-by-STI is set
+                 * without blocking-by-MovSS being set. Although in practise it  does not
+                 * make much difference since the order of checks are implementation defined.
+                 */
+                if (!(pVmcs->u32GuestIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
+                    iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_NMI_INJECT);
                 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestIntStateNmi);
+            }
 
             if (   !(pVmcs->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
@@ -4139,5 +4192,5 @@
         else
         {
-            pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR;
+            iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR);
             IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_VmcsLinkPtrCurVmcs);
         }
@@ -4148,5 +4201,5 @@
             || !PGMPhysIsGCPhysNormal(pVCpu->CTX_SUFF(pVM), GCPhysShadowVmcs))
         {
-            pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR;
+            iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR);
             IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_AddrVmcsLinkPtr);
         }
@@ -4158,5 +4211,5 @@
         if (RT_FAILURE(rc))
         {
-            pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR;
+            iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR);
             IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_VmcsLinkPtrReadPhys);
         }
@@ -4167,5 +4220,5 @@
         else
         {
-            pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR;
+            iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR);
             IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_VmcsLinkPtrRevId);
         }
@@ -4177,5 +4230,5 @@
         else
         {
-            pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR;
+            iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR);
             IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_VmcsLinkPtrShadow);
         }
@@ -4220,5 +4273,5 @@
             else
             {
-                pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_PDPTE;
+                iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE);
                 VMXVDIAG const enmDiag = iemVmxGetDiagVmentryPdpteRsvd(iPdpte);
                 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, enmDiag);
@@ -4228,5 +4281,5 @@
     else
     {
-        pVmcs->u64ExitQual.u = VMX_ENTRY_FAIL_QUAL_PDPTE;
+        iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE);
         IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestPdpteCr3ReadPhys);
     }
@@ -4281,27 +4334,19 @@
 IEM_STATIC int iemVmxVmentryCheckGuestState(PVMCPU pVCpu, const char *pszInstr)
 {
-    /* Check control registers, debug registers and MSRs. */
     int rc = iemVmxVmentryCheckGuestControlRegsMsrs(pVCpu, pszInstr);
     if (RT_SUCCESS(rc))
     {
-        /* Check guest segment registers, LDTR, TR. */
         rc = iemVmxVmentryCheckGuestSegRegs(pVCpu, pszInstr);
         if (RT_SUCCESS(rc))
         {
-            /* Check guest GDTR and IDTR. */
             rc = iemVmxVmentryCheckGuestGdtrIdtr(pVCpu, pszInstr);
             if (RT_SUCCESS(rc))
             {
-                /* Check guest RIP, RSP and RFLAGS. */
                 rc = iemVmxVmentryCheckGuestRipRFlags(pVCpu, pszInstr);
                 if (RT_SUCCESS(rc))
                 {
-                    /* Check guest non-register state. */
                     rc = iemVmxVmentryCheckGuestNonRegState(pVCpu, pszInstr);
                     if (RT_SUCCESS(rc))
-                    {
-                        /* Check guest PDPTEs. */
                         return iemVmxVmentryCheckGuestPdptes(pVCpu, pszInstr);
-                    }
                 }
             }
@@ -5083,5 +5128,5 @@
     else
     {
-        pVmcs->u64ExitQual.u = VMX_V_AUTOMSR_AREA_SIZE / sizeof(VMXAUTOMSR);
+        iemVmxVmcsSetExitQual(pVCpu, VMX_V_AUTOMSR_AREA_SIZE / sizeof(VMXAUTOMSR));
         IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_MsrLoadCount);
     }
@@ -5100,6 +5145,6 @@
                 &&  pMsr->u32Msr != MSR_K8_GS_BASE
                 &&  pMsr->u32Msr != MSR_K6_EFER
-                &&  pMsr->u32Msr >> 8 != MSR_IA32_X2APIC_START >> 8
-                &&  pMsr->u32Msr != MSR_IA32_SMM_MONITOR_CTL)
+                &&  pMsr->u32Msr != MSR_IA32_SMM_MONITOR_CTL
+                &&  pMsr->u32Msr >> 8 != MSR_IA32_X2APIC_START >> 8)
             {
                 VBOXSTRICTRC rcStrict = CPUMSetGuestMsr(pVCpu, pMsr->u32Msr, pMsr->u64Value);
@@ -5114,5 +5159,5 @@
                  * MSR in ring-0 if possible, or come up with a better, generic solution.
                  */
-                pVmcs->u64ExitQual.u = idxMsr;
+                iemVmxVmcsSetExitQual(pVCpu, idxMsr);
                 VMXVDIAG const enmDiag = rcStrict == VINF_CPUM_R3_MSR_WRITE
                                        ? kVmxVDiag_Vmentry_MsrLoadRing3
@@ -5122,5 +5167,5 @@
             else
             {
-                pVmcs->u64ExitQual.u = idxMsr;
+                iemVmxVmcsSetExitQual(pVCpu, idxMsr);
                 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_MsrLoadRsvd);
             }
@@ -5161,5 +5206,5 @@
         Assert(!(pVmcs->u64GuestPendingDbgXcpt.u));
 
-        if (pVmcs->u32GuestIntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI)
+        if (pVmcs->u32GuestIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI)
         {
             /** @todo NSTVMX: Virtual-NMIs doesn't affect NMI blocking in the normal sense.
@@ -5169,9 +5214,11 @@
             VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
         }
-        else if (   pVmcs->u32GuestIntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI
-                 || pVmcs->u32GuestIntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
-        {
+        else
+            Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS));
+
+        if (pVmcs->u32GuestIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
             EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
-        }
+        else
+            Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
 
         /* SMI blocking is irrelevant. We don't support SMIs yet. */
@@ -5200,7 +5247,4 @@
 IEM_STATIC int iemVmxVmentryLoadGuestState(PVMCPU pVCpu, const char *pszInstr)
 {
-    /*
-     * Load guest control, debug, segment, descriptor-table registers and some MSRs.
-     */
     iemVmxVmentryLoadGuestControlRegsMsrs(pVCpu);
     iemVmxVmentryLoadGuestSegRegs(pVCpu);
@@ -5215,5 +5259,4 @@
     pVCpu->cpum.GstCtx.rflags.u = pVmcs->u64GuestRFlags.u;
 
-    /* Load guest non-register state. */
     iemVmxVmentryLoadGuestNonRegState(pVCpu);
 
@@ -5364,32 +5407,25 @@
     }
 
-    /* Check VM-execution control fields. */
     rc = iemVmxVmentryCheckExecCtls(pVCpu, pszInstr);
     if (RT_SUCCESS(rc))
     {
-        /* Check VM-exit control fields. */
         rc = iemVmxVmentryCheckExitCtls(pVCpu, pszInstr);
         if (RT_SUCCESS(rc))
         {
-            /* Check VM-entry control fields. */
             rc = iemVmxVmentryCheckEntryCtls(pVCpu, pszInstr);
             if (RT_SUCCESS(rc))
             {
-                /* Check host-state fields. */
                 rc = iemVmxVmentryCheckHostState(pVCpu, pszInstr);
                 if (RT_SUCCESS(rc))
                 {
-                    /* Save the (outer) guest force-flags as VM-exits can occur from this point on. */
+                    /* Save the guest force-flags as VM-exits can occur from this point on. */
                     iemVmxVmentrySaveForceFlags(pVCpu);
 
-                    /* Check guest-state fields. */
                     rc = iemVmxVmentryCheckGuestState(pVCpu, pszInstr);
                     if (RT_SUCCESS(rc))
                     {
-                        /* Load guest-state fields. */
                         rc = iemVmxVmentryLoadGuestState(pVCpu, pszInstr);
                         if (RT_SUCCESS(rc))
                         {
-                            /* Load MSRs from the VM-entry auto-load MSR area. */
                             rc = iemVmxVmentryLoadGuestAutoMsrs(pVCpu, pszInstr);
                             if (RT_SUCCESS(rc))
@@ -5420,5 +5456,5 @@
                                 pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxNonRootMode = true;
 
-                                /* Event injection. */
+                                /* Now that we've switched page tables, we can inject events if any. */
                                 iemVmxVmentryInjectEvent(pVCpu, pszInstr);
 
@@ -5428,9 +5464,7 @@
                                 return VINF_SUCCESS;
                             }
-
                             return iemVmxVmexit(pVCpu, VMX_EXIT_ERR_MSR_LOAD | VMX_EXIT_REASON_ENTRY_FAILED);
                         }
                     }
-
                     return iemVmxVmexit(pVCpu, VMX_EXIT_ERR_INVALID_GUEST_STATE | VMX_EXIT_REASON_ENTRY_FAILED);
                 }
@@ -5492,7 +5526,5 @@
     }
 
-    /*
-     * Record that we're no longer in VMX root operation, block INIT, block and disable A20M.
-     */
+    /* Record that we're no longer in VMX root operation, block INIT, block and disable A20M. */
     pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxRootMode = false;
     Assert(!pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxNonRootMode);
