Index: /trunk/include/VBox/sup.h
===================================================================
--- /trunk/include/VBox/sup.h	(revision 43378)
+++ /trunk/include/VBox/sup.h	(revision 43379)
@@ -1363,4 +1363,6 @@
 SUPR0DECL(SUPPAGINGMODE) SUPR0GetPagingMode(void);
 SUPR0DECL(int) SUPR0EnableVTx(bool fEnable);
+SUPR0DECL(bool) SUPR0SuspendVTxOnCpu(void);
+SUPR0DECL(void) SUPR0ResumeVTxOnCpu(bool fSuspended);
 
 /** @name Absolute symbols
Index: /trunk/include/VBox/vmm/hwaccm.h
===================================================================
--- /trunk/include/VBox/vmm/hwaccm.h	(revision 43378)
+++ /trunk/include/VBox/vmm/hwaccm.h	(revision 43379)
@@ -29,4 +29,5 @@
 #include <VBox/vmm/pgm.h>
 #include <VBox/vmm/cpum.h>
+#include <VBox/vmm/vmm.h>
 #include <iprt/mp.h>
 
@@ -82,6 +83,6 @@
 VMMR0DECL(int)          HWACCMR0TermVM(PVM pVM);
 VMMR0DECL(int)          HWACCMR0EnableAllCpus(PVM pVM);
-VMMR0DECL(int)          HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled);
-VMMR0DECL(int)          HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled);
+VMMR0DECL(int)          HWACCMR0EnterSwitcher(PVM pVM, VMMSWITCHER enmSwitcher, bool *pfVTxDisabled);
+VMMR0DECL(void)         HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled);
 
 VMMR0DECL(void)         HWACCMR0SavePendingIOPortWrite(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, unsigned uPort, unsigned uAndVal, unsigned cbSize);
Index: /trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 43378)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 43379)
@@ -267,5 +267,5 @@
  endif
  #VBoxDrv_DEFS.debug      += DEBUG_DARWIN_GIP
- #VBoxDrv_DEFS.darwin     := VBOX_WITH_HOST_VMX - break raw-mode, hack+enable after 4.2.0!
+ #VBoxDrv_DEFS.darwin     := VBOX_WITH_HOST_VMX
  VBoxDrv_DEFS.linux      := \
 	KBUILD_MODNAME=KBUILD_STR\(vboxdrv\) KBUILD_BASENAME=KBUILD_STR\(vboxdrv\) MODULE CONFIG_VBOXDRV_AS_MISC
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 43378)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 43379)
@@ -173,4 +173,6 @@
     { "SUPR0ContFree",                          (void *)SUPR0ContFree },
     { "SUPR0EnableVTx",                         (void *)SUPR0EnableVTx },
+    { "SUPR0SuspendVTxOnCpu",                   (void *)SUPR0SuspendVTxOnCpu },
+    { "SUPR0ResumeVTxOnCpu",                    (void *)SUPR0ResumeVTxOnCpu },
     { "SUPR0GetPagingMode",                     (void *)SUPR0GetPagingMode },
     { "SUPR0LockMem",                           (void *)SUPR0LockMem },
@@ -3188,4 +3190,38 @@
 
 
+/**
+ * Suspends hardware virtualization extensions using the native OS API.
+ *
+ * This is called prior to entering raw-mode context.
+ *
+ * @returns @c true if suspended, @c false if not.
+ */
+SUPR0DECL(bool) SUPR0SuspendVTxOnCpu(void)
+{
+#ifdef RT_OS_DARWIN
+    return supdrvOSSuspendVTxOnCpu();
+#else
+    return false;
+#endif
+}
+
+
+/**
+ * Resumes hardware virtualization extensions using the native OS API.
+ *
+ * This is called after to entering raw-mode context.
+ *
+ * @param   fSuspended      The return value of SUPR0SuspendVTxOnCpu.
+ */
+SUPR0DECL(void) SUPR0ResumeVTxOnCpu(bool fSuspended)
+{
+#ifdef RT_OS_DARWIN
+    supdrvOSResumeVTxOnCpu(fSuspended);
+#else
+    Assert(!fSuspended);
+#endif
+}
+
+
 /** @todo document me */
 SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps)
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 43378)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 43379)
@@ -194,5 +194,5 @@
  *          - Remove RTSpinlockReleaseNoInts.
  */
-#define SUPDRV_IOC_VERSION                              0x001a0004
+#define SUPDRV_IOC_VERSION                              0x001a0005
 
 /** SUP_IOCTL_COOKIE. */
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 43378)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 43379)
@@ -601,4 +601,6 @@
 bool VBOXCALL   supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt);
 int  VBOXCALL   supdrvOSEnableVTx(bool fEnabled);
