Index: trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 79030)
+++ trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 79031)
@@ -14060,5 +14060,5 @@
         else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
         {
-            rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_MTF);
+            rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* u64ExitQual */);
             fCheckRemainingIntercepts = false;
             Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
@@ -14096,5 +14096,5 @@
                 && CPUMIsGuestVmxVirtNmiBlocking(pVCpu, &pVCpu->cpum.GstCtx))
             {
-                rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_NMI_WINDOW);
+                rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_NMI_WINDOW, 0 /* u64ExitQual */);
                 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW));
             }
@@ -14102,5 +14102,5 @@
                      && CPUMIsGuestVmxVirtIntrEnabled(pVCpu, &pVCpu->cpum.GstCtx))
             {
-                rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_INT_WINDOW);
+                rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_INT_WINDOW, 0 /* u64ExitQual */);
                 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_INT_WINDOW));
             }
@@ -15955,5 +15955,5 @@
 VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitStartupIpi(PVMCPU pVCpu, uint8_t uVector)
 {
-    VBOXSTRICTRC rcStrict = iemVmxVmexitStartupIpi(pVCpu, uVector);
+    VBOXSTRICTRC rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_SIPI, uVector);
     Assert(!pVCpu->iem.s.cActiveMappings);
     return iemExecStatusCodeFiddling(pVCpu, rcStrict);
@@ -15969,11 +15969,10 @@
  * @param   pVCpu           The cross context virtual CPU structure of the calling EMT.
  * @param   uExitReason     The VM-exit reason.
- * @param   uExitQual       The VM-exit qualification.
+ * @param   u64ExitQual     The Exit qualification.
  * @thread  EMT(pVCpu)
  */
-VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexit(PVMCPU pVCpu, uint32_t uExitReason, uint64_t uExitQual)
-{
-    iemVmxVmcsSetExitQual(pVCpu, uExitQual);
-    VBOXSTRICTRC rcStrict = iemVmxVmexit(pVCpu, uExitReason);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexit(PVMCPU pVCpu, uint32_t uExitReason, uint64_t u64ExitQual)
+{
+    VBOXSTRICTRC rcStrict = iemVmxVmexit(pVCpu, uExitReason, u64ExitQual);
     Assert(!pVCpu->iem.s.cActiveMappings);
     return iemExecStatusCodeFiddling(pVCpu, rcStrict);
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 79030)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 79031)
@@ -951,13 +951,13 @@
 
 /**
- * Sets the VM-exit qualification VMCS field.
- *
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   uExitQual   The VM-exit qualification.
- */
-DECL_FORCE_INLINE(void) iemVmxVmcsSetExitQual(PVMCPU pVCpu, uint64_t uExitQual)
+ * Sets the Exit qualification VMCS field.
+ *
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   u64ExitQual     The Exit qualification.
+ */
+DECL_FORCE_INLINE(void) iemVmxVmcsSetExitQual(PVMCPU pVCpu, uint64_t u64ExitQual)
 {
     PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
-    pVmcs->u64RoExitQual.u = uExitQual;
+    pVmcs->u64RoExitQual.u = u64ExitQual;
 }
 
@@ -966,6 +966,6 @@
  * Sets the VM-exit interruption information field.
  *
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   uExitQual   The VM-exit interruption information.
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   uExitIntInfo    The VM-exit interruption information.
  */
 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitIntInfo(PVMCPU pVCpu, uint32_t uExitIntInfo)
