Index: /trunk/include/VBox/hwaccm.h
===================================================================
--- /trunk/include/VBox/hwaccm.h	(revision 7470)
+++ /trunk/include/VBox/hwaccm.h	(revision 7471)
@@ -30,4 +30,5 @@
 #include <VBox/types.h>
 #include <VBox/pgm.h>
+#include <iprt/mp.h>
 
 
@@ -36,4 +37,18 @@
  */
 
+/**
+ * HWACCM state
+ */
+typedef enum HWACCMSTATE
+{
+    /* Not yet set */
+    HWACCMSTATE_UNINITIALIZED = 0,
+    /* Enabled */
+    HWACCMSTATE_ENABLED,
+    /* Disabled */
+    HWACCMSTATE_DISABLED,
+    /** The usual 32-bit hack. */
+    HWACCMSTATE_32BIT_HACK = 0x7fffffff
+} HWACCMSTATE;
 
 __BEGIN_DECLS
@@ -54,5 +69,19 @@
 
 /**
- * Does Ring-0 HWACCM initialization.
+ * Does global Ring-0 HWACCM initialization.
+ *
+ * @returns VBox status code.
+ */
+HWACCMR0DECL(int) HWACCMR0Init();
+
+/**
+ * Does global Ring-0 HWACCM termination.
+ *
+ * @returns VBox status code.
+ */
+HWACCMR0DECL(int) HWACCMR0Term();
+
+/**
+ * Does Ring-0 per VM HWACCM initialization.
  *
  * This is mainly to check that the Host CPU mode is compatible
@@ -62,5 +91,15 @@
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) HWACCMR0Init(PVM pVM);
+HWACCMR0DECL(int) HWACCMR0InitVM(PVM pVM);
+
+/**
+ * Sets up HWACCM on all cpus.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 The VM to operate on.
+ * @param   enmNewHwAccmState   New hwaccm state
+ *
+ */
+HWACCMR0DECL(int) HWACCMR0EnableAllCpus(PVM pVM, HWACCMSTATE enmNewHwAccmState);
 
 /** @} */
@@ -91,4 +130,12 @@
 
 /**
+ * Initialize VT-x or AMD-V
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+HWACCMR3DECL(int) HWACCMR3InitFinalizeR0(PVM pVM);
+
+/**
  * Applies relocations to data and code managed by this
  * component. This function will be called at init and
@@ -165,10 +212,10 @@
 
 /**
- * Does Ring-0 VMX initialization.
- *
- * @returns VBox status code.
- * @param   pVM         The VM to operate on.
- */
-HWACCMR0DECL(int) HWACCMR0SetupVMX(PVM pVM);
+ * Sets up a VT-x or AMD-V session
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM to operate on.
+ */
+HWACCMR0DECL(int) HWACCMR0SetupVM(PVM pVM);
 
 
@@ -182,19 +229,19 @@
 
 /**
- * Enable VMX or SVN
- *
- * @returns VBox status code.
- * @param   pVM         The VM to operate on.
- */
-HWACCMR0DECL(int) HWACCMR0Enable(PVM pVM);
-
-
-/**
- * Disable VMX or SVN
- *
- * @returns VBox status code.
- * @param   pVM         The VM to operate on.
- */
-HWACCMR0DECL(int) HWACCMR0Disable(PVM pVM);
+ * Enters the VT-x or AMD-V session
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM to operate on.
+ */
+HWACCMR0DECL(int) HWACCMR0Enter(PVM pVM);
+
+
+/**
+ * Leaves the VT-x or AMD-V session
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM to operate on.
+ */
+HWACCMR0DECL(int) HWACCMR0Leave(PVM pVM);
 
 
Index: /trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- /trunk/src/VBox/VMM/HWACCM.cpp	(revision 7470)
+++ /trunk/src/VBox/VMM/HWACCM.cpp	(revision 7471)
@@ -91,14 +91,4 @@
         return rc;
 
-    /** @todo Make sure both pages are either not accessible or readonly! */
-    /* Allocate one page for VMXON. */
-    pVM->hwaccm.s.vmx.pVMXON = SUPContAlloc(1, &pVM->hwaccm.s.vmx.pVMXONPhys);
-    if (pVM->hwaccm.s.vmx.pVMXON == 0)
-    {
-        AssertMsgFailed(("SUPContAlloc failed!!\n"));
-        return VERR_NO_MEMORY;
-    }
-    memset(pVM->hwaccm.s.vmx.pVMXON, 0, PAGE_SIZE);
-
     /* Allocate one page for the VM control structure (VMCS). */
     pVM->hwaccm.s.vmx.pVMCS = SUPContAlloc(1, &pVM->hwaccm.s.vmx.pVMCSPhys);
@@ -121,6 +111,4 @@
 
     /* Reuse those three pages for AMD SVM. (one is active; never both) */
-    pVM->hwaccm.s.svm.pHState       = pVM->hwaccm.s.vmx.pVMXON;
-    pVM->hwaccm.s.svm.pHStatePhys   = pVM->hwaccm.s.vmx.pVMXONPhys;
     pVM->hwaccm.s.svm.pVMCB         = pVM->hwaccm.s.vmx.pVMCS;
     pVM->hwaccm.s.svm.pVMCBPhys     = pVM->hwaccm.s.vmx.pVMCSPhys;
@@ -262,18 +250,36 @@
 
 /**
- * Applies relocations to data and code managed by this
- * component. This function will be called at init and
- * whenever the VMM need to relocate it self inside the GC.
- *
- * @param   pVM     The VM.
- */
-HWACCMR3DECL(void) HWACCMR3Relocate(PVM pVM)
-{
-#ifdef LOG_ENABLED
-    Log(("HWACCMR3Relocate to %VGv\n", MMHyperGetArea(pVM, 0)));
-#endif
+ * Initialize VT-x or AMD-V.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+HWACCMR3DECL(int) HWACCMR3InitFinalizeR0(PVM pVM)
+{
+    int rc;
+
+    /*
+     * 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 hwaccm mode. No mixing allowed.
+     *
+     */
+
+    /* 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 (VBOX_FAILURE(rc))
+    {
+        LogRel(("HWACCMR3InitFinalize: SUPCallVMMR0Ex VMMR0_DO_HWACC_ENABLE failed with %Vrc\n", rc));
+        LogRel(("HWACCMR3InitFinalize: disallowed %s of HWACCM\n", pVM->hwaccm.s.fAllowed ? "enabling" : "disabling"));
+        /* Invert the selection */
+        pVM->hwaccm.s.fAllowed ^= 1;
+        LogRel(("HWACCMR3InitFinalize: new HWACCM status = %s\n", pVM->hwaccm.s.fAllowed ? "enabled" : "disabled"));
+    }
 
     if (pVM->hwaccm.s.fAllowed == false)
-        return ;
+        return VINF_SUCCESS;    /* disabled */
+
+    Assert(!pVM->fHWACCMEnabled);
 
     if (pVM->hwaccm.s.vmx.fSupported)
@@ -424,5 +430,5 @@
             memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap));
 