+bool VBOXCALL   supdrvOSSuspendVTxOnCpu(void);
+void VBOXCALL   supdrvOSResumeVTxOnCpu(bool fSuspended);
 
 /**
Index: /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 43378)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 43379)
@@ -269,5 +269,5 @@
         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
         const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00190000
-                                   ? 0x00190003
+                                   ? 0x001a0005
                                    : SUPDRV_IOC_VERSION & 0xffff0000;
         CookieReq.u.In.u32MinVersion = uMinVersion;
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 43378)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 43379)
@@ -43,4 +43,5 @@
 #include <VBox/version.h>
 #include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
 #include <iprt/initterm.h>
 #include <iprt/assert.h>
@@ -50,4 +51,5 @@
 #include <iprt/alloc.h>
 #include <iprt/power.h>
+#include <iprt/dbg.h>
 #include <VBox/err.h>
 #include <VBox/log.h>
@@ -99,4 +101,6 @@
 static IOReturn         VBoxDrvDarwinSleepHandler(void *pvTarget, void *pvRefCon, UInt32 uMessageType, IOService *pProvider, void *pvMessageArgument, vm_size_t argSize);
 RT_C_DECLS_END
+
+static void             vboxdrvDarwinResolveSymbols(void);
 
 
@@ -211,6 +215,12 @@
 static int32_t volatile g_cSessions = 0;
 /** The notifier handle for the sleep callback handler. */
-static IONotifier *g_pSleepNotifier = NULL;
-
+static IONotifier      *g_pSleepNotifier = NULL;
+
+/** Pointer to vmx_suspend(). */
+static PFNRT            g_pfnVmxSuspend = NULL;
+/** Pointer to vmx_resume(). */
+static PFNRT            g_pfnVmxResume = NULL;
+/** Pointer to vmx_use_count. */
+static int volatile    *g_pVmxUseCount = NULL;
 
 
@@ -267,4 +277,6 @@
                             LogRel(("VBoxDrv: register for sleep/wakeup events failed\n"));
 
+                        /* Find kernel symbols that are kind of optional. */
+                        vboxdrvDarwinResolveSymbols();
                         return KMOD_RETURN_SUCCESS;
                     }
@@ -296,4 +308,37 @@
 
 /**
+ * Resolves kernel symbols we want (but may do without).
+ */
+static void vboxdrvDarwinResolveSymbols(void)
+{
+    RTDBGKRNLINFO hKrnlInfo;
+    int rc = RTR0DbgKrnlInfoOpen(&hKrnlInfo, 0);
+    if (RT_SUCCESS(rc))
+    {
+        /* The VMX stuff. */
+        int rc1 = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, NULL, "vmx_resume", (void **)&g_pfnVmxResume);
+        int rc2 = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, NULL, "vmx_suspend", (void **)&g_pfnVmxSuspend);
+        int rc3 = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, NULL, "vmx_use_count", (void **)&g_pVmxUseCount);
+        if (RT_SUCCESS(rc1) && RT_SUCCESS(rc2) && RT_SUCCESS(rc3))
+        {
+            LogRel(("VBoxDrv: vmx_resume=%p vmx_suspend=%p vmx_use_count=%p (%d) cr4=%#x\n",
+                    g_pfnVmxResume, g_pfnVmxSuspend, g_pVmxUseCount, *g_pVmxUseCount, ASMGetCR4() ));
+        }
+        else
+        {
+            LogRel(("VBoxDrv: failed to resolve vmx stuff: vmx_resume=%Rrc vmx_suspend=%Rrc vmx_use_count=%Rrc", rc1, rc2, rc3));
+            g_pfnVmxResume  = NULL;
+            g_pfnVmxSuspend = NULL;
+            g_pVmxUseCount  = NULL;
+        }
+
+        RTR0DbgKrnlInfoRelease(hKrnlInfo);
+    }
+    else
+        LogRel(("VBoxDrv: Failed to open kernel symbols, rc=%Rrc\n", rc));
+}
+
+
+/**
  * Stop the kernel module.
  */
@@ -711,8 +756,5 @@
 
 /**
- * Enables or disables VT-x using kernel functions.
- *
- * @returns VBox status code. VERR_NOT_SUPPORTED has a special meaning.
- * @param   fEnable     Whether to enable or disable.
+ * @copydoc SUPR0EnableVTx
  */
 int VBOXCALL supdrvOSEnableVTx(bool fEnable)
