Index: trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- trunk/src/VBox/VMM/HWACCM.cpp	(revision 8873)
+++ trunk/src/VBox/VMM/HWACCM.cpp	(revision 8876)
@@ -156,4 +156,5 @@
     STAM_REG(pVM, &pVM->hwaccm.s.StatFlushTLBWorldSwitch,   STAMTYPE_COUNTER, "/HWACCM/Flush/TLB/Switch",  STAMUNIT_OCCURENCES,    "Nr of occurances");
     STAM_REG(pVM, &pVM->hwaccm.s.StatNoFlushTLBWorldSwitch, STAMTYPE_COUNTER, "/HWACCM/Flush/TLB/Skipped", STAMUNIT_OCCURENCES,    "Nr of occurances");
+    STAM_REG(pVM, &pVM->hwaccm.s.StatFlushASID,             STAMTYPE_COUNTER, "/HWACCM/Flush/TLB/ASID",    STAMUNIT_OCCURENCES,    "Nr of occurances");
 
     pVM->hwaccm.s.pStatExitReason = 0;
Index: trunk/src/VBox/VMM/HWACCMInternal.h
===================================================================
--- trunk/src/VBox/VMM/HWACCMInternal.h	(revision 8873)
+++ trunk/src/VBox/VMM/HWACCMInternal.h	(revision 8876)
@@ -31,4 +31,6 @@
 #include <VBox/pgm.h>
 #include <iprt/memobj.h>
+#include <iprt/cpuset.h>
+#include <iprt/mp.h>
 
 __BEGIN_DECLS
@@ -317,4 +319,5 @@
     STAMCOUNTER             StatNoFlushTLBWorldSwitch;
     STAMCOUNTER             StatFlushTLBCRxChange;
+    STAMCOUNTER             StatFlushASID;
 
     STAMCOUNTER             StatSwitchGuestIrq;
@@ -327,4 +330,78 @@
 typedef HWACCM *PHWACCM;
 
+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 feature bits from cpuid 0x8000000a */
+        uint32_t                    u32Features;
+    } svm;
+    /** Saved error from detection */
+    int32_t         lLastError;
+
+    struct
+    {
+        uint32_t                    u32AMDFeatureECX;
+        uint32_t                    u32AMDFeatureEDX;
+    } cpuid;
+
+    HWACCMSTATE     enmHwAccmState;
+} HWACCMR0GLOBALS;
+
+typedef struct
+{
+    RTCPUID     idCpu;
+
+    RTR0MEMOBJ  pMemObj;
+    /* Current ASID (AMD-V only) */
+    uint32_t    uCurrentASID;
+
+    bool        fVMXConfigured;
+    bool        fSVMConfigured;
+} HWACCM_CPUINFO;
+typedef HWACCM_CPUINFO *PHWACCM_CPUINFO;
 
 #ifdef IN_RING0
Index: trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 8873)
+++ trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp	(revision 8876)
@@ -57,12 +57,8 @@
 *   Local Variables                                                            *
 *******************************************************************************/
