Index: trunk/include/VBox/vmm/cpum.h
===================================================================
--- trunk/include/VBox/vmm/cpum.h	(revision 72642)
+++ trunk/include/VBox/vmm/cpum.h	(revision 72643)
@@ -1376,5 +1376,5 @@
  * @param   pCtx    Current CPU context.
  */
-DECLINLINE(bool) CPUMIsGuestInLongModeEx(PCPUMCTX pCtx)
+DECLINLINE(bool) CPUMIsGuestInLongModeEx(PCCPUMCTX pCtx)
 {
     return (pCtx->msrEFER & MSR_K6_EFER_LMA) == MSR_K6_EFER_LMA;
@@ -1452,7 +1452,7 @@
     if (!pVmcb)
         return false;
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return RT_BOOL(pVmcb->ctrl.u64InterceptCtrl & fIntercept);
-    return HMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, fIntercept);
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmCtrlInterceptSet(pVCpu, fIntercept);
+    return RT_BOOL(pVmcb->ctrl.u64InterceptCtrl & fIntercept);
 }
 
@@ -1471,7 +1471,7 @@
     if (!pVmcb)
         return false;
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return RT_BOOL(pVmcb->ctrl.u16InterceptRdCRx & (UINT16_C(1) << uCr));
-    return HMIsGuestSvmReadCRxInterceptSet(pVCpu, pCtx, uCr);
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmReadCRxInterceptSet(pVCpu, uCr);
+    return RT_BOOL(pVmcb->ctrl.u16InterceptRdCRx & (UINT16_C(1) << uCr));
 }
 
@@ -1490,7 +1490,7 @@
     if (!pVmcb)
         return false;
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return RT_BOOL(pVmcb->ctrl.u16InterceptWrCRx & (UINT16_C(1) << uCr));
-    return HMIsGuestSvmWriteCRxInterceptSet(pVCpu, pCtx, uCr);
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmWriteCRxInterceptSet(pVCpu, uCr);
+    return RT_BOOL(pVmcb->ctrl.u16InterceptWrCRx & (UINT16_C(1) << uCr));
 }
 
@@ -1509,7 +1509,7 @@
     if (!pVmcb)
         return false;
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return RT_BOOL(pVmcb->ctrl.u16InterceptRdDRx & (UINT16_C(1) << uDr));
-    return HMIsGuestSvmReadDRxInterceptSet(pVCpu, pCtx, uDr);
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmReadDRxInterceptSet(pVCpu, uDr);
+    return RT_BOOL(pVmcb->ctrl.u16InterceptRdDRx & (UINT16_C(1) << uDr));
 }
 
@@ -1528,7 +1528,7 @@
     if (!pVmcb)
         return false;
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return RT_BOOL(pVmcb->ctrl.u16InterceptWrDRx & (UINT16_C(1) << uDr));
-    return HMIsGuestSvmWriteDRxInterceptSet(pVCpu, pCtx, uDr);
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmWriteDRxInterceptSet(pVCpu, uDr);
+    return RT_BOOL(pVmcb->ctrl.u16InterceptWrDRx & (UINT16_C(1) << uDr));
 }
 
@@ -1547,7 +1547,7 @@
     if (!pVmcb)
         return false;
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return RT_BOOL(pVmcb->ctrl.u32InterceptXcpt & (UINT32_C(1) << uVector));
-    return HMIsGuestSvmXcptInterceptSet(pVCpu, pCtx, uVector);
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmXcptInterceptSet(pVCpu, uVector);
+    return RT_BOOL(pVmcb->ctrl.u32InterceptXcpt & (UINT32_C(1) << uVector));
 }
 
@@ -1564,8 +1564,9 @@
 {
     PCSVMVMCB pVmcb = pCtx->hwvirt.svm.CTX_SUFF(pVmcb);
-    Assert(pVmcb);
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return pVmcb->ctrl.IntCtrl.n.u1VIntrMasking;
-    return HMIsGuestSvmVirtIntrMasking(pVCpu, pCtx);
+    if (!pVmcb)
+        return false;
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmVirtIntrMasking(pVCpu);
+    return pVmcb->ctrl.IntCtrl.n.u1VIntrMasking;
 }
 