@@ -2710,12 +2710,10 @@
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   uExitReason     The VM-exit reason.
- *
- * @remarks Make sure VM-exit qualification is updated before calling this
- *          function!
- */
-IEM_STATIC VBOXSTRICTRC iemVmxVmexit(PVMCPU pVCpu, uint32_t uExitReason)
+ * @param   u64ExitQual     The Exit qualification.
+ */
+IEM_STATIC VBOXSTRICTRC iemVmxVmexit(PVMCPU pVCpu, uint32_t uExitReason, uint64_t u64ExitQual)
 {
 # if defined(VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM) && !defined(IN_RING3)
-    RT_NOREF2(pVCpu, uExitReason);
+    RT_NOREF3(pVCpu, uExitReason, u64ExitQual);
     return VINF_EM_RAW_EMULATE_INSTR;
 # else
@@ -2738,8 +2736,10 @@
 
     /*
-     * Update the VM-exit reason. Other VMCS data fields are expected to be updated by the caller already.
+     * Update the VM-exit reason and Exit qualification.
+     * Other VMCS read-only data fields are expected to be updated by the caller already.
      */
     pVmcs->u32RoExitReason = uExitReason;
-    Log3(("vmexit: uExitReason=%#RX32 uExitQual=%#RX64 cs:rip=%04x:%#RX64\n", uExitReason, pVmcs->u64RoExitQual,
+    pVmcs->u64RoExitQual.u = u64ExitQual;
+    Log3(("vmexit: uExitReason=%#RX32 u64ExitQual=%#RX64 cs:rip=%04x:%#RX64\n", uExitReason, pVmcs->u64RoExitQual.u,
           pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
 
@@ -2887,8 +2887,8 @@
     /*
      * For instructions where any of the following fields are not applicable:
+     *   - Exit qualification must be cleared.
      *   - VM-exit instruction info. is undefined.
-     *   - VM-exit qualification must be cleared.
-     *   - VM-exit guest-linear address is undefined.
-     *   - VM-exit guest-physical address is undefined.
+     *   - Guest-linear address is undefined.
+     *   - Guest-physical address is undefined.
      *
      * The VM-exit instruction length is mandatory for all VM-exits that are caused by
@@ -2910,5 +2910,4 @@
     /* Update all the relevant fields from the VM-exit instruction information struct. */
     iemVmxVmcsSetExitInstrInfo(pVCpu, pExitInfo->InstrInfo.u);
-    iemVmxVmcsSetExitQual(pVCpu, pExitInfo->u64Qual);
     iemVmxVmcsSetExitGuestLinearAddr(pVCpu, pExitInfo->u64GuestLinearAddr);
     iemVmxVmcsSetExitGuestPhysAddr(pVCpu, pExitInfo->u64GuestPhysAddr);
@@ -2916,5 +2915,5 @@
 
     /* Perform the VM-exit. */
-    return iemVmxVmexit(pVCpu, pExitInfo->uReason);
+    return iemVmxVmexit(pVCpu, pExitInfo->uReason, pExitInfo->u64Qual);
 }
 
@@ -2972,5 +2971,5 @@
  *
  * This is intended for instructions that have a ModR/M byte and update the VM-exit
- * instruction information and VM-exit qualification fields.
+ * instruction information and Exit qualification fields.
  *
  * @param   pVCpu           The cross context virtual CPU structure.
@@ -2989,5 +2988,5 @@
 
     /*
-     * Update the VM-exit qualification field with displacement bytes.
+     * Update the Exit qualification field with displacement bytes.
      * See Intel spec. 27.2.1 "Basic VM-Exit Information".
      */
@@ -3017,5 +3016,5 @@
             ExitInfo.InstrInfo.u = uInstrInfo;
 
-            /* Update the VM-exit qualification. */
+            /* Update the Exit qualification. */
             ExitInfo.u64Qual = GCPtrDisp;
             break;
@@ -3649,5 +3648,5 @@
 {
     /*
-     * Task-switch VM-exits are unconditional and provide the VM-exit qualification.
+     * Task-switch VM-exits are unconditional and provide the Exit qualification.
      *
      * If the cause of the task switch is due to execution of CALL, IRET or the JMP
@@ -3672,9 +3671,8 @@
     }
 
-    uint64_t const uExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS, SelNewTss)
-                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE,  uType);
-    iemVmxVmcsSetExitQual(pVCpu, uExitQual);
+    uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS, SelNewTss)
+                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE,  uType);
     iemVmxVmcsSetExitInstrLen(pVCpu, cbInstr);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH, u64ExitQual);
 }
 
@@ -3697,5 +3695,5 @@
     Assert(pExitEventInfo);
 
-    /* The VM-exit qualification is mandatory for all task-switch VM-exits. */
+    /* The Exit qualification is mandatory for all task-switch VM-exits. */
     uint64_t const u64ExitQual = pExitInfo->u64Qual;
     iemVmxVmcsSetExitQual(pVCpu, u64ExitQual);
@@ -3743,5 +3741,5 @@
         iemVmxVmcsSetExitInstrLen(pVCpu, pExitInfo->cbInstr);
     }
-    return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH, u64ExitQual);
 }
 
@@ -3775,6 +3773,6 @@
                 pVmcs->u32PreemptTimer = 0;
 
-            /* Cause the VMX-preemption timer VM-exit. The VM-exit qualification MBZ. */
-            return iemVmxVmexit(pVCpu, VMX_EXIT_PREEMPT_TIMER);
+            /* Cause the VMX-preemption timer VM-exit. The Exit qualification MBZ. */
+            return iemVmxVmexit(pVCpu, VMX_EXIT_PREEMPT_TIMER, 0 /* u64ExitQual */);
         }
     }
@@ -3820,5 +3818,5 @@
              */
             if (!(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT))
-                return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT);
+                return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT, 0 /* u64ExitQual */);
 
             /*
@@ -3846,23 +3844,9 @@
                                           | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID,            1);
             iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
-            return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT);
+            return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT, 0 /* u64ExitQual */);
         }
     }
 
     return VINF_VMX_INTERCEPT_NOT_ACTIVE;