-            int rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
+            rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
             AssertRC(rc);
             if (rc == VINF_SUCCESS)
@@ -458,5 +464,5 @@
             pVM->hwaccm.s.fInitialized = true;
 
-            int rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
+            rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
             AssertRC(rc);
             if (rc == VINF_SUCCESS)
@@ -480,5 +486,18 @@
         LogRel(("HWACCM: VMX MSR_IA32_FEATURE_CONTROL=%VX64\n", pVM->hwaccm.s.vmx.msr.feature_ctrl));
     }
-
+    return VINF_SUCCESS;
+}
+
+/**
+ * Applies relocations to data and code managed by this
+ * component. This function will be called at init and
+ * whenever the VMM need to relocate it self inside the GC.
+ *
+ * @param   pVM     The VM.
+ */
+HWACCMR3DECL(void) HWACCMR3Relocate(PVM pVM)
+{
+    Log(("HWACCMR3Relocate to %VGv\n", MMHyperGetArea(pVM, 0)));
+    return;
 }
 
@@ -526,9 +545,4 @@
     }
 
-    if (pVM->hwaccm.s.vmx.pVMXON)
-    {
-        SUPContFree(pVM->hwaccm.s.vmx.pVMXON, 1);
-        pVM->hwaccm.s.vmx.pVMXON = 0;
-    }
     if (pVM->hwaccm.s.vmx.pVMCS)
     {
Index: /trunk/src/VBox/VMM/HWACCMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/HWACCMInternal.h	(revision 7470)
+++ /trunk/src/VBox/VMM/HWACCMInternal.h	(revision 7471)
@@ -154,9 +154,4 @@
         void                       *pVMCS;
 
-        /** Physical address of the VMXON page. */
-        RTHCPHYS                    pVMXONPhys;
-        /** Virtual address of the VMXON page. */
-        void                       *pVMXON;
-
         /** Physical address of the TSS page used for real mode emulation. */
         RTHCPHYS                    pRealModeTSSPhys;
@@ -165,5 +160,5 @@
 
         /** Host CR4 value (set by ring-0 VMX init) */
-        uint32_t                    hostCR4;
+        uint64_t                    hostCR4;
 
         /** Current VMX_VMCS_CTRL_PROC_EXEC_CONTROLS. */
@@ -216,9 +211,4 @@
         /** Virtual address of the host VM control block (VMCB). */
         void                       *pVMCBHost;
-
-        /** Physical address of the Host State page. */
-        RTHCPHYS                    pHStatePhys;
-        /** Virtual address of the Host State page. */
-        void                       *pHState;
 
         /** Physical address of the IO bitmap (12kb). */
Index: /trunk/src/VBox/VMM/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VM.cpp	(revision 7470)
+++ /trunk/src/VBox/VMM/VM.cpp	(revision 7471)
@@ -694,4 +694,9 @@
     if (VBOX_SUCCESS(rc))
         rc = vmR3InitDoCompleted(pVM, VMINITCOMPLETED_RING0);
+
+    /** todo: move this to the VMINITCOMPLETED_RING0 notification handler once implemented */
+    if (VBOX_SUCCESS(rc))
+        rc = HWACCMR3InitFinalizeR0(pVM);
+
     LogFlow(("vmR3InitRing0: returns %Vrc\n", rc));
     return rc;
Index: /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 7470)
+++ /trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 7471)
@@ -36,30 +36,110 @@
 #include <iprt/assert.h>
 #include <iprt/asm.h>
+#include <iprt/string.h>
+#include <iprt/memobj.h>
+#include <iprt/cpuset.h>
 #include "HWVMXR0.h"
 #include "HWSVMR0.h"
 
-/**
- * Does Ring-0 HWACCM initialization.
- *
- * This is mainly to check that the Host CPU mode is compatible
- * with VMX.
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static DECLCALLBACK(void) HWACCMR0EnableCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2);
+static DECLCALLBACK(void) HWACCMR0DisableCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2);
+
+/*******************************************************************************
+*   Local Variables                                                            *
+*******************************************************************************/
+static struct
+{
+    struct
+    {
+        RTR0MEMOBJ  pMemObj;
+        bool        fVMXConfigured;
+        bool        fSVMConfigured;
+    } aCpuInfo[RTCPUSET_MAX_CPUS];
+
+    struct
+    {
+        /** Set by the ring-0 driver to indicate VMX is supported by the CPU. */
+        bool                        fSupported;
+
+        /** Host CR4 value (set by ring-0 VMX init) */
+        uint64_t                    hostCR4;
+
+        /** VMX MSR values */
+        struct
+        {
+            uint64_t                feature_ctrl;
+            uint64_t                vmx_basic_info;
+            uint64_t                vmx_pin_ctls;
+            uint64_t                vmx_proc_ctls;
+            uint64_t                vmx_exit;
+            uint64_t                vmx_entry;
+            uint64_t                vmx_misc;
+            uint64_t                vmx_cr0_fixed0;
+            uint64_t                vmx_cr0_fixed1;
+            uint64_t                vmx_cr4_fixed0;
+            uint64_t                vmx_cr4_fixed1;
+            uint64_t                vmx_vmcs_enum;
+        } msr;
+        /* Last instruction error */
+        uint32_t                    ulLastInstrError;
+    } vmx;
+    struct
+    {
+        /** Set by the ring-0 driver to indicate SVM is supported by the CPU. */
+        bool                        fSupported;
+
+        /** SVM revision. */
+        uint32_t                    u32Rev;
+
+        /** Maximum ASID allowed. */
+        uint32_t                    u32MaxASID;
+    } svm;
+    /** Saved error from detection */
+    int32_t         lLastError;
+
+    struct
+    {
+        uint32_t                    u32AMDFeatureECX;
+        uint32_t                    u32AMDFeatureEDX;
+    } cpuid;
+
+    HWACCMSTATE     enmHwAccmState;
+} HWACCMR0Globals;
+
+
+
+/**
+ * Does global Ring-0 HWACCM initialization.
  *
  * @returns VBox status code.
- * @param   pVM         The VM to operate on.
- */
-HWACCMR0DECL(int) HWACCMR0Init(PVM pVM)
-{
-    LogComFlow(("HWACCMR0Init: %p\n", pVM));
-
-    pVM->hwaccm.s.vmx.fSupported = false;;
-    pVM->hwaccm.s.svm.fSupported = false;;
+ */
+HWACCMR0DECL(int) HWACCMR0Init()
+{
+    int        rc;
+    RTR0MEMOBJ pScatchMemObj;
+    void      *pvScatchPage;
+    RTHCPHYS   pScatchPagePhys;
+
+    memset(&HWACCMR0Globals, 0, sizeof(HWACCMR0Globals));
+    HWACCMR0Globals.enmHwAccmState = HWACCMSTATE_UNINITIALIZED;
+
+    rc = RTR0MemObjAllocCont(&pScatchMemObj, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    pvScatchPage    = RTR0MemObjAddress(pScatchMemObj);
+    pScatchPagePhys = RTR0MemObjGetPagePhysAddr(pScatchMemObj, 0);
+    memset(pvScatchPage, 0, PAGE_SIZE);
+
+    /* Assume success */
+    rc = VINF_SUCCESS;
 
 #ifndef VBOX_WITH_HYBIRD_32BIT_KERNEL /* paranoia */
 
-    pVM->hwaccm.s.fHWACCMR0Init = true;
-    pVM->hwaccm.s.lLastError    = VINF_SUCCESS;
-
     /*
-     * Check for VMX capabilities
+     * Check for VT-x and AMD-V capabilities
      */
     if (ASMHasCpuId())
@@ -70,8 +150,11 @@
         uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX;
 
+        /* Make sure we don't get rescheduled to another cpu during this probe. */
+        RTCCUINTREG fFlags = ASMIntDisableFlags();
+
         ASMCpuId(0, &u32Dummy, &u32VendorEBX, &u32VendorECX, &u32VendorEDX);
         ASMCpuId(1, &u32Dummy, &u32Dummy, &u32FeaturesECX, &u32FeaturesEDX);
         /* Query AMD features. */
-        ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &pVM->hwaccm.s.cpuid.u32AMDFeatureECX, &pVM->hwaccm.s.cpuid.u32AMDFeatureEDX);
+        ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &HWACCMR0Globals.cpuid.u32AMDFeatureECX, &HWACCMR0Globals.cpuid.u32AMDFeatureEDX);
 
         if (    u32VendorEBX == X86_CPUID_VENDOR_INTEL_EBX
@@ -89,5 +172,5 @@
                )
             {
-                pVM->hwaccm.s.vmx.msr.feature_ctrl    = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
+                HWACCMR0Globals.vmx.msr.feature_ctrl    = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
                 /*
                  * Both the LOCK and VMXON bit must be set; otherwise VMXON will generate a #GP.
@@ -95,69 +178,66 @@
                  */
                 /** @todo need to check this for each cpu/core in the system!!!) */
-                if (!(pVM->hwaccm.s.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK)))
+                if (!(HWACCMR0Globals.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK)))
                 {
                     /* MSR is not yet locked; we can change it ourselves here */
-                    pVM->hwaccm.s.vmx.msr.feature_ctrl |= (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK);
-                    ASMWrMsr(MSR_IA32_FEATURE_CONTROL, pVM->hwaccm.s.vmx.msr.feature_ctrl);
+                    HWACCMR0Globals.vmx.msr.feature_ctrl |= (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK);
+                    ASMWrMsr(MSR_IA32_FEATURE_CONTROL, HWACCMR0Globals.vmx.msr.feature_ctrl);
                 }
 