@@ -1582,8 +1583,9 @@
 {
     PCSVMVMCB pVmcb = pCtx->hwvirt.svm.CTX_SUFF(pVmcb);
-    Assert(pVmcb);
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return pVmcb->ctrl.NestedPagingCtrl.n.u1NestedPaging;
-    return HMIsGuestSvmNestedPagingEnabled(pVCpu, pCtx);
+    if (!pVmcb)
+        return false;
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMIsGuestSvmNestedPagingEnabled(pVCpu);
+    return pVmcb->ctrl.NestedPagingCtrl.n.u1NestedPaging;
 }
 
@@ -1600,8 +1602,9 @@
 {
     PCSVMVMCB pVmcb = pCtx->hwvirt.svm.CTX_SUFF(pVmcb);
-    Assert(pVmcb);
-    if (!pCtx->hwvirt.svm.fHMCachedVmcb)
-        return pVmcb->ctrl.u16PauseFilterCount;
-    return HMGetGuestSvmPauseFilterCount(pVCpu, pCtx);
+    if (!pVmcb)
+        return false;
+    if (HMHasGuestSvmVmcbCached(pVCpu))
+        return HMGetGuestSvmPauseFilterCount(pVCpu);
+    return pVmcb->ctrl.u16PauseFilterCount;
 }
 
Index: trunk/include/VBox/vmm/cpum.mac
===================================================================
--- trunk/include/VBox/vmm/cpum.mac	(revision 72642)
+++ trunk/include/VBox/vmm/cpum.mac	(revision 72643)
@@ -270,5 +270,4 @@
     .hwvirt.svm.cPauseFilterThreshold  resw          1
     .hwvirt.svm.fInterceptEvents       resb          1
-    .hwvirt.svm.fHMCachedVmcb          resb          1
     alignb 8
     .hwvirt.svm.pvMsrBitmapR0          RTR0PTR_RES   1
Index: trunk/include/VBox/vmm/cpumctx.h
===================================================================
--- trunk/include/VBox/vmm/cpumctx.h	(revision 72642)
+++ trunk/include/VBox/vmm/cpumctx.h	(revision 72643)
@@ -511,8 +511,6 @@
                 /** 0x3c4 - Whether the injected event is subject to event intercepts. */
                 bool                fInterceptEvents;
-                /** 0x3c5 - Whether parts of the VMCB are cached (and potentially modified) by HM. */
-                bool                fHMCachedVmcb;
-                /** 0x3c6 - Padding. */
-                bool                afPadding[2];
+                /** 0x3c5 - Padding. */
+                bool                afPadding[3];
                 /** 0x3c8 - MSR permission bitmap - R0 ptr. */
                 R0PTRTYPE(void *)   pvMsrBitmapR0;
@@ -764,5 +762,5 @@
 
 /** @name CPUMCTX_EXTRN_XXX
- * Used to parts of the CPUM state that is externalized and needs fetching
+ * Used for parts of the CPUM state that is externalized and needs fetching
  * before use.
  *
@@ -893,4 +891,7 @@
                                                  | CPUMCTX_EXTRN_SYSENTER_MSRS | CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS)
 
+/** Hardware-virtualization (SVM or VMX) state is kept externally. */
+#define CPUMCTX_EXTRN_HWVIRT                    UINT64_C(0x0000020000000000)
+
 /** Mask of bits the keepers can use for state tracking. */
 #define CPUMCTX_EXTRN_KEEPER_STATE_MASK         UINT64_C(0xffff000000000000)
@@ -905,6 +906,19 @@
 #define CPUMCTX_EXTRN_NEM_WIN_MASK              UINT64_C(0x0007000000000000)
 
