Index: /trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h	(revision 97052)
+++ /trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h	(revision 97053)
@@ -39,4 +39,6 @@
 #endif
 
+/** Enables condensing of VMREAD instructions, see vmxHCReadToTransient(). */
+#define HMVMX_WITH_CONDENSED_VMREADS
 
 /** Use the function table. */
@@ -1341,4 +1343,154 @@
     }
 }
+
+
+/**
+ * Reads VMCS fields into the VMXTRANSIENT structure, slow path version.
+ *
+ * Don't call directly unless the it's likely that some or all of the fields
+ * given in @a a_fReadMask have already been read.
+ *
+ * @tparam  a_fReadMask     The fields to read.
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   pVmxTransient   The VMX-transient structure.
+ */
+template<uint32_t const a_fReadMask>
+static void vmxHCReadToTransientSlow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
+{
+    if ((pVmxTransient->fVmcsFieldsRead & a_fReadMask) != a_fReadMask)
+    {
+        uint32_t const fVmcsFieldsRead = pVmxTransient->fVmcsFieldsRead;
+        int            rc;
+
+        if (   (a_fReadMask      & HMVMX_READ_EXIT_QUALIFICATION)
+            && !(fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
+        {
+            rc = VMX_VMCS_READ_NW(pVCpu, VMX_VMCS_RO_EXIT_QUALIFICATION,             &pVmxTransient->uExitQual);
+            AssertRC(rc);
+        }
+        if (    (a_fReadMask     & HMVMX_READ_EXIT_INSTR_LEN)
+            && !(fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INSTR_LENGTH,            &pVmxTransient->cbExitInstr);
+            AssertRC(rc);
+        }
+        if (   (a_fReadMask      & HMVMX_READ_EXIT_INSTR_INFO)
+            && !(fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INSTR_INFO,              &pVmxTransient->ExitInstrInfo.u);
+            AssertRC(rc);
+        }
+        if (   (a_fReadMask      & HMVMX_READ_IDT_VECTORING_INFO)
+            && !(fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_IDT_VECTORING_INFO,           &pVmxTransient->uIdtVectoringInfo);
+            AssertRC(rc);
+        }
+        if (   (a_fReadMask      & HMVMX_READ_IDT_VECTORING_ERROR_CODE)
+            && !(fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,     &pVmxTransient->uIdtVectoringErrorCode);
+            AssertRC(rc);
+        }
+        if (   (a_fReadMask      & HMVMX_READ_EXIT_INTERRUPTION_INFO)
+            && !(fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,       &pVmxTransient->uExitIntInfo);
+            AssertRC(rc);
+        }
+        if (    (a_fReadMask     & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE)
+            && !(fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
+            AssertRC(rc);
+        }
+        if (   (a_fReadMask      & HMVMX_READ_GUEST_LINEAR_ADDR)
+            && !(fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
+        {
+            rc = VMX_VMCS_READ_NW(pVCpu, VMX_VMCS_RO_GUEST_LINEAR_ADDR,              &pVmxTransient->uGuestLinearAddr);
+            AssertRC(rc);
+        }
+        if (   (a_fReadMask      & HMVMX_READ_GUEST_PHYSICAL_ADDR)
+            && !(fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
+        {
+            rc = VMX_VMCS_READ_64(pVCpu, VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,         &pVmxTransient->uGuestPhysicalAddr);
+            AssertRC(rc);
+        }
+
+        pVmxTransient->fVmcsFieldsRead |= a_fReadMask;
+    }
+}
+
+
+/**
+ * Reads VMCS fields into the VMXTRANSIENT structure.
+ *
+ * This optimizes for the case where none of @a a_fReadMask has been read yet,
+ * generating an optimized read sequences w/o any conditionals between in
+ * non-strict builds.
+ *
+ * @tparam  a_fReadMask     The fields to read.  One or more of the
+ *                          HMVMX_READ_XXX fields ORed together.
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   pVmxTransient   The VMX-transient structure.
+ */
+template<uint32_t const a_fReadMask>
+DECLINLINE(void) vmxHCReadToTransient(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
+{
+    if (RT_LIKELY(!(pVmxTransient->fVmcsFieldsRead & a_fReadMask)))
+    {
+        int rc;
+        if (a_fReadMask & HMVMX_READ_EXIT_QUALIFICATION)
+        {
+            rc = VMX_VMCS_READ_NW(pVCpu, VMX_VMCS_RO_EXIT_QUALIFICATION,             &pVmxTransient->uExitQual);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_EXIT_INSTR_LEN)
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INSTR_LENGTH,            &pVmxTransient->cbExitInstr);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_EXIT_INSTR_INFO)
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INSTR_INFO,              &pVmxTransient->ExitInstrInfo.u);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_IDT_VECTORING_INFO)
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_IDT_VECTORING_INFO,           &pVmxTransient->uIdtVectoringInfo);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_IDT_VECTORING_ERROR_CODE)
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,     &pVmxTransient->uIdtVectoringErrorCode);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_EXIT_INTERRUPTION_INFO)
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,       &pVmxTransient->uExitIntInfo);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE)
+        {
+            rc = VMX_VMCS_READ_32(pVCpu, VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_GUEST_LINEAR_ADDR)
+        {
+            rc = VMX_VMCS_READ_NW(pVCpu, VMX_VMCS_RO_GUEST_LINEAR_ADDR,              &pVmxTransient->uGuestLinearAddr);
+            AssertRC(rc);
+        }
+        if (a_fReadMask & HMVMX_READ_GUEST_PHYSICAL_ADDR)
+        {
+            rc = VMX_VMCS_READ_64(pVCpu, VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,         &pVmxTransient->uGuestPhysicalAddr);
+            AssertRC(rc);
+        }
+
+        pVmxTransient->fVmcsFieldsRead |= a_fReadMask;
+    }
+    else
+        vmxHCReadToTransientSlow<a_fReadMask>(pVCpu, pVmxTransient);
+}
+
 
 #ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