+
 static struct
 {
-    struct
-    {
-        RTR0MEMOBJ  pMemObj;
-        bool        fVMXConfigured;
-        bool        fSVMConfigured;
-    } aCpuInfo[RTCPUSET_MAX_CPUS];
+    HWACCM_CPUINFO aCpuInfo[RTCPUSET_MAX_CPUS];
 
     struct
@@ -536,5 +532,5 @@
     if (pVM->hwaccm.s.vmx.fSupported)
     {
-        paRc[idCpu] = VMXR0EnableCpu(idCpu, pVM, pvPageCpu, pPageCpuPhys);
+        paRc[idCpu] = VMXR0EnableCpu(&HWACCMR0Globals.aCpuInfo[idCpu], pVM, pvPageCpu, pPageCpuPhys);
         AssertRC(paRc[idCpu]);
         if (VBOX_SUCCESS(paRc[idCpu]))
@@ -544,5 +540,5 @@
     if (pVM->hwaccm.s.svm.fSupported)
     {
-        paRc[idCpu] = SVMR0EnableCpu(idCpu, pVM, pvPageCpu, pPageCpuPhys);
+        paRc[idCpu] = SVMR0EnableCpu(&HWACCMR0Globals.aCpuInfo[idCpu], pVM, pvPageCpu, pPageCpuPhys);
         AssertRC(paRc[idCpu]);
         if (VBOX_SUCCESS(paRc[idCpu]))
@@ -577,5 +573,5 @@
     if (HWACCMR0Globals.aCpuInfo[idCpu].fVMXConfigured)
     {
-        paRc[idCpu] = VMXR0DisableCpu(idCpu, pvPageCpu, pPageCpuPhys);
+        paRc[idCpu] = VMXR0DisableCpu(&HWACCMR0Globals.aCpuInfo[idCpu], pvPageCpu, pPageCpuPhys);
         AssertRC(paRc[idCpu]);
         HWACCMR0Globals.aCpuInfo[idCpu].fVMXConfigured = false;
@@ -584,5 +580,5 @@
     if (HWACCMR0Globals.aCpuInfo[idCpu].fSVMConfigured)
     {
-        paRc[idCpu] = SVMR0DisableCpu(idCpu, pvPageCpu, pPageCpuPhys);
+        paRc[idCpu] = SVMR0DisableCpu(&HWACCMR0Globals.aCpuInfo[idCpu], pvPageCpu, pPageCpuPhys);
         AssertRC(paRc[idCpu]);
         HWACCMR0Globals.aCpuInfo[idCpu].fSVMConfigured = false;
@@ -797,4 +793,5 @@
     CPUMCTX *pCtx;
     int      rc;
+    RTCPUID  idCpu = RTMpCpuId();
 
     rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
@@ -804,10 +801,10 @@
     if (pVM->hwaccm.s.vmx.fSupported)
     {
-        return VMXR0RunGuestCode(pVM, pCtx);
+        return VMXR0RunGuestCode(pVM, pCtx, &HWACCMR0Globals.aCpuInfo[idCpu]);
     }
     else
     {
         Assert(pVM->hwaccm.s.svm.fSupported);
-        return SVMR0RunGuestCode(pVM, pCtx);
+        return SVMR0RunGuestCode(pVM, pCtx, &HWACCMR0Globals.aCpuInfo[idCpu]);
     }
 }
Index: trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 8873)
+++ trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 8876)
@@ -42,4 +42,6 @@
 #include <iprt/assert.h>
 #include <iprt/asm.h>
+#include <iprt/cpuset.h>
+#include <iprt/mp.h>
 #include "HWSVMR0.h"
 
@@ -50,10 +52,10 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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)
+HWACCMR0DECL(int) SVMR0EnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
 {
     AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
@@ -63,4 +65,8 @@
     /* We must turn on AMD-V and setup the host state physical address, as those MSRs are per-cpu/core. */
 
+#ifdef LOG_ENABLED
+    SUPR0Printf("SVMR0EnableCpu cpu %d page (%x) %x\n", pCpu->idCpu, pvPageCpu, (uint32_t)pPageCpuPhys);
+#endif
+
     /* Turn on AMD-V in the EFER MSR. */
     uint64_t val = ASMRdMsr(MSR_K6_EFER);
@@ -70,4 +76,6 @@
     /* Write the physical page address where the CPU will store the host state while executing the VM. */
     ASMWrMsr(MSR_K8_VM_HSAVE_PA, pPageCpuPhys);
+
+    pCpu->uCurrentASID = 0;   /* we'll aways increment this the first time (host uses ASID 0) */
     return VINF_SUCCESS;
 }
@@ -77,13 +85,17 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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)
+HWACCMR0DECL(int) SVMR0DisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
 {
     AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
     AssertReturn(pvPageCpu, VERR_INVALID_PARAMETER);
 
+#ifdef LOG_ENABLED
+    SUPR0Printf("SVMR0DisableCpu cpu %d\n", pCpu->idCpu);
+#endif
+
     /* Turn off AMD-V in the EFER MSR. */
     uint64_t val = ASMRdMsr(MSR_K6_EFER);
@@ -92,4 +104,6 @@
     /* Invalidate host state physical address. */
     ASMWrMsr(MSR_K8_VM_HSAVE_PA, 0);
+    pCpu->uCurrentASID = 0;
+
     return VINF_SUCCESS;
 }