-}
-
-
-/**
- * VMX VM-exit handler for VM-exits due to startup-IPIs (SIPI).
- *
- * @returns VBox strict status code.
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   uVector     The SIPI vector.
- */
-IEM_STATIC VBOXSTRICTRC iemVmxVmexitStartupIpi(PVMCPU pVCpu, uint8_t uVector)
-{
-    iemVmxVmcsSetExitQual(pVCpu, uVector);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_SIPI);
 }
 
@@ -3891,5 +3875,4 @@
         iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
         iemVmxVmcsSetExitIntErrCode(pVCpu, 0);
-        iemVmxVmcsSetExitQual(pVCpu, 0);
         iemVmxVmcsSetExitInstrLen(pVCpu, 0);
 
@@ -3906,6 +3889,5 @@
         iemVmxVmcsSetIdtVectoringInfo(pVCpu, 0);
         iemVmxVmcsSetIdtVectoringErrCode(pVCpu, 0);
-
-        return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI);
+        return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI, 0 /* u64ExitQual */);
     }
 
@@ -3931,5 +3913,4 @@
     Assert(VMX_EXIT_INT_INFO_IS_VALID(pExitEventInfo->uExitIntInfo));
 
-    iemVmxVmcsSetExitQual(pVCpu, pExitInfo->u64Qual);
     iemVmxVmcsSetExitInstrLen(pVCpu, pExitInfo->cbInstr);
     iemVmxVmcsSetExitIntInfo(pVCpu, pExitEventInfo->uExitIntInfo);
@@ -3937,5 +3918,5 @@
     iemVmxVmcsSetIdtVectoringInfo(pVCpu, pExitEventInfo->uIdtVectoringInfo);
     iemVmxVmcsSetIdtVectoringErrCode(pVCpu, pExitEventInfo->uIdtVectoringErrCode);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI, pExitInfo->u64Qual);
 }
 
@@ -4023,17 +4004,17 @@
 
         /* Construct the rest of the event related information fields and cause the VM-exit. */
-        uint64_t uExitQual;
+        uint64_t u64ExitQual;
         if (uVector == X86_XCPT_PF)
         {
             Assert(fFlags & IEM_XCPT_FLAGS_CR2);
-            uExitQual = uCr2;
+            u64ExitQual = uCr2;
         }
         else if (uVector == X86_XCPT_DB)
         {
             IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR6);
-            uExitQual = pVCpu->cpum.GstCtx.dr[6] & VMX_VMCS_EXIT_QUAL_VALID_MASK;
-        }
-        else
-            uExitQual = 0;
+            u64ExitQual = pVCpu->cpum.GstCtx.dr[6] & VMX_VMCS_EXIT_QUAL_VALID_MASK;
+        }
+        else
+            u64ExitQual = 0;
 
         uint8_t  const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
@@ -4047,5 +4028,4 @@
         iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
         iemVmxVmcsSetExitIntErrCode(pVCpu, uErrCode);
-        iemVmxVmcsSetExitQual(pVCpu, uExitQual);
 
         /*
@@ -4060,5 +4040,5 @@
             iemVmxVmcsSetExitInstrLen(pVCpu, 0);
 
-        return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI);
+        return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI, u64ExitQual);
     }
 
@@ -4087,5 +4067,5 @@
     iemVmxVmcsSetIdtVectoringErrCode(pVCpu, 0);
 
-    return iemVmxVmexit(pVCpu, VMX_EXIT_TRIPLE_FAULT);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_TRIPLE_FAULT, 0 /* u64ExitQual */);
 }
 
@@ -4114,8 +4094,7 @@
         enmAccess = VMXAPICACCESS_LINEAR_WRITE;
 
-    uint64_t const uExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_APIC_ACCESS_OFFSET, offAccess)
-                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_APIC_ACCESS_TYPE,   enmAccess);
-    iemVmxVmcsSetExitQual(pVCpu, uExitQual);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_ACCESS);
+    uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_APIC_ACCESS_OFFSET, offAccess)
+                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_APIC_ACCESS_TYPE,   enmAccess);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_ACCESS, u64ExitQual);
 }
 
@@ -4139,8 +4118,7 @@
     iemVmxVmcsSetExitIntInfo(pVCpu, 0);
     iemVmxVmcsSetExitIntErrCode(pVCpu, 0);
-    iemVmxVmcsSetExitQual(pVCpu, pExitInfo->u64Qual);
     iemVmxVmcsSetIdtVectoringInfo(pVCpu, pExitEventInfo->uIdtVectoringInfo);
     iemVmxVmcsSetIdtVectoringErrCode(pVCpu, pExitEventInfo->uIdtVectoringErrCode);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_ACCESS);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_ACCESS, pExitInfo->u64Qual);
 }
 
