Index: /trunk/include/VBox/hwaccm.h
===================================================================
--- /trunk/include/VBox/hwaccm.h	(revision 17245)
+++ /trunk/include/VBox/hwaccm.h	(revision 17246)
@@ -90,5 +90,7 @@
 VMMR0DECL(int)  HWACCMR0InitVM(PVM pVM);
 VMMR0DECL(int)  HWACCMR0TermVM(PVM pVM);
-VMMR0DECL(int)  HWACCMR0EnableAllCpus(PVM pVM, HWACCMSTATE enmNewHwAccmState);
+VMMR0DECL(int)  HWACCMR0EnableAllCpus(PVM pVM);
+VMMR0DECL(int)  HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled);
+VMMR0DECL(int)  HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled);
 /** @} */
 #endif /* IN_RING0 */
Index: /trunk/include/VBox/vmm.h
===================================================================
--- /trunk/include/VBox/vmm.h	(revision 17245)
+++ /trunk/include/VBox/vmm.h	(revision 17246)
@@ -114,9 +114,10 @@
 } VMMCALLHOST;
 
-RTRCPTR             VMMGetStackRC(PVM pVM);
-VMCPUID             VMMGetCpuId(PVM pVM);
-PVMCPU              VMMGetCpu(PVM pVM);
-VMMDECL(PVMCPU)     VMMGetCpuEx(PVM pVM, RTCPUID idCpu);
-VMMDECL(uint32_t)   VMMGetSvnRev(void);
+RTRCPTR              VMMGetStackRC(PVM pVM);
+VMCPUID              VMMGetCpuId(PVM pVM);
+PVMCPU               VMMGetCpu(PVM pVM);
+VMMDECL(PVMCPU)      VMMGetCpuEx(PVM pVM, RTCPUID idCpu);
+VMMDECL(uint32_t)    VMMGetSvnRev(void);
+VMMDECL(VMMSWITCHER) VMMGetSwitcher(PVM pVM);
 
 /** @def VMMIsHwVirtExtForced
Index: /trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- /trunk/src/VBox/VMM/HWACCM.cpp	(revision 17245)
+++ /trunk/src/VBox/VMM/HWACCM.cpp	(revision 17246)
@@ -227,5 +227,5 @@
         if (!pVM->hwaccm.s.fAllowed)
 # endif
-            return VM_SET_ERROR(pVM, VERR_INVALID_PARAMETER, "64-bit guest support was requested without also enabling VT-x.");
+            return VM_SET_ERROR(pVM, VERR_INVALID_PARAMETER, "64-bit guest support was requested without also enabling HWVirtEx (VT-x/AMD-V).");
     }
 #else
@@ -447,56 +447,14 @@
     }
 
-    /*
-     * Note that we have a global setting for VT-x/AMD-V usage. VMX root mode changes the way the CPU operates. Our 64 bits switcher will trap
-     * because it turns off paging, which is not allowed in VMX root mode.
-     *
-     * To simplify matters we'll just force all running VMs to either use raw or VT-x mode. No mixing allowed in the VT-x case.
-     * There's no such problem with AMD-V. (@todo)
-     *
-     */
-    /* If we enabled or disabled hwaccm mode, then it can't be changed until all the VMs are shutdown. */
-    rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_ENABLE, (pVM->hwaccm.s.fAllowed) ? HWACCMSTATE_ENABLED : HWACCMSTATE_DISABLED, NULL);
+    if (!pVM->hwaccm.s.fAllowed)
+        return VINF_SUCCESS;    /* nothing to do */
+
+    /* Enable VT-x or AMD-V on all host CPUs. */
+    rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_ENABLE, 0, NULL);
     if (RT_FAILURE(rc))
     {
         LogRel(("HWACCMR3InitFinalize: SUPCallVMMR0Ex VMMR0_DO_HWACC_ENABLE failed with %Rrc\n", rc));
-        LogRel(("HWACCMR3InitFinalize: disallowed %s of HWACCM\n", pVM->hwaccm.s.fAllowed ? "enabling" : "disabling"));
-
-#ifdef RT_OS_DARWIN
-        /*
-         * This is 100% fatal if we didn't prepare for a HwVirtExt setup because of
-         * missing ring-0 allocations. For VMs that require HwVirtExt it doesn't normally
-         * make sense to try run them in software mode, so fail that too.
-         */
-        if (VMMIsHwVirtExtForced(pVM))
-            VM_SET_ERROR(pVM, rc, "An active VM already uses software virtualization. It is not allowed to "
-                         "simultaneously use VT-x.");
-        else
-            VM_SET_ERROR(pVM, rc, "An active VM already uses Intel VT-x hardware acceleration. It is not "
-                         "allowed to simultaneously use software virtualization.");
         return rc;
-
-#else  /* !RT_OS_DARWIN */
-
-        /* Invert the selection */
-        pVM->hwaccm.s.fAllowed ^= 1;
-        if (pVM->hwaccm.s.fAllowed)
-        {
-            if (pVM->hwaccm.s.vmx.fSupported)
-                VM_SET_ERROR(pVM, rc, "An active VM already uses Intel VT-x hardware acceleration. It is not allowed "
-                                      "to simultaneously use software virtualization.\n");
-            else
-                VM_SET_ERROR(pVM, rc, "An active VM already uses AMD-V hardware acceleration. It is not allowed to "
-                                      "simultaneously use software virtualization.\n");
-        }
-        else
-            VM_SET_ERROR(pVM, rc, "An active VM already uses software virtualization. It is not allowed to simultaneously "
-                                  "use VT-x or AMD-V.\n");
-        return rc;
-#endif /* !RT_OS_DARWIN */
-    }
-
-    if (pVM->hwaccm.s.fAllowed == false)
-        return VINF_SUCCESS;    /* disabled */
-
+    }
     Assert(!pVM->fHWACCMEnabled || VMMIsHwVirtExtForced(pVM));
 