+/** HM/SVM: Inhibit maskable interrupts (VMCPU_FF_INHIBIT_INTERRUPTS). */
+#define CPUMCTX_EXTRN_HM_SVM_INT_SHADOW         UINT64_C(0x0001000000000000)
+/** HM/SVM: Nested-guest interrupt pending (VMCPU_FF_INTERRUPT_NESTED_GUEST). */
+#define CPUMCTX_EXTRN_HM_SVM_HWVIRT_VIRQ        UINT64_C(0x0002000000000000)
+/** HM/SVM: Mask. */
+#define CPUMCTX_EXTRN_HM_SVM_MASK               UINT64_C(0x0003000000000000)
+
+/** HM/VMX: Guest-interruptibility state (VMCPU_FF_INHIBIT_INTERRUPTS,
+ *  VMCPU_FF_BLOCK_NMIS). */
+#define CPUMCTX_EXTRN_HM_VMX_INT_STATE          UINT64_C(0x0001000000000000)
+/** HM/VMX: Mask. */
+#define CPUMCTX_EXTRN_HM_VMX_MASK               UINT64_C(0x0001000000000000)
+
 /** All CPUM state bits, not including keeper specific ones. */
-#define CPUMCTX_EXTRN_ALL                       UINT64_C(0x000001fffffffffc)
+#define CPUMCTX_EXTRN_ALL                       UINT64_C(0x000003fffffffffc)
 /** @} */
 
Index: trunk/include/VBox/vmm/hm.h
===================================================================
--- trunk/include/VBox/vmm/hm.h	(revision 72642)
+++ trunk/include/VBox/vmm/hm.h	(revision 72643)
@@ -216,4 +216,6 @@
 VMMR0_INT_DECL(void)            HMR0NotifyCpumModifiedHostCr0(PVMCPU VCpu);
 VMMR0_INT_DECL(bool)            HMR0SuspendPending(void);
+VMMR0_INT_DECL(int)             HMR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt);
+VMMR0_INT_DECL(int)             HMR0ImportStateOnDemand(PVMCPU pVCpu, PCPUMCTX pCtx, uint64_t fWhat);
 
 # if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
Index: trunk/include/VBox/vmm/hm_svm.h
===================================================================
--- trunk/include/VBox/vmm/hm_svm.h	(revision 72642)
+++ trunk/include/VBox/vmm/hm_svm.h	(revision 72643)
@@ -1067,6 +1067,8 @@
     /** Cache of the LBR virtualization bit. */
     bool                fLbrVirt;
+    /** Whether the VMCB is cached by HM.  */
+    bool                fCacheValid;
     /** Alignment. */
-    bool                afPadding0[5];
+    bool                afPadding0[4];
 } SVMNESTEDVMCBCACHE;
 #pragma pack()
@@ -1076,8 +1078,4 @@
 typedef const SVMNESTEDVMCBCACHE *PCSVMNESTEDVMCBCACHE;
 AssertCompileSizeAlignment(SVMNESTEDVMCBCACHE, 8);
-
-#ifdef IN_RING0
-VMMR0DECL(int) SVMR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt);
-#endif /* IN_RING0 */
 
 /**
@@ -1140,13 +1138,15 @@
  * Don't add any more functions here unless there is no other option.
  */