@@ -4156,21 +4134,7 @@
 {
     Assert(offApic < XAPIC_OFF_END + 4);
-
-    /* Write only bits 11:0 of the APIC offset into the VM-exit qualification field. */
+    /* Write only bits 11:0 of the APIC offset into the Exit qualification field. */
     offApic &= UINT16_C(0xfff);
-    iemVmxVmcsSetExitQual(pVCpu, offApic);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_WRITE);
-}
-
-
-/**
- * VMX VM-exit handler for virtualized-EOIs.
- *
- * @param   pVCpu       The cross context virtual CPU structure.
- */
-IEM_STATIC VBOXSTRICTRC iemVmxVmexitVirtEoi(PVMCPU pVCpu, uint8_t uVector)
-{
-    iemVmxVmcsSetExitQual(pVCpu, uVector);
-    return iemVmxVmexit(pVCpu, VMX_EXIT_VIRTUALIZED_EOI);
+    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_WRITE, offApic);
 }
 
@@ -4926,5 +4890,5 @@
         {
             Log2(("tpr_virt: uTpr=%u uTprThreshold=%u -> VM-exit\n", uTpr, uTprThreshold));
-            return iemVmxVmexit(pVCpu, VMX_EXIT_TPR_BELOW_THRESHOLD);
+            return iemVmxVmexit(pVCpu, VMX_EXIT_TPR_BELOW_THRESHOLD, 0 /* u64ExitQual */);
         }
     }
@@ -5001,5 +4965,5 @@
     iemVmxPprVirtualization(pVCpu);
     if (iemVmxIsEoiInterceptSet(pVCpu, uVector))
-        return iemVmxVmexitVirtEoi(pVCpu, uVector);
+        return iemVmxVmexit(pVCpu, VMX_EXIT_VIRTUALIZED_EOI, uVector);
     iemVmxEvalPendingVirtIntrs(pVCpu);
     return VINF_SUCCESS;
@@ -5901,5 +5865,5 @@
                 /*
                  * 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
+                 * We update the 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.
@@ -7051,5 +7015,5 @@
                  * If we're in ring-0, we cannot handle returns to ring-3 at this point and continue VM-entry.
                  * If any guest hypervisor loads MSRs that require ring-3 handling, we cause a VM-entry failure
-                 * recording the MSR index in the VM-exit qualification (as per the Intel spec.) and indicated
+                 * recording the MSR index in the Exit qualification (as per the Intel spec.) and indicated
                  * further by our own, specific diagnostic code. Later, we can try implement handling of the
                  * MSR in ring-0 if possible, or come up with a better, generic solution.
@@ -7489,5 +7453,5 @@
      * specified to be undefined needs to be initialized here.
      *
-     * Thus, it is especially important to clear the VM-exit qualification field
+     * Thus, it is especially important to clear the Exit qualification field
      * since it must be zero for VM-exits where it is not used. Similarly, the
      * VM-exit interruption information field's valid bit needs to be cleared for
@@ -7644,6 +7608,8 @@
      * See Intel spec. 24.11.4 "Software Access to Related Structures".
      */
-    Assert(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs));
+    PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    Assert(pVmcs);
     Assert(IEM_VMX_HAS_CURRENT_VMCS(pVCpu));
+
     int rc = iemVmxVmentryCheckExecCtls(pVCpu, pszInstr);
     if (RT_SUCCESS(rc))
@@ -7682,5 +7648,5 @@
                                 /* VMLAUNCH instruction must update the VMCS launch state. */
                                 if (uInstrId == VMXINSTRID_VMLAUNCH)
-                                    pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs)->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_LAUNCHED;
+                                    pVmcs->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_LAUNCHED;
 
                                 /* Perform the VMX transition (PGM updates). */
@@ -7752,8 +7718,10 @@
                                 return rcStrict;
                             }
-                            return iemVmxVmexit(pVCpu, VMX_EXIT_ERR_MSR_LOAD | VMX_EXIT_REASON_ENTRY_FAILED);
+                            return iemVmxVmexit(pVCpu, VMX_EXIT_ERR_MSR_LOAD | VMX_EXIT_REASON_ENTRY_FAILED,
+                                                pVmcs->u64RoExitQual.u);
                         }
                     }
-                    return iemVmxVmexit(pVCpu, VMX_EXIT_ERR_INVALID_GUEST_STATE | VMX_EXIT_REASON_ENTRY_FAILED);
+                    return iemVmxVmexit(pVCpu, VMX_EXIT_ERR_INVALID_GUEST_STATE | VMX_EXIT_REASON_ENTRY_FAILED,
+                                        pVmcs->u64RoExitQual.u);
                 }
 