Index: /trunk/src/VBox/VMM/VMMAll/VMMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/VMMAll.cpp	(revision 17245)
+++ /trunk/src/VBox/VMM/VMMAll/VMMAll.cpp	(revision 17246)
@@ -130,2 +130,12 @@
 }
 
+/**
+ * Queries the current switcher
+ *
+ * @returns active switcher
+ * @param   pVM             VM handle.
+ */
+VMMDECL(VMMSWITCHER) VMMGetSwitcher(PVM pVM)
+{
+    return pVM->vmm.s.enmSwitcher;
+}
Index: /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 17245)
+++ /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 17246)
@@ -563,10 +563,9 @@
  * @returns VBox status code.
  * @param   pVM                 The VM to operate on.
- * @param   enmNewHwAccmState   New hwaccm state
- *
- */
-VMMR0DECL(int) HWACCMR0EnableAllCpus(PVM pVM, HWACCMSTATE enmNewHwAccmState)
-{
-    Assert(sizeof(HWACCMR0Globals.enmHwAccmState) == sizeof(uint32_t));
+ *
+ */
+VMMR0DECL(int) HWACCMR0EnableAllCpus(PVM pVM)
+{
+    AssertCompile(sizeof(HWACCMR0Globals.enmHwAccmState) == sizeof(uint32_t));
 
     /* Make sure we don't touch hwaccm after we've disabled hwaccm in preparation of a suspend. */
@@ -574,11 +573,7 @@
         return VERR_HWACCM_SUSPEND_PENDING;
 
-    if (ASMAtomicCmpXchgU32((volatile uint32_t *)&HWACCMR0Globals.enmHwAccmState, enmNewHwAccmState, HWACCMSTATE_UNINITIALIZED))
+    if (ASMAtomicCmpXchgU32((volatile uint32_t *)&HWACCMR0Globals.enmHwAccmState, HWACCMSTATE_ENABLED, HWACCMSTATE_UNINITIALIZED))
     {
         int rc;
-
-        /* Don't setup hwaccm as that might not work (vt-x & 64 bits raw mode) */
-        if (enmNewHwAccmState == HWACCMSTATE_DISABLED)
-            return VINF_SUCCESS;
 
         if (   HWACCMR0Globals.vmx.fSupported
@@ -637,10 +632,5 @@
         return rc;
     }
-
-    if (HWACCMR0Globals.enmHwAccmState == enmNewHwAccmState)
-        return VINF_SUCCESS;
-
-    /* Request to change the mode is not allowed */
-    return VERR_ACCESS_DENIED;
+    return VINF_SUCCESS;
 }
 
@@ -1131,5 +1121,5 @@
     STAM_PROFILE_ADV_START(&pVCpu->hwaccm.s.StatWorldSwitch3264, z);   
     if (pVM->hwaccm.s.vmx.fSupported)
-        rc  = VMXR0Execute64BitsHandler(pVM, pVCpu, pCtx, pVM->hwaccm.s.pfnTest64, 5, &aParam[0]);
+        rc = VMXR0Execute64BitsHandler(pVM, pVCpu, pCtx, pVM->hwaccm.s.pfnTest64, 5, &aParam[0]);
     else
         rc = SVMR0Execute64BitsHandler(pVM, pVCpu, pCtx, pVM->hwaccm.s.pfnTest64, 5, &aParam[0]);
@@ -1173,4 +1163,78 @@
 {
     return &HWACCMR0Globals.aCpuInfo[idCpu];
+}
+
+/**
+ * Disable VT-x if it's active *and* the current switcher turns off paging
+ *
+ * @returns VBox status code.
+ * @param   pVM             VM handle.
+ * @param   pfVTxDisabled   VT-x was disabled or not (out)
+ */
+VMMR0DECL(int) HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled)
+{
+    Assert(!(ASMGetFlags() & X86_EFL_IF));
+
+    *pfVTxDisabled = false;
+
+    if (    HWACCMR0Globals.enmHwAccmState != HWACCMSTATE_ENABLED
+        ||  !HWACCMR0Globals.vmx.fSupported /* no such issues with AMD-V */)
+        return VINF_SUCCESS;    /* nothing to do */
+
+    switch(VMMGetSwitcher(pVM))
+    {
+    case VMMSWITCHER_32_TO_32:
+    case VMMSWITCHER_PAE_TO_PAE:
+        return VINF_SUCCESS;    /* safe switchers as they don't turn off paging */
+
+    case VMMSWITCHER_32_TO_PAE: 
+    case VMMSWITCHER_PAE_TO_32: /* is this one actually used?? */
+    case VMMSWITCHER_AMD64_TO_32:
+    case VMMSWITCHER_AMD64_TO_PAE:
+        break;                  /* unsafe switchers */
+
+    default:
+        AssertFailed();
+        return VERR_INTERNAL_ERROR;
+    }
+
+    PHWACCM_CPUINFO pCpu = HWACCMR0GetCurrentCpu();
+    void           *pvPageCpu;
+    RTHCPHYS        pPageCpuPhys;
+
+    AssertReturn(pCpu && pCpu->pMemObj, VERR_INTERNAL_ERROR);
+    pvPageCpu    = RTR0MemObjAddress(pCpu->pMemObj);
+    pPageCpuPhys = RTR0MemObjGetPagePhysAddr(pCpu->pMemObj, 0);
+
+    *pfVTxDisabled = true;
+    return VMXR0DisableCpu(pCpu, pvPageCpu, pPageCpuPhys);
+}
+
+/**
+ * Reeable VT-x if was active *and* the current switcher turned off paging
+ *
+ * @returns VBox status code.
+ * @param   pVM          VM handle.
+ * @param   fVTxDisabled VT-x was disabled or not
+ */
+VMMR0DECL(int) HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled)
+{
+    Assert(!(ASMGetFlags() & X86_EFL_IF));
+
+    if (!fVTxDisabled)
+        return VINF_SUCCESS;    /* nothing to do */
+
+    Assert(   HWACCMR0Globals.enmHwAccmState == HWACCMSTATE_ENABLED
+           && HWACCMR0Globals.vmx.fSupported);
+
+    PHWACCM_CPUINFO pCpu = HWACCMR0GetCurrentCpu();
+    void           *pvPageCpu;
+    RTHCPHYS        pPageCpuPhys;
+
+    AssertReturn(pCpu && pCpu->pMemObj, VERR_INTERNAL_ERROR);
+    pvPageCpu    = RTR0MemObjAddress(pCpu->pMemObj);
+    pPageCpuPhys = RTR0MemObjGetPagePhysAddr(pCpu->pMemObj, 0);
+
+    return VMXR0EnableCpu(pCpu, pVM, pvPageCpu, pPageCpuPhys);
 }
 
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 17245)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 17246)
@@ -501,14 +501,10 @@
 VMMR0DECL(int) VMMR0EntryInt(PVM pVM, VMMR0OPERATION enmOperation, void *pvArg)
 {
-    switch (enmOperation)
-    {
-        default:
-            /*
-             * We're returning VERR_NOT_SUPPORT here so we've got something else
-             * than -1 which the interrupt gate glue code might return.
-             */
-            Log(("operation %#x is not supported\n", enmOperation));
-            return VERR_NOT_SUPPORTED;
-    }
+    /*
+     * We're returning VERR_NOT_SUPPORT here so we've got something else
+     * than -1 which the interrupt gate glue code might return.
+     */
+    Log(("operation %#x is not supported\n", enmOperation));
+    return VERR_NOT_SUPPORTED;
 }
 