@@ -7107,9 +7259,15 @@
         {
             NOREF(uVector);
+#ifdef HMVMX_WITH_CONDENSED_VMREADS
+            vmxHCReadToTransient<  HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
+                                 | HMVMX_READ_EXIT_INSTR_LEN
+                                 | HMVMX_READ_IDT_VECTORING_INFO
+                                 | HMVMX_READ_IDT_VECTORING_ERROR_CODE>(pVCpu, pVmxTransient);
+#else
             vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient);
             vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
             vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
             vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
-
+#endif
             rcStrict = vmxHCExitXcpt(pVCpu, pVmxTransient);
             break;
@@ -7427,6 +7585,11 @@
 
     PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
+#ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+#else
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
+#endif
     int rc = vmxHCImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
     AssertRCReturn(rc, rc);
@@ -7604,7 +7767,13 @@
     return VERR_EM_INTERPRETER;
 #else
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
@@ -7656,7 +7825,12 @@
     uint32_t fIntrState;
     uint64_t u64Val;
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadEntryIntInfoVmcs(pVCpu, pVmxTransient);
+    vmxHCReadEntryInstrLenVmcs(pVCpu, pVmxTransient);
+# endif
     vmxHCReadEntryXcptErrorCodeVmcs(pVCpu, pVmxTransient);
-    vmxHCReadEntryInstrLenVmcs(pVCpu, pVmxTransient);
 
     Log4(("uInvalidReason                             %u\n",     uInvalidReason));
@@ -8045,6 +8219,11 @@
 
     PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
+# endif
 
     VBOXSTRICTRC rcStrict;
@@ -8221,6 +8400,11 @@
     PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
     PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
+#endif
     int rc = vmxHCImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
                                                      | CPUMCTX_EXTRN_EFER);
@@ -8486,5 +8670,5 @@
 
             vmxHCSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
-                                   pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
+                                 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
 
             Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
@@ -8524,9 +8708,19 @@
     STAM_COUNTER_INC(&VCPU_2_VMXSTATS(pVCpu).StatExitApicAccess);
 
+#ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN
+                         | HMVMX_READ_EXIT_INTERRUPTION_INFO
+                         | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
+                         | HMVMX_READ_IDT_VECTORING_INFO
+                         | HMVMX_READ_IDT_VECTORING_ERROR_CODE>(pVCpu, pVmxTransient);
+#else
+    vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+    vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitIntInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient);
-    vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
+#endif
 
     /*
@@ -8551,5 +8745,4 @@
     /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
     PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
-    vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     int rc = vmxHCImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
     AssertRCReturn(rc, rc);
@@ -8718,9 +8911,18 @@
     Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_INSTR_LEN
+                         | HMVMX_READ_EXIT_INTERRUPTION_INFO
+                         | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
+                         | HMVMX_READ_IDT_VECTORING_INFO
+                         | HMVMX_READ_IDT_VECTORING_ERROR_CODE
+                         | HMVMX_READ_GUEST_PHYSICAL_ADDR>(pVCpu, pVmxTransient);
+# else
+    vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitIntInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient);
-    vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
+# endif
 
     /*
@@ -8740,9 +8942,9 @@
         {
             STAM_COUNTER_INC(&VCPU_2_VMXSTATS(pVCpu).StatInjectInterpret);
-#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
             /** @todo NSTVMX: Think about how this should be handled. */
             if (pVmxTransient->fIsNestedGuest)
                 return VERR_VMX_IPE_3;