@@ -720,5 +762,8 @@
 #ifdef VBOX_WITH_HOST_VMX
     int rc;
-    if (version_major >= 10 /* 10 = 10.6.x = Snow Leopard */)
+    if (   version_major >= 10 /* 10 = 10.6.x = Snow Leopard */
+        && g_pfnVmxSuspend
+        && g_pfnVmxResume
+        && g_pVmxUseCount)
     {
         if (fEnable)
@@ -736,4 +781,5 @@
                 rc = VERR_UNRESOLVED_ERROR;
             }
+            LogRel(("VBoxDrv: host_vmxon  -> vmx_use_count=%d rc=%Rrc\n", *g_pVmxUseCount, rc));
         }
         else
@@ -741,4 +787,5 @@
             host_vmxoff();
             rc = VINF_SUCCESS;
+            LogRel(("VBoxDrv: host_vmxoff -> vmx_use_count=%d\n", *g_pVmxUseCount));
         }
     }
@@ -752,4 +799,52 @@
 #else
     return VERR_NOT_SUPPORTED;
+#endif
+}
+
+
+/**
+ * @copydoc SUPR0SuspendVTxOnCpu
+ */
+bool VBOXCALL supdrvOSSuspendVTxOnCpu(void)
+{
+#ifdef VBOX_WITH_HOST_VMX
+    /*
+     * Consult the VMX usage counter, don't try suspend if not enabled.
+     *
+     * Note!  The host_vmxon/off code is still race prone since, but this is
+     *        currently the best we can do without always enable VMX when
+     *        loading the driver.
+     */
+    if (   g_pVmxUseCount
+        && *g_pVmxUseCount > 0)
+    {
+        g_pfnVmxSuspend();
+        return true;
+    }
+    return false;
+#else
+    return false;
+#endif
+}
+
+
+/**
+ * @copydoc SUPR0ResumeVTxOnCpu
+ */
+void VBOXCALL   supdrvOSResumeVTxOnCpu(bool fSuspended)
+{
+#ifdef VBOX_WITH_HOST_VMX
+    /*
+     * Don't consult the counter here, the state knows better.
+     * We're executing with interrupts disabled and anyone racing us with
+     * disabling VT-x will be waiting in the rendezvous code.
+     */
+    if (   fSuspended
+        && g_pfnVmxResume)
+        g_pfnVmxResume();
+    else
+        Assert(!fSuspended);
+#else
+    Assert(!fSuspended);
 #endif
 }
Index: /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 43378)
+++ /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 43379)
@@ -1691,7 +1691,8 @@
  * @returns VBox status code.
  * @param   pVM             Pointer to the VM.
+ * @param   enmSwitcher     The switcher we're about to use.
  * @param   pfVTxDisabled   Where to store whether VT-x was disabled or not.
  */