@@ -301,4 +315,7 @@
     pVMCB->ctrl.u64LBRVirt      = 0;
 
+    /** The ASID must start at 1; the host uses 0. */
+    pVMCB->ctrl.TLBCtrl.n.u32ASID = 1;
+
     return rc;
 }
@@ -638,7 +655,4 @@
     pVMCB->guest.u64EFER   = MSR_K6_EFER_SVME;
 
-    /** @note We can do more complex things with tagged TLBs. */
-    pVMCB->ctrl.TLBCtrl.n.u32ASID = 1;
-
     /** TSC offset. */
     if (TMCpuTickCanUseRealTSC(pVM, &pVMCB->ctrl.u64TSCOffset))
@@ -678,6 +692,7 @@
  * @param   pVM         The VM to operate on.
  * @param   pCtx        Guest context
+ * @param   pCpu        CPU info struct
  */
-HWACCMR0DECL(int) SVMR0RunGuestCode(PVM pVM, CPUMCTX *pCtx)
+HWACCMR0DECL(int) SVMR0RunGuestCode(PVM pVM, CPUMCTX *pCtx, PHWACCM_CPUINFO pCpu)
 {
     int         rc = VINF_SUCCESS;
@@ -688,4 +703,6 @@
 
     STAM_PROFILE_ADV_START(&pVM->hwaccm.s.StatEntry, x);
+
+    AssertReturn(pCpu->fSVMConfigured, VERR_EM_INTERNAL_ERROR);
 
     pVMCB = (SVM_VMCB *)pVM->hwaccm.s.svm.pVMCB;
@@ -771,5 +788,24 @@
 
     /* Make sure we flush the TLB when required. */
-    pVMCB->ctrl.TLBCtrl.n.u1TLBFlush = pVM->hwaccm.s.svm.fForceTLBFlush;
+    if (    pVM->hwaccm.s.svm.fForceTLBFlush
+        && !pVM->hwaccm.s.svm.fAlwaysFlushTLB)
+    {
+        if (++pCpu->uCurrentASID >= pVM->hwaccm.s.svm.u32MaxASID)
+        {
+            pCpu->uCurrentASID               = 1;       /* start at 1; host uses 0 */
+            pVMCB->ctrl.TLBCtrl.n.u1TLBFlush = 1;       /* wrap around; flush TLB */
+        }
+        else
+            STAM_COUNTER_INC(&pVM->hwaccm.s.StatFlushASID);
+    }
+    else
+    {
+        Assert(pVM->hwaccm.s.svm.fForceTLBFlush == pVM->hwaccm.s.svm.fAlwaysFlushTLB);
+        pVMCB->ctrl.TLBCtrl.n.u1TLBFlush = pVM->hwaccm.s.svm.fForceTLBFlush;
+    }
+
+    Assert(pCpu->uCurrentASID >= 1 && pCpu->uCurrentASID < pVM->hwaccm.s.svm.u32MaxASID);
+    pVMCB->ctrl.TLBCtrl.n.u32ASID = pCpu->uCurrentASID;
+
 #ifdef VBOX_WITH_STATISTICS
     if (pVMCB->ctrl.TLBCtrl.n.u1TLBFlush)
Index: trunk/src/VBox/VMM/VMMR0/HWSVMR0.h
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWSVMR0.h	(revision 8873)
+++ trunk/src/VBox/VMM/VMMR0/HWSVMR0.h	(revision 8876)
@@ -62,10 +62,10 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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);
+HWACCMR0DECL(int) SVMR0EnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
 
 /**
@@ -73,9 +73,9 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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);
+HWACCMR0DECL(int) SVMR0DisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
 
 /**
@@ -112,6 +112,7 @@
  * @param   pVM         The VM to operate on.
  * @param   pCtx        Guest context
+ * @param   pCpu        CPU info struct
  */