-#endif
+# endif
             return VINF_EM_RAW_INJECT_TRPM_EVENT;
         }
@@ -8758,5 +8960,7 @@
      */
     PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
+# ifndef HMVMX_WITH_CONDENSED_VMREADS
     vmxHCReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
     AssertRCReturn(rc, rc);
@@ -8831,10 +9035,20 @@
     Assert(pVCpu->CTX_SUFF(pVM)->hmr0.s.fNestedPaging);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN
+                         | HMVMX_READ_EXIT_INTERRUPTION_INFO
+                         | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
+                         | HMVMX_READ_IDT_VECTORING_INFO
+                         | HMVMX_READ_IDT_VECTORING_ERROR_CODE
+                         | HMVMX_READ_GUEST_PHYSICAL_ADDR>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+    vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitIntInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient);
-    vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
+# endif
 
     /*
@@ -8858,5 +9072,7 @@
 
     PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
+# ifndef HMVMX_WITH_CONDENSED_VMREADS
     vmxHCReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
     AssertRCReturn(rc, rc);
@@ -8896,5 +9112,8 @@
         return VINF_SUCCESS;
     }
-#else
+    Log4Func(("EPT return to ring-3 rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+    return rcStrict;
+
+#else /* IN_NEM_DARWIN */
     PVM pVM = pVCpu->CTX_SUFF(pVM);
     uint64_t const uHostTsc = ASMReadTSC(); RT_NOREF(uHostTsc);
@@ -8966,8 +9185,8 @@
 
     ASMAtomicUoOrU64(&VCPU_2_VMXSTATE(pVCpu).fCtxChanged, HM_CHANGED_ALL_GUEST);