@@ -543,17 +539,28 @@
             {
                 RTCCUINTREG uFlags = ASMIntDisableFlags();
-
-#ifdef VBOX_STRICT
+                int rc;
+                bool fVTxDisabled;
+
                 if (RT_UNLIKELY(!PGMGetHyperCR3(pVM)))
                 {
-                    pVM->vmm.s.iLastGZRc = VERR_ACCESS_DENIED;
+                    pVM->vmm.s.iLastGZRc = VERR_PGM_NO_CR3_SHADOW_ROOT;
                     return;
                 }
-#endif
+
+                /* We might need to disable VT-x if the active switcher turns off paging. */
+                rc = HWACCMR0EnterSwitcher(pVM, &fVTxDisabled);
+                if (RT_FAILURE(rc))
+                {
+                    pVM->vmm.s.iLastGZRc = rc;
+                    return;
+                }
 
                 TMNotifyStartOfExecution(pVM);
-                int rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
+                rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
                 pVM->vmm.s.iLastGZRc = rc;
                 TMNotifyEndOfExecution(pVM);
+
+                /* Re-enable VT-x if previously turned off. */
+                HWACCMR0LeaveSwitcher(pVM, fVTxDisabled);
 
                 if (    rc == VINF_EM_RAW_INTERRUPT
@@ -753,5 +760,5 @@
          */
         case VMMR0_DO_HWACC_ENABLE:
-            return HWACCMR0EnableAllCpus(pVM, (HWACCMSTATE)u64Arg);
+            return HWACCMR0EnableAllCpus(pVM);
 
         /*
@@ -771,4 +778,7 @@
         case VMMR0_DO_CALL_HYPERVISOR:
         {
+            int rc;
+            bool fVTxDisabled;
+
             /* Safety precaution as HWACCM can disable the switcher. */
             Assert(!pVM->vmm.s.fSwitcherDisabled);
@@ -776,11 +786,19 @@
                 return VERR_NOT_SUPPORTED;
 
-#ifdef VBOX_STRICT
             if (RT_UNLIKELY(!PGMGetHyperCR3(pVM)))
-                return VERR_NOT_SUPPORTED;
-#endif
+                return VERR_PGM_NO_CR3_SHADOW_ROOT;
 
             RTCCUINTREG fFlags = ASMIntDisableFlags();
-            int rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
+
+            /* We might need to disable VT-x if the active switcher turns off paging. */
+            rc = HWACCMR0EnterSwitcher(pVM, &fVTxDisabled);
+            if (RT_FAILURE(rc))
+                return rc;
+
+            rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
+
+            /* Re-enable VT-x if previously turned off. */
+            HWACCMR0LeaveSwitcher(pVM, fVTxDisabled);
+
             /** @todo dispatch interrupts? */
             ASMSetFlags(fFlags);