-HWACCMR0DECL(int) SVMR0RunGuestCode(PVM pVM, CPUMCTX *pCtx);
+HWACCMR0DECL(int) SVMR0RunGuestCode(PVM pVM, CPUMCTX *pCtx, PHWACCM_CPUINFO pCpu);
 
 
Index: trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 8873)
+++ trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 8876)
@@ -63,10 +63,10 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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)
+HWACCMR0DECL(int) VMXR0EnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
 {
     AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
@@ -78,5 +78,5 @@
 
 #ifdef LOG_ENABLED
-    SUPR0Printf("VMXR0EnableCpu cpu %d page (%x) %x\n", idCpu, pvPageCpu, (uint32_t)pPageCpuPhys);
+    SUPR0Printf("VMXR0EnableCpu cpu %d page (%x) %x\n", pCpu->idCpu, pvPageCpu, (uint32_t)pPageCpuPhys);
 #endif
     /* Set revision dword at the beginning of the VMXON structure. */
@@ -105,9 +105,9 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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)
+HWACCMR0DECL(int) VMXR0DisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
 {
     AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
@@ -121,5 +121,5 @@
 
 #ifdef LOG_ENABLED
-    SUPR0Printf("VMXR0DisableCpu cpu %d\n", idCpu);
+    SUPR0Printf("VMXR0DisableCpu cpu %d\n", pCpu->idCpu);
 #endif
     return VINF_SUCCESS;
@@ -963,5 +963,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)
@@ -970,6 +970,7 @@
  * @param   pVM         The VM to operate on.
  * @param   pCtx        Guest context
+ * @param   pCpu        CPU info struct
  */
-HWACCMR0DECL(int) VMXR0RunGuestCode(PVM pVM, CPUMCTX *pCtx)
+HWACCMR0DECL(int) VMXR0RunGuestCode(PVM pVM, CPUMCTX *pCtx, PHWACCM_CPUINFO pCpu)
 {
     int         rc = VINF_SUCCESS;
@@ -983,4 +984,6 @@
 
     Log2(("\nE"));
+
+    AssertReturn(pCpu->fVMXConfigured, VERR_EM_INTERNAL_ERROR);
 
     STAM_PROFILE_ADV_START(&pVM->hwaccm.s.StatEntry, x);
Index: trunk/src/VBox/VMM/VMMR0/HWVMXR0.h
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWVMXR0.h	(revision 8873)
+++ trunk/src/VBox/VMM/VMMR0/HWVMXR0.h	(revision 8876)
@@ -63,10 +63,10 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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);
+HWACCMR0DECL(int) VMXR0EnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
 
 /**
@@ -74,9 +74,9 @@
  *
  * @returns VBox status code.
- * @param   idCpu           The identifier for the CPU the function is called on.
+ * @param   pCpu            CPU info struct
  * @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);
+HWACCMR0DECL(int) VMXR0DisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys);
 
 /**
@@ -131,6 +131,7 @@
  * @param   pVM         The VM to operate on.
  * @param   pCtx        Guest context
+ * @param   pCpu        CPU info struct
  */
-HWACCMR0DECL(int) VMXR0RunGuestCode(PVM pVM, CPUMCTX *pCtx);
+HWACCMR0DECL(int) VMXR0RunGuestCode(PVM pVM, CPUMCTX *pCtx, PHWACCM_CPUINFO pCpu);
 
 