-#endif
-
-    Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+
+    Log4Func(("EPT return rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     return rcStrict;
+#endif /* IN_NEM_DARWIN */
 }
 
@@ -8981,7 +9200,13 @@
     HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | CPUMCTX_EXTRN_HWVIRT
@@ -9042,7 +9267,13 @@
     HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | CPUMCTX_EXTRN_HWVIRT
@@ -9074,7 +9305,13 @@
     HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+#endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | CPUMCTX_EXTRN_HWVIRT
@@ -9111,7 +9348,13 @@
      * code elsewhere dares look at unsynced VMCS fields.
      */
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | CPUMCTX_EXTRN_HWVIRT
@@ -9199,7 +9442,13 @@
      * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
      */
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | CPUMCTX_EXTRN_HWVIRT
@@ -9259,7 +9508,13 @@
     HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | CPUMCTX_EXTRN_HWVIRT
@@ -9291,7 +9546,13 @@
     HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
@@ -9323,7 +9584,13 @@
     HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_INFO
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
     int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
                                                                     | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
@@ -9393,13 +9660,18 @@
         case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
         {
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+            vmxHCReadToTransient<  HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
+                                 | HMVMX_READ_EXIT_INSTR_LEN
+                                 | HMVMX_READ_IDT_VECTORING_INFO
+                                 | HMVMX_READ_IDT_VECTORING_ERROR_CODE>(pVCpu, pVmxTransient);
+# else
             vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient);
             vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
             vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
             vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
+# endif
 
             PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
-            bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
-                                                                   pVmxTransient->uExitIntErrorCode);
-            if (fIntercept)
+            if (CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo), pVmxTransient->uExitIntErrorCode))
             {
                 /* Exit qualification is required for debug and page-fault exceptions. */
@@ -9499,9 +9771,15 @@
     HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN
+                         | HMVMX_READ_IDT_VECTORING_INFO
+                         | HMVMX_READ_IDT_VECTORING_ERROR_CODE>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
-
+# endif
     VMXVEXITINFO const      ExitInfo      = VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN_FROM_TRANSIENT(pVmxTransient);
     VMXVEXITEVENTINFO const ExitEventInfo = VMXVEXITEVENTINFO_INIT_ONLY_IDT(pVmxTransient->uIdtVectoringInfo,
@@ -9536,7 +9814,11 @@
     if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
     {
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+        vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                             | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
         vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
-
+# endif
         VMXVEXITINFO const ExitInfo = VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN_FROM_TRANSIENT(pVmxTransient);
         return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
@@ -9585,7 +9867,11 @@
     if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
     {
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+        vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                             | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
         vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
-
+# endif
         VMXVEXITINFO const ExitInfo = VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_FROM_TRANSIENT(pVmxTransient);
         return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
@@ -9623,6 +9909,11 @@
     HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
+# endif
 
     VBOXSTRICTRC rcStrict;
@@ -9771,7 +10062,11 @@
     if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
     {
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+        vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                             | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
         vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
-
+# endif
         VMXVEXITINFO const ExitInfo = VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN_FROM_TRANSIENT(pVmxTransient);
         return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
@@ -9973,8 +10268,15 @@
     HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN
+                         | HMVMX_READ_IDT_VECTORING_INFO
+                         | HMVMX_READ_IDT_VECTORING_ERROR_CODE>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
     vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+# endif
 
     Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
@@ -10061,8 +10363,13 @@
     {
         Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+        vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                             | HMVMX_READ_EXIT_INSTR_INFO
+                             | HMVMX_READ_EXIT_INSTR_LEN>(pVCpu, pVmxTransient);
+# else
         vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
-
+# endif
         VMXVEXITINFO const ExitInfo = VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_FROM_TRANSIENT(pVmxTransient);
         return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
@@ -10166,8 +10473,13 @@
 # endif
 
+# ifdef HMVMX_WITH_CONDENSED_VMREADS
+    vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                         | HMVMX_READ_EXIT_INSTR_LEN
+                         | HMVMX_READ_EXIT_INSTR_INFO>(pVCpu, pVmxTransient);
+# else
     vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
     vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient);
-
+# endif
     VMXVEXITINFO const ExitInfo = VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_FROM_TRANSIENT(pVmxTransient);
     return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
@@ -10194,12 +10506,22 @@
         AssertRCReturn(rc, rc);
 
+#  ifdef DSL_IRQ_FIX_2
+#   ifdef HMVMX_WITH_CONDENSED_VMREADS
+        vmxHCReadToTransient<  HMVMX_READ_EXIT_QUALIFICATION
+                             | HMVMX_READ_EXIT_INSTR_LEN
+                             | HMVMX_READ_EXIT_INTERRUPTION_INFO
+                             | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
+                             | HMVMX_READ_IDT_VECTORING_INFO
+                             | HMVMX_READ_IDT_VECTORING_ERROR_CODE
+                             | HMVMX_READ_GUEST_PHYSICAL_ADDR>(pVCpu, pVmxTransient);
+#   else
         vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
-        vmxHCReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
-#  ifdef DSL_IRQ_FIX_2
+        vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitIntInfoVmcs(pVCpu, pVmxTransient);
         vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient);
-        vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
         vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
         vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
+        vmxHCReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
+#   endif
 
         /*
@@ -10218,4 +10540,6 @@
         bool const fClearEventOnForward = VCPU_2_VMXSTATE(pVCpu).Event.fPending; /* paranoia. should not inject events below.  */
 #  else
+        vmxHCReadExitQualVmcs(pVCpu, pVmxTransient);
+        vmxHCReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
         VBOXSTRICTRC rcStrict;
 #  endif
@@ -10274,8 +10598,9 @@
         }
 
+#  ifndef DSL_IRQ_FIX_2
         vmxHCReadExitInstrLenVmcs(pVCpu, pVmxTransient);
         vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
         vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
-#  ifdef DSL_IRQ_FIX_2
+#  else
         if (fClearEventOnForward)
             VCPU_2_VMXSTATE(pVCpu).Event.fPending = false;
@@ -10333,6 +10658,11 @@
 
         AssertMsg(Walk.fFailed & PGM_WALKFAIL_EPT_MISCONFIG, ("GCPhysNestedFault=%#RGp\n", GCPhysNestedFault));
+#  ifdef HMVMX_WITH_CONDENSED_VMREADS
+        vmxHCReadToTransient<  HMVMX_READ_IDT_VECTORING_INFO
+                             | HMVMX_READ_IDT_VECTORING_ERROR_CODE>(pVCpu, pVmxTransient);
+#  else
         vmxHCReadIdtVectoringInfoVmcs(pVCpu, pVmxTransient);
         vmxHCReadIdtVectoringErrorCodeVmcs(pVCpu, pVmxTransient);
+#  endif
 
         VMXVEXITEVENTINFO const ExitEventInfo = VMXVEXITEVENTINFO_INIT_ONLY_IDT(pVmxTransient->uIdtVectoringInfo,