-                if (   (pVM->hwaccm.s.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
+                if (   (HWACCMR0Globals.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
                                                           == (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
                 {
-                    pVM->hwaccm.s.vmx.fSupported          = true;
-                    pVM->hwaccm.s.vmx.msr.vmx_basic_info  = ASMRdMsr(MSR_IA32_VMX_BASIC_INFO);
-                    pVM->hwaccm.s.vmx.msr.vmx_pin_ctls    = ASMRdMsr(MSR_IA32_VMX_PINBASED_CTLS);
-                    pVM->hwaccm.s.vmx.msr.vmx_proc_ctls   = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS);
-                    pVM->hwaccm.s.vmx.msr.vmx_exit        = ASMRdMsr(MSR_IA32_VMX_EXIT_CTLS);
-                    pVM->hwaccm.s.vmx.msr.vmx_entry       = ASMRdMsr(MSR_IA32_VMX_ENTRY_CTLS);
-                    pVM->hwaccm.s.vmx.msr.vmx_misc        = ASMRdMsr(MSR_IA32_VMX_MISC);
-                    pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0  = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED0);
-                    pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1  = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED1);
-                    pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed0  = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED0);
-                    pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed1  = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED1);
-                    pVM->hwaccm.s.vmx.msr.vmx_vmcs_enum   = ASMRdMsr(MSR_IA32_VMX_VMCS_ENUM);
+                    HWACCMR0Globals.vmx.fSupported          = true;
+                    HWACCMR0Globals.vmx.msr.vmx_basic_info  = ASMRdMsr(MSR_IA32_VMX_BASIC_INFO);
+                    HWACCMR0Globals.vmx.msr.vmx_pin_ctls    = ASMRdMsr(MSR_IA32_VMX_PINBASED_CTLS);
+                    HWACCMR0Globals.vmx.msr.vmx_proc_ctls   = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS);
+                    HWACCMR0Globals.vmx.msr.vmx_exit        = ASMRdMsr(MSR_IA32_VMX_EXIT_CTLS);
+                    HWACCMR0Globals.vmx.msr.vmx_entry       = ASMRdMsr(MSR_IA32_VMX_ENTRY_CTLS);
+                    HWACCMR0Globals.vmx.msr.vmx_misc        = ASMRdMsr(MSR_IA32_VMX_MISC);
+                    HWACCMR0Globals.vmx.msr.vmx_cr0_fixed0  = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED0);
+                    HWACCMR0Globals.vmx.msr.vmx_cr0_fixed1  = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED1);
+                    HWACCMR0Globals.vmx.msr.vmx_cr4_fixed0  = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED0);
+                    HWACCMR0Globals.vmx.msr.vmx_cr4_fixed1  = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED1);
+                    HWACCMR0Globals.vmx.msr.vmx_vmcs_enum   = ASMRdMsr(MSR_IA32_VMX_VMCS_ENUM);
 
                     /*
                      * Check CR4.VMXE
                      */
-                    pVM->hwaccm.s.vmx.hostCR4 = ASMGetCR4();
-                    if (!(pVM->hwaccm.s.vmx.hostCR4 & X86_CR4_VMXE))
+                    HWACCMR0Globals.vmx.hostCR4 = ASMGetCR4();
+                    if (!(HWACCMR0Globals.vmx.hostCR4 & X86_CR4_VMXE))
                     {
                         /* In theory this bit could be cleared behind our back. Which would cause #UD faults when we
                          * try to execute the VMX instructions...
                          */
-                        ASMSetCR4(pVM->hwaccm.s.vmx.hostCR4 | X86_CR4_VMXE);
+                        ASMSetCR4(HWACCMR0Globals.vmx.hostCR4 | X86_CR4_VMXE);
                     }
 