-VMM_INT_DECL(bool)     HMIsGuestSvmCtrlInterceptSet(PVMCPU pVCpu, PCPUMCTX pCtx, uint64_t fIntercept);
-VMM_INT_DECL(bool)     HMIsGuestSvmReadCRxInterceptSet(PVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uCr);
-VMM_INT_DECL(bool)     HMIsGuestSvmWriteCRxInterceptSet(PVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uCr);
-VMM_INT_DECL(bool)     HMIsGuestSvmReadDRxInterceptSet(PVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uDr);
-VMM_INT_DECL(bool)     HMIsGuestSvmWriteDRxInterceptSet(PVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uDr);
-VMM_INT_DECL(bool)     HMIsGuestSvmXcptInterceptSet(PVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uVector);
-VMM_INT_DECL(bool)     HMIsGuestSvmVirtIntrMasking(PVMCPU pVCpu, PCCPUMCTX pCtx);
-VMM_INT_DECL(bool)     HMIsGuestSvmNestedPagingEnabled(PVMCPU pVCpu, PCCPUMCTX pCtx);
-VMM_INT_DECL(uint16_t) HMGetGuestSvmPauseFilterCount(PVMCPU pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(bool)     HMHasGuestSvmVmcbCached(PVMCPU pVCpu);
+VMM_INT_DECL(bool)     HMIsGuestSvmCtrlInterceptSet(PVMCPU pVCpu, uint64_t fIntercept);
+VMM_INT_DECL(bool)     HMIsGuestSvmReadCRxInterceptSet(PVMCPU pVCpu, uint8_t uCr);
+VMM_INT_DECL(bool)     HMIsGuestSvmWriteCRxInterceptSet(PVMCPU pVCpu, uint8_t uCr);
+VMM_INT_DECL(bool)     HMIsGuestSvmReadDRxInterceptSet(PVMCPU pVCpu, uint8_t uDr);
+VMM_INT_DECL(bool)     HMIsGuestSvmWriteDRxInterceptSet(PVMCPU pVCpu, uint8_t uDr);
+VMM_INT_DECL(bool)     HMIsGuestSvmXcptInterceptSet(PVMCPU pVCpu, uint8_t uVector);
+VMM_INT_DECL(bool)     HMIsGuestSvmVirtIntrMasking(PVMCPU pVCpu);
+VMM_INT_DECL(bool)     HMIsGuestSvmNestedPagingEnabled(PVMCPU pVCpu);
+VMM_INT_DECL(uint16_t) HMGetGuestSvmPauseFilterCount(PVMCPU pVCpu);
+
 /** @} */
 
Index: trunk/include/VBox/vmm/hm_vmx.h
===================================================================
--- trunk/include/VBox/vmm/hm_vmx.h	(revision 72642)
+++ trunk/include/VBox/vmm/hm_vmx.h	(revision 72643)
@@ -2535,9 +2535,4 @@
 }
 
-#ifdef IN_RING0
-VMMR0DECL(int) VMXR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt);
-VMMR0DECL(int) VMXR0InvalidatePhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys);
-#endif /* IN_RING0 */
-
 /** @} */
 
Index: trunk/include/VBox/vmm/iem.h
===================================================================
--- trunk/include/VBox/vmm/iem.h	(revision 72642)
+++ trunk/include/VBox/vmm/iem.h	(revision 72643)
@@ -218,4 +218,24 @@
                                                     | CPUMCTX_EXTRN_DR7 /* for memory breakpoints */ )
 
+#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
+/** The CPUMCTX_EXTRN_XXX mask needed when calling IEMExecSvmVmexit().
+ * IEM will ASSUME the caller has ensured these are already present. */
+# define IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK   (  CPUMCTX_EXTRN_RSP \
+                                              | CPUMCTX_EXTRN_RAX \
+                                              | CPUMCTX_EXTRN_RIP \
+                                              | CPUMCTX_EXTRN_RFLAGS \
+                                              | CPUMCTX_EXTRN_CS \
+                                              | CPUMCTX_EXTRN_SS \
+                                              | CPUMCTX_EXTRN_DS \
+                                              | CPUMCTX_EXTRN_ES \
+                                              | CPUMCTX_EXTRN_GDTR \
+                                              | CPUMCTX_EXTRN_IDTR \
+                                              | CPUMCTX_EXTRN_CR_MASK \
+                                              | CPUMCTX_EXTRN_EFER \
+                                              | CPUMCTX_EXTRN_DR6 \
+                                              | CPUMCTX_EXTRN_DR7 \
+                                              | CPUMCTX_EXTRN_OTHER_MSRS \
+                                              | CPUMCTX_EXTRN_HWVIRT)
+#endif
 
 VMMDECL(VBOXSTRICTRC)       IEMExecOne(PVMCPU pVCpu);