-VMMR0DECL(int) HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled)
+VMMR0DECL(int) HWACCMR0EnterSwitcher(PVM pVM, VMMSWITCHER enmSwitcher, bool *pfVTxDisabled)
 {
     Assert(!(ASMGetFlags() & X86_EFL_IF) || !RTThreadPreemptIsEnabled(NIL_RTTHREAD));
@@ -1699,10 +1700,10 @@
     *pfVTxDisabled = false;
 
-    if (   !g_HvmR0.fEnabled
-        || !g_HvmR0.vmx.fSupported /* no such issues with AMD-V */
-        || !g_HvmR0.fGlobalInit    /* Local init implies the CPU is currently not in VMX root mode. */)
-        return VINF_SUCCESS;    /* nothing to do */
-
-    switch (VMMGetSwitcher(pVM))
+    /* No such issues with AMD-V */
+    if (!g_HvmR0.vmx.fSupported)
+        return VINF_SUCCESS;
+
+    /* Check if the swithcing we're up to is safe. */
+    switch (enmSwitcher)
     {
         case VMMSWITCHER_32_TO_32:
@@ -1720,4 +1721,24 @@
     }
 
+    /* When using SUPR0EnableVTx we must let the host suspend and resume VT-x,
+       regardless of whether we're currently using VT-x or not. */
+    if (g_HvmR0.vmx.fUsingSUPR0EnableVTx)
+    {
+        *pfVTxDisabled = SUPR0SuspendVTxOnCpu();
+        return VINF_SUCCESS;
+    }
+
+    /** @todo Check if this code is presumtive wrt other VT-x users on the
+     *        system... */
+
+    /* Nothing to do if we haven't enabled VT-x. */
+    if (!g_HvmR0.fEnabled)
+        return VINF_SUCCESS;
+
+    /* Local init implies the CPU is currently not in VMX root mode. */
+    if (!g_HvmR0.fGlobalInit)
+        return VINF_SUCCESS;
+
+    /* Ok, disable VT-x. */
     PHMGLOBLCPUINFO pCpu = HWACCMR0GetCurrentCpu();
     AssertReturn(pCpu && pCpu->hMemObj != NIL_RTR0MEMOBJ, VERR_HM_IPE_2);
@@ -1734,25 +1755,29 @@
  * switcher turned off paging.
  *
- * @returns VBox status code.
  * @param   pVM             Pointer to the VM.
  * @param   fVTxDisabled    Whether VT-x was disabled or not.
  */
-VMMR0DECL(int) HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled)
+VMMR0DECL(void) HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled)
 {
     Assert(!(ASMGetFlags() & X86_EFL_IF));
 
     if (!fVTxDisabled)
-        return VINF_SUCCESS;    /* nothing to do */
-
-    Assert(g_HvmR0.fEnabled);
+        return;         /* nothing to do */
+
     Assert(g_HvmR0.vmx.fSupported);
-    Assert(g_HvmR0.fGlobalInit);
-
-    PHMGLOBLCPUINFO pCpu = HWACCMR0GetCurrentCpu();
-    AssertReturn(pCpu && pCpu->hMemObj != NIL_RTR0MEMOBJ, VERR_HM_IPE_2);
-
-    void           *pvCpuPage     = RTR0MemObjAddress(pCpu->hMemObj);
-    RTHCPHYS        HCPhysCpuPage = RTR0MemObjGetPagePhysAddr(pCpu->hMemObj, 0);
-    return VMXR0EnableCpu(pCpu, pVM, pvCpuPage, HCPhysCpuPage, false);
+    if (g_HvmR0.vmx.fUsingSUPR0EnableVTx)
+        SUPR0ResumeVTxOnCpu(fVTxDisabled);
+    else
+    {
+        Assert(g_HvmR0.fEnabled);
+        Assert(g_HvmR0.fGlobalInit);
+
+        PHMGLOBLCPUINFO pCpu = HWACCMR0GetCurrentCpu();
+        AssertReturnVoid(pCpu && pCpu->hMemObj != NIL_RTR0MEMOBJ);
+
+        void           *pvCpuPage     = RTR0MemObjAddress(pCpu->hMemObj);
+        RTHCPHYS        HCPhysCpuPage = RTR0MemObjGetPagePhysAddr(pCpu->hMemObj, 0);
+        VMXR0EnableCpu(pCpu, pVM, pvCpuPage, HCPhysCpuPage, false);
+    }
 }
 
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 43378)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 43379)
@@ -137,8 +137,14 @@
          */
 
-        if (ASMGetCR4() & X86_CR4_VMXE)
-            return VERR_VMX_IN_VMX_ROOT_MODE;
-
-        ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);    /* Make sure the VMX instructions don't cause #UD faults. */
+        /** @todo r=bird: Why is this code different than the probing code earlier
+         *        on? It just sets VMXE if needed and doesn't check that it isn't
+         *        set.  Mac OS X host_vmxoff may leave this set and we'll fail here
+         *        and debug-assert in the calling code.  This is what caused the
+         *        "regression" after backing out the SUPR0EnableVTx code hours before
+         *        4.2.0GA (reboot fixed the issue).  I've changed here to do the same
+         *        as the init code. */
+        uint64_t uCr4 = ASMGetCR4();
+        if (!(uCr4 & X86_CR4_VMXE))
+            ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);    /* Make sure the VMX instructions don't cause #UD faults. */
 
         /*
@@ -148,5 +154,5 @@
         if (RT_FAILURE(rc))
         {
-            ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
+            ASMSetCR4(uCr4);
             return VERR_VMX_VMXON_FAILED;
         }
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 43378)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 43379)
@@ -683,5 +683,5 @@
                 /* We might need to disable VT-x if the active switcher turns off paging. */
                 bool fVTxDisabled;
-                int rc = HWACCMR0EnterSwitcher(pVM, &fVTxDisabled);
+                int rc = HWACCMR0EnterSwitcher(pVM, pVM->vmm.s.enmSwitcher, &fVTxDisabled);
                 if (RT_SUCCESS(rc))
                 {
@@ -999,5 +999,5 @@
 
             /* We might need to disable VT-x if the active switcher turns off paging. */
-            rc = HWACCMR0EnterSwitcher(pVM, &fVTxDisabled);
+            rc = HWACCMR0EnterSwitcher(pVM, pVM->vmm.s.enmSwitcher, &fVTxDisabled);
             if (RT_FAILURE(rc))
                 return rc;