-                    if (    pVM->hwaccm.s.vmx.pVMXONPhys 
-                        &&  pVM->hwaccm.s.vmx.pVMXON)
+                    /* Set revision dword at the beginning of the structure. */
+                    *(uint32_t *)pvScatchPage = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(HWACCMR0Globals.vmx.msr.vmx_basic_info);
+
+#if HC_ARCH_BITS == 64
+                    /* Enter VMX Root Mode */
+                    rc = VMXEnable(pScatchPagePhys);
+                    if (VBOX_FAILURE(rc))
                     {
-                        /* Set revision dword at the beginning of the structure. */
-                        *(uint32_t *)pVM->hwaccm.s.vmx.pVMXON = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
-
-#if HC_ARCH_BITS == 64
-                        /* Enter VMX Root Mode */
-                        int rc = VMXEnable(pVM->hwaccm.s.vmx.pVMXONPhys);
-                        if (VBOX_FAILURE(rc))
-                        {
-                            /* KVM leaves the CPU in VMX root mode. Not only is this not allowed, it will crash the host when we enter raw mode, because
-                             * (a) clearing X86_CR4_VMXE in CR4 causes a #GP    (we no longer modify this bit)
-                             * (b) turning off paging causes a #GP              (unavoidable when switching from long to 32 bits mode)
-                             *
-                             * They should fix their code, but until they do we simply refuse to run.
-                             */
-                            return VERR_VMX_IN_VMX_ROOT_MODE;
-                        }
+                        /* KVM leaves the CPU in VMX root mode. Not only is this not allowed, it will crash the host when we enter raw mode, because
+                         * (a) clearing X86_CR4_VMXE in CR4 causes a #GP    (we no longer modify this bit)
+                         * (b) turning off paging causes a #GP              (unavoidable when switching from long to 32 bits mode)
+                         *
+                         * They should fix their code, but until they do we simply refuse to run.
+                         */
+                        rc = VERR_VMX_IN_VMX_ROOT_MODE;
+                    }
+                    else
                         VMXDisable();
 #endif
-                    }
                     /* Restore CR4 again; don't leave the X86_CR4_VMXE flag set if it wasn't so before (some software could incorrectly think it's in VMX mode) */
-                    ASMSetCR4(pVM->hwaccm.s.vmx.hostCR4);
+                    ASMSetCR4(HWACCMR0Globals.vmx.hostCR4);
                 }
                 else
-                    pVM->hwaccm.s.lLastError = VERR_VMX_ILLEGAL_FEATURE_CONTROL_MSR;
+                    HWACCMR0Globals.lLastError = VERR_VMX_ILLEGAL_FEATURE_CONTROL_MSR;
             }
             else
-                pVM->hwaccm.s.lLastError = VERR_VMX_NO_VMX;
+                HWACCMR0Globals.lLastError = VERR_VMX_NO_VMX;
         }
         else
@@ -171,5 +251,5 @@
              * We also assume all SVM-enabled CPUs support fxsave/fxrstor.
              */
