Index: /trunk/include/VBox/vmm/hm.h
===================================================================
--- /trunk/include/VBox/vmm/hm.h	(revision 76289)
+++ /trunk/include/VBox/vmm/hm.h	(revision 76290)
@@ -218,4 +218,5 @@
 VMMR0_INT_DECL(int)             HMR0Init(void);
 VMMR0_INT_DECL(int)             HMR0Term(void);
+VMMR0_INT_DECL(int)             HMR0PreInitVM(PVM pVM);
 VMMR0_INT_DECL(int)             HMR0InitVM(PVM pVM);
 VMMR0_INT_DECL(int)             HMR0TermVM(PVM pVM);
Index: /trunk/include/VBox/vmm/vmm.h
===================================================================
--- /trunk/include/VBox/vmm/vmm.h	(revision 76289)
+++ /trunk/include/VBox/vmm/vmm.h	(revision 76290)
@@ -338,8 +338,10 @@
     VMMR0_DO_VMMR0_TERM,
 
-    /** Setup the hardware accelerated raw-mode session. */
+    /** Setup hardware-assisted VM session. */
     VMMR0_DO_HM_SETUP_VM = 128,
-    /** Attempt to enable or disable hardware accelerated raw-mode. */
+    /** Attempt to enable or disable hardware-assisted mode. */
     VMMR0_DO_HM_ENABLE,
+    /** Pre-initialize hardware-assisted VM session. */
+    VMMR0_DO_HM_PRE_INIT,
 
     /** Call PGMR0PhysAllocateHandyPages(). */
Index: /trunk/src/VBox/VMM/VMMR0/HMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMR0.cpp	(revision 76289)
+++ /trunk/src/VBox/VMM/VMMR0/HMR0.cpp	(revision 76290)
@@ -28,5 +28,4 @@
 #include <VBox/vmm/hm_vmx.h>
 #include <VBox/vmm/hm_svm.h>
-#include <VBox/vmm/gim.h>
 #include <VBox/err.h>
 #include <VBox/log.h>
@@ -1198,26 +1197,22 @@
 
 /**
- * Does ring-0 per-VM HM initialization.
- *
- * This will copy HM global into the VM structure and call the CPU specific
- * init routine which will allocate resources for each virtual CPU and such.
+ * Pre-initializes ring-0 HM per-VM structures.
+ *
+ * This is the first HM ring-0 function to be called when a VM is created. It is
+ * called after VT-x/AMD-V has been detected, and initialized and -after- HM's CFGM
+ * settings have been queried.
+ *
+ * This copies relevant, global HM structures into per-VM data and initializes some
+ * per-VCPU data.
  *
  * @returns VBox status code.
  * @param   pVM         The cross context VM structure.
  *
- * @remarks This is called after HMR3Init(), see vmR3CreateU() and
- *          vmR3InitRing3().
- */
-VMMR0_INT_DECL(int) HMR0InitVM(PVM pVM)
+ * @remarks This is called during HMR3Init(). Be really careful what we call here as
+ *          almost no VM machinery is up at this point (e.g. PGM, CPUM).
+ */
+VMMR0_INT_DECL(int) HMR0PreInitVM(PVM pVM)
 {
     AssertReturn(pVM, VERR_INVALID_PARAMETER);
-
-#ifdef LOG_ENABLED
-    SUPR0Printf("HMR0InitVM: %p\n", pVM);
-#endif
-
-    /* Make sure we don't touch HM after we've disabled HM in preparation of a suspend. */
-    if (ASMAtomicReadBool(&g_HmR0.fSuspended))
-        return VERR_HM_SUSPEND_PENDING;
 
     /*
@@ -1264,5 +1259,4 @@
         pVCpu->hm.s.idEnteredCpu   = NIL_RTCPUID;
         pVCpu->hm.s.idLastCpu      = NIL_RTCPUID;
-        pVCpu->hm.s.fGIMTrapXcptUD = GIMShouldTrapXcptUD(pVCpu);
 
         /* We'll aways increment this the first time (host uses ASID 0). */
@@ -1270,4 +1264,35 @@
     }
 
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Does ring-0 per-VM HM initialization.
+ *
+ * This will call the CPU specific init. routine which may initialize and allocate
+ * resources for virtual CPUs.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The cross context VM structure.
+ *
+ * @remarks This is called after HMR3Init(), see vmR3CreateU() and
+ *          vmR3InitRing3().
+ */
+VMMR0_INT_DECL(int) HMR0InitVM(PVM pVM)
+{
+    AssertReturn(pVM, VERR_INVALID_PARAMETER);
+
+    /* Make sure we don't touch HM after we've disabled HM in preparation of a suspend. */
+    if (ASMAtomicReadBool(&g_HmR0.fSuspended))
+        return VERR_HM_SUSPEND_PENDING;
+
+    /*
+     * Get host kernel features that HM might need to know in order
+     * to co-operate and function properly with the host OS (e.g. SMAP).
+     *
+     * Technically, we could do this as part of the pre-init VM procedure
+     * but it shouldn't be done later than this point so we do it here.
+     */
     pVM->hm.s.fHostKernelFeatures = SUPR0GetKernelFeatures();
 
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 76289)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 76290)
@@ -1930,4 +1930,12 @@
 
         /*
+         * Pre-initialize hardware-assisted mode per-VM data.
+         */
+        case VMMR0_DO_HM_PRE_INIT:
+            rc = HMR0PreInitVM(pVM);
+            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
+            break;
+
+        /*
          * Switch to RC to execute Hypervisor function.
          */