-            if (   (pVM->hwaccm.s.cpuid.u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
+            if (   (HWACCMR0Globals.cpuid.u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
                 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
                 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
@@ -193,39 +273,265 @@
                     {
                         /* Query AMD features. */
-                        ASMCpuId(0x8000000A, &pVM->hwaccm.s.svm.u32Rev, &pVM->hwaccm.s.svm.u32MaxASID, &u32Dummy, &u32Dummy);
-
-                        pVM->hwaccm.s.svm.fSupported = true;
+                        ASMCpuId(0x8000000A, &HWACCMR0Globals.svm.u32Rev, &HWACCMR0Globals.svm.u32MaxASID, &u32Dummy, &u32Dummy);
+
+                        HWACCMR0Globals.svm.fSupported = true;
                     }
                     else
                     {
-                        pVM->hwaccm.s.lLastError = VERR_SVM_ILLEGAL_EFER_MSR;
+                        HWACCMR0Globals.lLastError = VERR_SVM_ILLEGAL_EFER_MSR;
                         AssertFailed();
                     }
                 }
                 else
-                    pVM->hwaccm.s.lLastError = VERR_SVM_DISABLED;
+                    HWACCMR0Globals.lLastError = VERR_SVM_DISABLED;
             }
             else
-                pVM->hwaccm.s.lLastError = VERR_SVM_NO_SVM;
+                HWACCMR0Globals.lLastError = VERR_SVM_NO_SVM;
         }
         else
-            pVM->hwaccm.s.lLastError = VERR_HWACCM_UNKNOWN_CPU;
-    }
-    else
-        pVM->hwaccm.s.lLastError = VERR_HWACCM_NO_CPUID;
+            HWACCMR0Globals.lLastError = VERR_HWACCM_UNKNOWN_CPU;
+
+        ASMSetFlags(fFlags);
+    }
+    else
+        HWACCMR0Globals.lLastError = VERR_HWACCM_NO_CPUID;
 
 #endif /* !VBOX_WITH_HYBIRD_32BIT_KERNEL */
 
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Sets up and activates VMX
+    RTR0MemObjFree(pScatchMemObj, false);
+    return rc;
+}
+
+/**
+ * Does global Ring-0 HWACCM termination.
+ *
+ * @returns VBox status code.
+ */
+HWACCMR0DECL(int) HWACCMR0Term()
+{
+    int aRc[RTCPUSET_MAX_CPUS];
+
+    memset(aRc, 0, sizeof(aRc));
+    int rc = RTMpOnAll(HWACCMR0DisableCPU, aRc, NULL);
+    AssertRC(rc);
+
+    /* Free the per-cpu pages used for VT-x and AMD-V */
+    for (unsigned i=0;i<RT_ELEMENTS(HWACCMR0Globals.aCpuInfo);i++)
+    {
+        AssertMsg(VBOX_SUCCESS(aRc[i]), ("HWACCMR0DisableCPU failed for cpu %d with rc=%d\n", i, aRc[i]));
+        if (HWACCMR0Globals.aCpuInfo[i].pMemObj)
+        {
+            RTR0MemObjFree(HWACCMR0Globals.aCpuInfo[i].pMemObj, false);
+            HWACCMR0Globals.aCpuInfo[i].pMemObj = NULL;
+        }
+    }
+    return rc;
+}
+
+/**
+ * Sets up HWACCM on all cpus.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 The VM to operate on.
+ * @param   enmNewHwAccmState   New hwaccm state
+ *
+ */
+HWACCMR0DECL(int) HWACCMR0EnableAllCpus(PVM pVM, HWACCMSTATE enmNewHwAccmState)
+{
+    Assert(sizeof(HWACCMR0Globals.enmHwAccmState) == sizeof(uint32_t));
+    if (ASMAtomicCmpXchgU32((volatile uint32_t *)&HWACCMR0Globals.enmHwAccmState, enmNewHwAccmState, HWACCMSTATE_UNINITIALIZED))
+    {
+        int aRc[RTCPUSET_MAX_CPUS];
+        memset(aRc, 0, sizeof(aRc));
+
+        /* Allocate one page per cpu for the global vt-x and amd-v pages */
+        for (unsigned i=0;i<RT_ELEMENTS(HWACCMR0Globals.aCpuInfo);i++)
+        {
+            Assert(!HWACCMR0Globals.aCpuInfo[i].pMemObj);
+
+            /** @todo this is rather dangerous if cpus can be taken offline; we don't care for now */
+            if (RTMpIsCpuOnline(i))
+            {
+                int rc = RTR0MemObjAllocCont(&HWACCMR0Globals.aCpuInfo[i].pMemObj, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
+                if (RT_FAILURE(rc))
+                    return rc;
+
+                void *pvR0 = RTR0MemObjAddress(HWACCMR0Globals.aCpuInfo[i].pMemObj);
+                memset(pvR0, 0, PAGE_SIZE);
+            }
+        }
+
+        /* First time, so initialize each cpu/core */
+        int rc = RTMpOnAll(HWACCMR0EnableCPU, (void *)pVM, aRc);
+        if (VBOX_SUCCESS(rc))
+        {
+            for (unsigned i=0;i<RT_ELEMENTS(aRc);i++)
+            {
+                if (RTMpIsCpuOnline(i))
+                {
+                    AssertMsg(VBOX_SUCCESS(aRc[i]), ("HWACCMR0EnableCPU failed for cpu %d with rc=%d\n", i, aRc[i]));
+                    if (VBOX_FAILURE(aRc[i]))
+                    {
+                        rc = aRc[i];
+                        break;
+                    }
+                }
+            }
+        }
+        return rc;
+    }
+
+    if (HWACCMR0Globals.enmHwAccmState == enmNewHwAccmState)
+        return VINF_SUCCESS;
+
+    /* Request to change the mode is not allowed */
+    return VERR_ACCESS_DENIED;
+}
+
+/**
+ * Worker function passed to RTMpOnAll, RTMpOnOthers and RTMpOnSpecific that
+ * is to be called on the target cpus.
+ * 
+ * @param   idCpu       The identifier for the CPU the function is called on.
+ * @param   pvUser1     The 1st user argument.
+ * @param   pvUser2     The 2nd user argument.
+ */
+static DECLCALLBACK(void) HWACCMR0EnableCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2)
+{
+    PVM      pVM = (PVM)pvUser1;
+    int     *paRc = (int *)pvUser2;
+    void    *pvPageCpu;
+    RTHCPHYS pPageCpuPhys;
+
+    Assert(pVM);
+    Assert(idCpu < RT_ELEMENTS(HWACCMR0Globals.aCpuInfo));
+
+    /* Should never happen */
+    if (!HWACCMR0Globals.aCpuInfo[idCpu].pMemObj)
+    {
+        AssertFailed();
+        return;
+    }
+
+    pvPageCpu    = RTR0MemObjAddress(HWACCMR0Globals.aCpuInfo[idCpu].pMemObj);
+    pPageCpuPhys = RTR0MemObjGetPagePhysAddr(HWACCMR0Globals.aCpuInfo[idCpu].pMemObj, 0);
+
+    if (pVM->hwaccm.s.vmx.fSupported)
+    {
+        paRc[idCpu] = VMXR0EnableCpu(idCpu, pVM, pvPageCpu, pPageCpuPhys);
+        if (VBOX_SUCCESS(paRc[idCpu]))
+            HWACCMR0Globals.aCpuInfo[idCpu].fVMXConfigured = true;
+    }
+    else
+    {
+        Assert(pVM->hwaccm.s.svm.fSupported);
+        paRc[idCpu] = SVMR0EnableCpu(idCpu, pVM, pvPageCpu, pPageCpuPhys);
+        if (VBOX_SUCCESS(paRc[idCpu]))
+            HWACCMR0Globals.aCpuInfo[idCpu].fSVMConfigured = true;
+    }
+    return;
+}
+
+/**
+ * Worker function passed to RTMpOnAll, RTMpOnOthers and RTMpOnSpecific that
+ * is to be called on the target cpus.
+ * 
+ * @param   idCpu       The identifier for the CPU the function is called on.
+ * @param   pvUser1     The 1st user argument.
+ * @param   pvUser2     The 2nd user argument.
+ */
+static DECLCALLBACK(void) HWACCMR0DisableCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2)
+{
+    void    *pvPageCpu;
+    RTHCPHYS pPageCpuPhys;
+    int     *paRc = (int *)pvUser1;
+
+    Assert(idCpu < RT_ELEMENTS(HWACCMR0Globals.aCpuInfo));
+
+    /* Should never happen */
+    if (!HWACCMR0Globals.aCpuInfo[idCpu].pMemObj)
+    {
+        AssertFailed();
+        return;
+    }
+
+    pvPageCpu    = RTR0MemObjAddress(HWACCMR0Globals.aCpuInfo[idCpu].pMemObj);
+    pPageCpuPhys = RTR0MemObjGetPagePhysAddr(HWACCMR0Globals.aCpuInfo[idCpu].pMemObj, 0);
+
+    if (HWACCMR0Globals.aCpuInfo[idCpu].fVMXConfigured)
+    {
+        paRc[idCpu] = VMXR0DisableCpu(idCpu, pvPageCpu, pPageCpuPhys);
+        AssertRC(paRc[idCpu]);
+        HWACCMR0Globals.aCpuInfo[idCpu].fVMXConfigured = false;
+    }
+    else
+    if (HWACCMR0Globals.aCpuInfo[idCpu].fSVMConfigured)
+    {
+        paRc[idCpu] = SVMR0DisableCpu(idCpu, pvPageCpu, pPageCpuPhys);
+        AssertRC(paRc[idCpu]);
+        HWACCMR0Globals.aCpuInfo[idCpu].fSVMConfigured = false;
+    }
+    return;
+}
+
+
+/**
+ * Does Ring-0 per VM HWACCM initialization.
+ *
+ * This is mainly to check that the Host CPU mode is compatible
+ * with VMX.
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) HWACCMR0SetupVMX(PVM pVM)
+HWACCMR0DECL(int) HWACCMR0InitVM(PVM pVM)
+{
+    LogComFlow(("HWACCMR0Init: %p\n", pVM));
+
+    pVM->hwaccm.s.vmx.fSupported = false;
+    pVM->hwaccm.s.svm.fSupported = false;
+
+    if (HWACCMR0Globals.vmx.fSupported)
+    {
+        pVM->hwaccm.s.vmx.fSupported            = true;
+        pVM->hwaccm.s.vmx.hostCR4               = HWACCMR0Globals.vmx.hostCR4;
+        pVM->hwaccm.s.vmx.msr.feature_ctrl      = HWACCMR0Globals.vmx.msr.feature_ctrl;
+        pVM->hwaccm.s.vmx.msr.vmx_basic_info    = HWACCMR0Globals.vmx.msr.vmx_basic_info;
+        pVM->hwaccm.s.vmx.msr.vmx_pin_ctls      = HWACCMR0Globals.vmx.msr.vmx_pin_ctls;
+        pVM->hwaccm.s.vmx.msr.vmx_proc_ctls     = HWACCMR0Globals.vmx.msr.vmx_proc_ctls;
+        pVM->hwaccm.s.vmx.msr.vmx_exit          = HWACCMR0Globals.vmx.msr.vmx_exit;
+        pVM->hwaccm.s.vmx.msr.vmx_entry         = HWACCMR0Globals.vmx.msr.vmx_entry;
+        pVM->hwaccm.s.vmx.msr.vmx_misc          = HWACCMR0Globals.vmx.msr.vmx_misc;
+        pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0    = HWACCMR0Globals.vmx.msr.vmx_cr0_fixed0;
+        pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1    = HWACCMR0Globals.vmx.msr.vmx_cr0_fixed1;
+        pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed0    = HWACCMR0Globals.vmx.msr.vmx_cr4_fixed0;
+        pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed1    = HWACCMR0Globals.vmx.msr.vmx_cr4_fixed1;
+        pVM->hwaccm.s.vmx.msr.vmx_vmcs_enum     = HWACCMR0Globals.vmx.msr.vmx_vmcs_enum;
+
+    }
+    else
+    if (HWACCMR0Globals.svm.fSupported)
+    {
+        pVM->hwaccm.s.svm.fSupported            = true;
+        pVM->hwaccm.s.svm.u32Rev                = HWACCMR0Globals.svm.u32Rev;
+        pVM->hwaccm.s.svm.u32MaxASID            = HWACCMR0Globals.svm.u32MaxASID;
+    }
+
+    pVM->hwaccm.s.lLastError                = HWACCMR0Globals.lLastError;
+    pVM->hwaccm.s.cpuid.u32AMDFeatureECX    = HWACCMR0Globals.cpuid.u32AMDFeatureECX;
+    pVM->hwaccm.s.cpuid.u32AMDFeatureEDX    = HWACCMR0Globals.cpuid.u32AMDFeatureEDX;
+
+    return VINF_SUCCESS;
+}
+
+
+
+/**
+ * Sets up a VT-x or AMD-V session
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM to operate on.
+ */
+HWACCMR0DECL(int) HWACCMR0SetupVM(PVM pVM)
 {
     int rc = VINF_SUCCESS;
@@ -236,7 +542,7 @@
     /* Setup Intel VMX. */
     if (pVM->hwaccm.s.vmx.fSupported)
-        rc = VMXR0Setup(pVM);
-    else
-        rc = SVMR0Setup(pVM);
+        rc = VMXR0SetupVM(pVM);
+    else
+        rc = SVMR0SetupVM(pVM);
 
     return rc;
@@ -245,10 +551,10 @@
 
 /**
- * Enable VMX or SVN
+ * Enters the VT-x or AMD-V session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) HWACCMR0Enable(PVM pVM)
+HWACCMR0DECL(int) HWACCMR0Enter(PVM pVM)
 {
     CPUMCTX *pCtx;
@@ -267,5 +573,5 @@
     if (pVM->hwaccm.s.vmx.fSupported)
     {
-        rc  = VMXR0Enable(pVM);
+        rc  = VMXR0Enter(pVM);
         AssertRC(rc);
         rc |= VMXR0SaveHostState(pVM);
@@ -279,5 +585,5 @@
     {
         Assert(pVM->hwaccm.s.svm.fSupported);
-        rc  = SVMR0Enable(pVM);
+        rc  = SVMR0Enter(pVM);
         AssertRC(rc);
         rc |= SVMR0LoadGuestState(pVM, pCtx);
@@ -292,10 +598,10 @@
 
 /**
- * Disable VMX or SVN
+ * Leaves the VT-x or AMD-V session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) HWACCMR0Disable(PVM pVM)
+HWACCMR0DECL(int) HWACCMR0Leave(PVM pVM)
 {
     CPUMCTX *pCtx;
@@ -323,10 +629,10 @@
     if (pVM->hwaccm.s.vmx.fSupported)
     {
-        return VMXR0Disable(pVM);
+        return VMXR0Leave(pVM);
     }
     else
     {
         Assert(pVM->hwaccm.s.svm.fSupported);
-        return SVMR0Disable(pVM);
+        return SVMR0Leave(pVM);
     }
 }
Index: /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 7470)
+++ /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 7471)
@@ -43,10 +43,59 @@
 
 /**
- * Sets up and activates SVM
+ * Sets up and activates AMD-V on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pVM             The VM to operate on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) SVMR0EnableCpu(RTCPUID idCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
+{
+    AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
+    AssertReturn(pVM, VERR_INVALID_PARAMETER);
+    AssertReturn(pvPageCpu, VERR_INVALID_PARAMETER);
+
+    /* We must turn on AMD-V and setup the host state physical address, as those MSRs are per-cpu/core. */
+
+    /* Turn on AMD-V in the EFER MSR. */
+    uint64_t val = ASMRdMsr(MSR_K6_EFER);
+    if (!(val & MSR_K6_EFER_SVME))
+        ASMWrMsr(MSR_K6_EFER, val | MSR_K6_EFER_SVME);
+
+    /* Write the physical page address where the CPU will store the host state while executing the VM. */
+    ASMWrMsr(MSR_K8_VM_HSAVE_PA, pPageCpuPhys);
+    return VINF_SUCCESS;
+}
+
+/**
+ * Deactivates AMD-V on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) SVMR0DisableCpu(RTCPUID idCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
+{
+    AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
+    AssertReturn(pvPageCpu, VERR_INVALID_PARAMETER);
+
+    /* Turn off AMD-V in the EFER MSR. */
+    uint64_t val = ASMRdMsr(MSR_K6_EFER);
+    ASMWrMsr(MSR_K6_EFER, val & ~MSR_K6_EFER_SVME);
+
+    /* Invalidate host state physical address. */
+    ASMWrMsr(MSR_K8_VM_HSAVE_PA, 0);
+    return VINF_SUCCESS;
+}
+
+/**
+ * Sets up SVM for the specified VM
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) SVMR0Setup(PVM pVM)
+HWACCMR0DECL(int) SVMR0SetupVM(PVM pVM)
 {
     int         rc = VINF_SUCCESS;
@@ -1413,10 +1462,10 @@
 
 /**
- * Enable SVM
+ * Enters the AMD-V session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) SVMR0Enable(PVM pVM)
+HWACCMR0DECL(int) SVMR0Enter(PVM pVM)
 {
     uint64_t val;
@@ -1424,14 +1473,4 @@
     Assert(pVM->hwaccm.s.svm.fSupported);
 
-    /* We must turn on SVM and setup the host state physical address, as those MSRs are per-cpu/core. */
-
-    /* Turn on SVM in the EFER MSR. */
-    val = ASMRdMsr(MSR_K6_EFER);
-    if (!(val & MSR_K6_EFER_SVME))
-        ASMWrMsr(MSR_K6_EFER, val | MSR_K6_EFER_SVME);
-
-    /* Write the physical page address where the CPU will store the host state while executing the VM. */
-    ASMWrMsr(MSR_K8_VM_HSAVE_PA, pVM->hwaccm.s.svm.pHStatePhys);
-
     /* Force a TLB flush on VM entry. */
     pVM->hwaccm.s.svm.fResumeVM = false;
@@ -1445,20 +1484,11 @@
 
 /**
- * Disable SVM
+ * Leaves the AMD-V session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) SVMR0Disable(PVM pVM)
+HWACCMR0DECL(int) SVMR0Leave(PVM pVM)
 {
-    /** @todo hopefully this is not very expensive. */
-
-    /* Turn off SVM in the EFER MSR. */
-    uint64_t val = ASMRdMsr(MSR_K6_EFER);
-    ASMWrMsr(MSR_K6_EFER, val & ~MSR_K6_EFER_SVME);
-
-    /* Invalidate host state physical address. */
-    ASMWrMsr(MSR_K8_VM_HSAVE_PA, 0);
-
     Assert(pVM->hwaccm.s.svm.fSupported);
     return VINF_SUCCESS;
Index: /trunk/src/VBox/VMM/VMMR0/HWSVMR0.h
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWSVMR0.h	(revision 7470)
+++ /trunk/src/VBox/VMM/VMMR0/HWSVMR0.h	(revision 7471)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /** @file
- * HWACCM SVM - Internal header file.
+ * HWACCM AMD-V - Internal header file.
  */
 
@@ -39,30 +39,51 @@
 
 /**
- * Enable SVM
+ * Enters the AMD-V session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) SVMR0Enable(PVM pVM);
+HWACCMR0DECL(int) SVMR0Enter(PVM pVM);
 
 /**
- * Disable SVM
+ * Leaves the AMD-V session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) SVMR0Disable(PVM pVM);
+HWACCMR0DECL(int) SVMR0Leave(PVM pVM);
 
 /**
- * Sets up and activates SVM
+ * Sets up and activates AMD-V on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pVM             The VM to operate on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) SVMR0EnableCpu(RTCPUID idCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
+
+/**
+ * Deactivates AMD-V on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) SVMR0DisableCpu(RTCPUID idCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
+
+/**
+ * Sets up AMD-V for the specified VM
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) SVMR0Setup(PVM pVM);
+HWACCMR0DECL(int) SVMR0SetupVM(PVM pVM);
 
 
 /**
- * Runs guest code in a SVM VM.
+ * Runs guest code in an AMD-V VM.
  *
  * @note NEVER EVER turn on interrupts here. Due to our illegal entry into the kernel, it might mess things up. (XP kernel traps have been frequently observed)
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 7470)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 7471)
@@ -49,11 +49,5 @@
 
         VMXReadVMCS(VMX_VMCS_RO_VM_INSTR_ERROR, &instrError);
-        Log(("VMXR0CheckError -> generic error %x\n", instrError));
-
         pVM->hwaccm.s.vmx.ulLastInstrError = instrError;
-    }
-    else
-    {
-        Log(("VMXR0CheckError failed with %Vrc\n", rc));
     }
     pVM->hwaccm.s.lLastError = rc;
@@ -61,10 +55,71 @@
 
 /**
- * Sets up and activates VMX
+ * Sets up and activates VT-x on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pVM             The VM to operate on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) VMXR0EnableCpu(RTCPUID idCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
+{
+    AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
+    AssertReturn(pVM, VERR_INVALID_PARAMETER);
+    AssertReturn(pvPageCpu, VERR_INVALID_PARAMETER);
+
+    /* Setup Intel VMX. */
+    Assert(pVM->hwaccm.s.vmx.fSupported);
+
+    /* Set revision dword at the beginning of the VMXON structure. */
+    *(uint32_t *)pvPageCpu = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
+
+    /* @todo we should unmap the two pages from the virtual address space in order to prevent accidental corruption.
+     * (which can have very bad consequences!!!)
+     */
+
+    /* Make sure the VMX instructions don't cause #UD faults. */
+    ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);
+
+    /* Enter VMX Root Mode */
+    int rc = VMXEnable(pPageCpuPhys);
+    if (VBOX_FAILURE(rc))
+    {
+        VMXR0CheckError(pVM, rc);
+        ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
+        return VERR_VMX_VMXON_FAILED;
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Deactivates VT-x on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) VMXR0DisableCpu(RTCPUID idCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
+{
+    AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
+    AssertReturn(pvPageCpu, VERR_INVALID_PARAMETER);
+
+    /* Leave VMX Root Mode. */
+    VMXDisable();
+
+    /* And clear the X86_CR4_VMXE bit */
+    ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
+    return VINF_SUCCESS;
+}
+
+/**
+ * Sets up VT-x for the specified VM
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) VMXR0Setup(PVM pVM)
+HWACCMR0DECL(int) VMXR0SetupVM(PVM pVM)
 {
     int rc = VINF_SUCCESS;
@@ -74,26 +129,6 @@
         return VERR_INVALID_PARAMETER;
 
-    /* Setup Intel VMX. */
-    Assert(pVM->hwaccm.s.vmx.fSupported);
-
-    /* Set revision dword at the beginning of both structures. */
+    /* Set revision dword at the beginning of the VMCS structure. */
     *(uint32_t *)pVM->hwaccm.s.vmx.pVMCS  = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
-    *(uint32_t *)pVM->hwaccm.s.vmx.pVMXON = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
-
-    /* @todo we should unmap the two pages from the virtual address space in order to prevent accidental corruption.
-     * (which can have very bad consequences!!!)
-     */
-
-    /* Make sure the VMX instructions don't cause #UD faults. */
-    ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);
-
-    /* Enter VMX Root Mode */
-    Log(("pVMXONPhys = %VHp\n", pVM->hwaccm.s.vmx.pVMXONPhys));
-    rc = VMXEnable(pVM->hwaccm.s.vmx.pVMXONPhys);
-    if (VBOX_FAILURE(rc))
-    {
-        VMXR0CheckError(pVM, rc);
-        return VERR_VMX_VMXON_FAILED;
-    }
 
     /* Clear VM Control Structure. */