Index: /trunk/src/VBox/VMM/VMMR3/HM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 76289)
+++ /trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 76290)
@@ -46,4 +46,5 @@
 #include <VBox/vmm/pgm.h>
 #include <VBox/vmm/ssm.h>
+#include <VBox/vmm/gim.h>
 #include <VBox/vmm/trpm.h>
 #include <VBox/vmm/dbgf.h>
@@ -400,5 +401,5 @@
 static DECLCALLBACK(void) hmR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
 static DECLCALLBACK(void) hmR3InfoEventPending(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
-static int                hmR3InitCPU(PVM pVM);
+static int                hmR3InitFinalizeR3(PVM pVM);
 static int                hmR3InitFinalizeR0(PVM pVM);
 static int                hmR3InitFinalizeR0Intel(PVM pVM);
@@ -702,6 +703,9 @@
             if (fCaps & SUPVTCAPS_AMD_V)
             {
+                rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_PRE_INIT, 0, NULL);
+                AssertRCReturn(rc, rc);
+                Assert(pVM->hm.s.svm.fSupported);
+
                 LogRel(("HM: HMR3Init: AMD-V%s\n", fCaps & SUPVTCAPS_NESTED_PAGING ? " w/ nested paging" : ""));
-                pVM->hm.s.svm.fSupported = true;
                 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_HW_VIRT);
             }
@@ -712,9 +716,12 @@
                 if (RT_SUCCESS(rc))
                 {
+                    rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_PRE_INIT, 0, NULL);
+                    AssertRCReturn(rc, rc);
+                    Assert(pVM->hm.s.vmx.fSupported);
+
                     LogRel(("HM: HMR3Init: VT-x%s%s%s\n",
                             fCaps & SUPVTCAPS_NESTED_PAGING ? " w/ nested paging" : "",
                             fCaps & SUPVTCAPS_VTX_UNRESTRICTED_GUEST ? " and unrestricted guest execution" : "",
                             (fCaps & (SUPVTCAPS_NESTED_PAGING | SUPVTCAPS_VTX_UNRESTRICTED_GUEST)) ? " hw support" : ""));
-                    pVM->hm.s.vmx.fSupported = true;
                     VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_HW_VIRT);
                 }
@@ -844,10 +851,10 @@
 
 /**
- * Initializes the per-VCPU HM.
+ * Initializes HM components after ring-3 phase has been fully initialized.
  *
  * @returns VBox status code.
  * @param   pVM         The cross context VM structure.
  */
-static int hmR3InitCPU(PVM pVM)
+static int hmR3InitFinalizeR3(PVM pVM)
 {
     LogFlow(("HMR3InitCPU\n"));
@@ -860,4 +867,5 @@
         PVMCPU pVCpu = &pVM->aCpus[i];
         pVCpu->hm.s.fActive = false;
+        pVCpu->hm.s.fGIMTrapXcptUD = GIMShouldTrapXcptUD(pVCpu);    /* Is safe to call now since GIMR3Init() has completed. */
     }
 
@@ -1180,5 +1188,5 @@
     {
         case VMINITCOMPLETED_RING3:
-            return hmR3InitCPU(pVM);
+            return hmR3InitFinalizeR3(pVM);
         case VMINITCOMPLETED_RING0:
             return hmR3InitFinalizeR0(pVM);