@@ -274,6 +309,4 @@
 vmx_end:
     VMXR0CheckError(pVM, rc);
-    /* Leave VMX Root Mode. */
-    VMXDisable();
     return rc;
 }
@@ -1939,29 +1972,25 @@
 
 /**
- * Enable VMX
+ * Enters the VT-x session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) VMXR0Enable(PVM pVM)
+HWACCMR0DECL(int) VMXR0Enter(PVM pVM)
 {
     Assert(pVM->hwaccm.s.vmx.fSupported);
 
-    /* Make sure the VMX instructions don't cause #UD faults. */
-    ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);
-
-    /* Enter VMX Root Mode */
-    int rc = VMXEnable(pVM->hwaccm.s.vmx.pVMXONPhys);
+    unsigned cr4 = ASMGetCR4();
+    if (!(cr4 & X86_CR4_VMXE))
+    {
+        AssertMsgFailed(("X86_CR4_VMXE should be set!\n"));
+        return VERR_VMX_X86_CR4_VMXE_CLEARED;
+    }
+
+    /* Activate the VM Control Structure. */
+    int rc = VMXActivateVMCS(pVM->hwaccm.s.vmx.pVMCSPhys);
     if (VBOX_FAILURE(rc))
         return rc;
 
-    /* Activate the VM Control Structure. */
-    rc = VMXActivateVMCS(pVM->hwaccm.s.vmx.pVMCSPhys);
-    if (VBOX_FAILURE(rc))
-    {
-        /* Leave VMX Root Mode. */
-        VMXDisable();
-        return rc;
-    }
     pVM->hwaccm.s.vmx.fResumeVM = false;
     return VINF_SUCCESS;
@@ -1970,10 +1999,10 @@
 
 /**
- * Disable VMX
+ * Leaves the VT-x session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) VMXR0Disable(PVM pVM)
+HWACCMR0DECL(int) VMXR0Leave(PVM pVM)
 {
     Assert(pVM->hwaccm.s.vmx.fSupported);
@@ -1983,7 +2012,4 @@
     AssertRC(rc);
 
-    /* Leave VMX Root Mode. */
-    VMXDisable();
-
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.h
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.h	(revision 7470)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.h	(revision 7471)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /** @file
- * HWACCM SVM - Internal header file.
+ * HWACCM VT-x - Internal header file.
  */
 
@@ -39,26 +39,48 @@
 
 /**
- * Enable VMX
+ * Enters the VT-x session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) VMXR0Enable(PVM pVM);
+HWACCMR0DECL(int) VMXR0Enter(PVM pVM);
 
 /**
- * Disable VMX
+ * Leaves the VT-x session
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) VMXR0Disable(PVM pVM);
+HWACCMR0DECL(int) VMXR0Leave(PVM pVM);
+
 
 /**
- * Sets up and activates VMX
+ * Sets up and activates VT-x on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pVM             The VM to operate on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) VMXR0EnableCpu(RTCPUID idCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
+
+/**
+ * Deactivates VT-x on the current CPU
+ *
+ * @returns VBox status code.
+ * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pvPageCpu       Pointer to the global cpu page
+ * @param   pPageCpuPhys    Physical address of the global cpu page
+ */
+HWACCMR0DECL(int) VMXR0DisableCpu(RTCPUID idCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
+
+/**
+ * Sets up VT-x for the specified VM
  *
  * @returns VBox status code.
  * @param   pVM         The VM to operate on.
  */
-HWACCMR0DECL(int) VMXR0Setup(PVM pVM);
+HWACCMR0DECL(int) VMXR0SetupVM(PVM pVM);
 
 
@@ -82,5 +104,5 @@
 
 /**
- * Runs guest code in a VMX VM.
+ * Runs guest code in a VT-x VM.
  *
  * @note NEVER EVER turn on interrupts here. Due to our illegal entry into the kernel, it might mess things up. (XP kernel traps have been frequently observed)
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 7470)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 7471)
@@ -40,4 +40,5 @@
 #include <iprt/assert.h>
 #include <iprt/stdarg.h>
+#include <iprt/mp.h>
 
 #if defined(_MSC_VER) && defined(RT_ARCH_AMD64) /** @todo check this with with VC7! */
@@ -65,4 +66,7 @@
 #endif
 
+/*******************************************************************************
+*   Local Variables                                                            *
+*******************************************************************************/
 
 /**
@@ -78,5 +82,5 @@
 
     /*
-     * Initialize the GVMM and GMM.
+     * Initialize the GVMM, GMM.& HWACCM
      */
     int rc = GVMMR0Init();
@@ -86,20 +90,24 @@
         if (RT_SUCCESS(rc))
         {
+            rc = HWACCMR0Init();
+            if (RT_SUCCESS(rc))
+            {
 #ifdef VBOX_WITH_INTERNAL_NETWORKING
-            LogFlow(("ModuleInit: g_pIntNet=%p\n", g_pIntNet));
-            g_pIntNet = NULL;
-            LogFlow(("ModuleInit: g_pIntNet=%p should be NULL now...\n", g_pIntNet));
-            rc = INTNETR0Create(&g_pIntNet);
-            if (VBOX_SUCCESS(rc))
-            {
-                LogFlow(("ModuleInit: returns success. g_pIntNet=%p\n", g_pIntNet));
+                LogFlow(("ModuleInit: g_pIntNet=%p\n", g_pIntNet));
+                g_pIntNet = NULL;
+                LogFlow(("ModuleInit: g_pIntNet=%p should be NULL now...\n", g_pIntNet));
+                rc = INTNETR0Create(&g_pIntNet);
+                if (VBOX_SUCCESS(rc))
+                {
+                    LogFlow(("ModuleInit: returns success. g_pIntNet=%p\n", g_pIntNet));
+                    return VINF_SUCCESS;
+                }
+                g_pIntNet = NULL;
+                LogFlow(("ModuleTerm: returns %Vrc\n", rc));
+#else
+                LogFlow(("ModuleInit: returns success.\n"));
                 return VINF_SUCCESS;
+#endif
             }
-            g_pIntNet = NULL;
-            LogFlow(("ModuleTerm: returns %Vrc\n", rc));
-#else
-            LogFlow(("ModuleInit: returns success.\n"));
-            return VINF_SUCCESS;
-#endif
         }
     }
@@ -128,4 +136,7 @@
     }
 #endif
+
+    /* Global HWACCM cleanup */
+    HWACCMR0Term();
 
     /*
@@ -212,7 +223,5 @@
          * Init HWACCM.
          */
-        RTCCUINTREG fFlags = ASMIntDisableFlags();
-        rc = HWACCMR0Init(pVM);
-        ASMSetFlags(fFlags);
+        rc = HWACCMR0InitVM(pVM);
         if (RT_SUCCESS(rc))
         {
@@ -609,9 +618,9 @@
             RTCCUINTREG uFlags = ASMIntDisableFlags();
 #endif
-            int rc = HWACCMR0Enable(pVM);
+            int rc = HWACCMR0Enter(pVM);
             if (VBOX_SUCCESS(rc))
             {
                 rc = vmmR0CallHostSetJmp(&pVM->vmm.s.CallHostR0JmpBuf, HWACCMR0RunGuestCode, pVM); /* this may resume code. */
-                int rc2 = HWACCMR0Disable(pVM);
+                int rc2 = HWACCMR0Leave(pVM);
                 AssertRC(rc2);
             }
@@ -732,4 +741,11 @@
 
         /*
+         * Attempt to enable hwacc mode and check the current setting.
+         *
+         */
+        case VMMR0_DO_HWACC_ENABLE:
+            return HWACCMR0EnableAllCpus(pVM, (HWACCMSTATE)u64Arg);
+
+        /*
          * Setup the hardware accelerated raw-mode session.
          */
@@ -737,5 +753,5 @@
         {
             RTCCUINTREG fFlags = ASMIntDisableFlags();
-            int rc = HWACCMR0SetupVMX(pVM);
+            int rc = HWACCMR0SetupVM(pVM);
             ASMSetFlags(fFlags);
             return rc;
@@ -747,7 +763,7 @@
         case VMMR0_DO_CALL_HYPERVISOR:
         {
-            /* Safety precaution as VMX disables the switcher. */
+            /* Safety precaution as HWACCM can disable the switcher. */
             Assert(!pVM->vmm.s.fSwitcherDisabled);
-            if (pVM->vmm.s.fSwitcherDisabled)
+            if (RT_UNLIKELY(pVM->vmm.s.fSwitcherDisabled))
                 return VERR_NOT_SUPPORTED;
 
