Index: /trunk/include/VBox/vmm/vm.h
===================================================================
--- /trunk/include/VBox/vmm/vm.h	(revision 87811)
+++ /trunk/include/VBox/vmm/vm.h	(revision 87812)
@@ -1364,5 +1364,5 @@
         struct TM   s;
 #endif
-        uint8_t     padding[9152];      /* multiple of 64 */
+        uint8_t     padding[9920];      /* multiple of 64 */
     } tm;
 
@@ -1463,5 +1463,5 @@
 
     /** Padding for aligning the structure size on a page boundrary. */
-    uint8_t         abAlignment2[2392 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
+    uint8_t         abAlignment2[1624 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
 
     /* ---- end small stuff ---- */
Index: /trunk/include/VBox/vmm/vm.mac
===================================================================
--- /trunk/include/VBox/vmm/vm.mac	(revision 87811)
+++ /trunk/include/VBox/vmm/vm.mac	(revision 87812)
@@ -63,14 +63,24 @@
     alignb 64
     .hm                     resb 5888
+    alignb 64
     .nem                    resb 512
+    alignb 64
     .trpm                   resb 128
+    alignb 64
     .tm                     resb 5760
+    alignb 64
     .vmm                    resb 896
+    alignb 64
     .pdm                    resb 256
+    alignb 64
     .iom                    resb 512
+    alignb 64
     .dbgf                   resb 512
+    alignb 64
     .gim                    resb 512
+    alignb 64
     .apic                   resb 3840
 
+    alignb 64
     .fTraceGroups           resd 1
     .uAdHoc                 resd 1
@@ -121,19 +131,35 @@
     alignb 64
     .cpum                   resb 1536
+    alignb 64
     .vmm                    resb 1600
+    alignb 64
     .pgm                    resb 21120
+    alignb 64
     .hm                     resb 5504
+    alignb 64
     .trpm                   resb 2048
+    alignb 64
     .selm                   resb 768
+    alignb 64
     .mm                     resb 192
+    alignb 64
     .pdm                    resb 8128
+    alignb 64
     .iom                    resb 1152
+    alignb 64
     .em                     resb 256
+    alignb 64
     .nem                    resb 128
-    .tm                     resb 9152
+    alignb 64
+    .tm                     resb 9920
+    alignb 64
     .dbgf                   resb 2432
+    alignb 64
     .ssm                    resb 128
+    alignb 64
     .gim                    resb 448
+    alignb 64
     .apic                   resb 128
+    alignb 64
     .vm                     resb 32
     .cfgm                   resb 8
Index: /trunk/src/VBox/VMM/VMMAll/TMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/TMAll.cpp	(revision 87811)
+++ /trunk/src/VBox/VMM/VMMAll/TMAll.cpp	(revision 87812)
@@ -365,22 +365,24 @@
     PTMTIMERQUEUECC const   pQueueCC = TM_GET_TIMER_QUEUE_CC(pVM, enmClock, pQueue);
 
-    if (    VM_IS_EMT(pVM)
-        &&  RT_SUCCESS(TM_TRY_LOCK_TIMERS(pVM)))
-    {
-        STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatScheduleOne), a);
-        Log3(("tmSchedule: tmTimerQueueSchedule\n"));
-        tmTimerQueueSchedule(pVM, pQueueCC, pQueue);
+    if (VM_IS_EMT(pVM)) /** @todo drop EMT requirement here. */
+    {
+        int rc = PDMCritSectTryEnter(&pQueue->TimerLock);
+        if (RT_SUCCESS_NP(rc))
+        {
+            STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatScheduleOne), a);
+            Log3(("tmSchedule: tmTimerQueueSchedule\n"));
+            tmTimerQueueSchedule(pVM, pQueueCC, pQueue);
 #ifdef VBOX_STRICT
-        tmTimerQueuesSanityChecks(pVM, "tmSchedule");
+            tmTimerQueuesSanityChecks(pVM, "tmSchedule");
 #endif
-        STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatScheduleOne), a);
-        TM_UNLOCK_TIMERS(pVM);
-    }
-    else
-    {
-        TMTIMERSTATE enmState = pTimer->enmState;
-        if (TMTIMERSTATE_IS_PENDING_SCHEDULING(enmState))
-            tmScheduleNotify(pVM);
-    }
+            STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatScheduleOne), a);
+            PDMCritSectLeave(&pQueue->TimerLock);
+            return;
+        }
+    }
+
+    TMTIMERSTATE enmState = pTimer->enmState;
+    if (TMTIMERSTATE_IS_PENDING_SCHEDULING(enmState))
+        tmScheduleNotify(pVM);
 }
 
@@ -624,6 +626,5 @@
 void tmTimerQueueSchedule(PVMCC pVM, PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueue)
 {
-    TM_ASSERT_TIMER_LOCK_OWNERSHIP(pVM);
-    NOREF(pVM);
+    Assert(PDMCritSectIsOwner(&pQueue->TimerLock));
 
     /*
@@ -661,11 +662,7 @@
  * @param   pVM         The cross context VM structure.
  * @param   pszWhere    Caller location clue.
- *
- * @remarks Called while owning the lock.
  */
 void tmTimerQueuesSanityChecks(PVMCC pVM, const char *pszWhere)
 {
-    TM_ASSERT_TIMER_LOCK_OWNERSHIP(pVM);
-
     for (uint32_t idxQueue = 0; idxQueue < RT_ELEMENTS(pVM->tm.s.aTimerQueues); idxQueue++)
     {
@@ -674,5 +671,5 @@
         Assert(pQueue->enmClock == (TMCLOCK)idxQueue);
 
-        int rc = PDMCritSectRwTryEnterShared(&pQueue->AllocLock);
+        int rc = PDMCritSectTryEnter(&pQueue->TimerLock);
         if (RT_SUCCESS(rc))
         {
@@ -780,5 +777,5 @@
                     PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
             }
-            PDMCritSectRwLeaveShared(&pQueue->AllocLock);
+            PDMCritSectLeave(&pQueue->TimerLock);
         }
     }
@@ -1198,13 +1195,12 @@
  * @param   pTimer          The timer handle.
  * @param   u64Expire       The new expire time.
- */
-static int tmTimerSetOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t u64Expire)
+ * @param   pQueue          Pointer to the shared timer queue data.
+ * @param   enmClock        The sanitized clock.
+ */
+static int tmTimerSetOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t u64Expire, PTMTIMERQUEUE pQueue, TMCLOCK enmClock)
 {
     Assert(pTimer->idxPrev == UINT32_MAX);
     Assert(pTimer->idxNext == UINT32_MAX);
     Assert(pTimer->enmState == TMTIMERSTATE_ACTIVE);
-
-    TMCLOCK const enmClock = pTimer->enmClock;
-    AssertReturn((unsigned)enmClock < TMCLOCK_MAX, VERR_TM_IPE_2);
 
     /*
@@ -1224,9 +1220,7 @@
      * Link the timer into the active list.
      */
-    PTMTIMERQUEUE const pQueue = &pVM->tm.s.aTimerQueues[enmClock];
     tmTimerQueueLinkActive(pVM, TM_GET_TIMER_QUEUE_CC(pVM, enmClock, pQueue), pQueue, pTimer, u64Expire);
 
     STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetOpt);
-    TM_UNLOCK_TIMERS(pVM);
     return VINF_SUCCESS;
 }
@@ -1358,13 +1352,19 @@
     {
         /* Try take the TM lock and check the state again. */
-        if (RT_SUCCESS_NP(TM_TRY_LOCK_TIMERS(pVM)))
+        TMCLOCK const       enmClock = pTimer->enmClock;
+        AssertReturn((unsigned)enmClock < TMCLOCK_MAX, VERR_TM_IPE_2);
+        PTMTIMERQUEUE const pQueue   = &pVM->tm.s.aTimerQueues[enmClock];
+
+        int rc = PDMCritSectTryEnter(&pQueue->TimerLock);
+        if (RT_SUCCESS_NP(rc))
         {
             if (RT_LIKELY(tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, enmState1)))
             {
-                tmTimerSetOptimizedStart(pVM, pTimer, u64Expire);
+                tmTimerSetOptimizedStart(pVM, pTimer, u64Expire, pQueue, enmClock);
                 STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatTimerSet), a);
+                PDMCritSectLeave(&pQueue->TimerLock);
                 return VINF_SUCCESS;
             }
-            TM_UNLOCK_TIMERS(pVM);
+            PDMCritSectLeave(&pQueue->TimerLock);
         }
     }
@@ -1508,6 +1508,9 @@
  * @param   pu64Now         Where to return the current time stamp used.
  *                          Optional.
- */
-static int tmTimerSetRelativeOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
+ * @param   pQueue          Pointer to the shared timer queue data.
+ * @param   enmClock        The sanitized clock.
+ */
+static int tmTimerSetRelativeOptimizedStart(PVMCC pVM, PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now,
+                                            PTMTIMERQUEUE pQueue, TMCLOCK enmClock)
 {
     Assert(pTimer->idxPrev == UINT32_MAX);
@@ -1518,6 +1521,4 @@
      * Calculate and set the expiration time.
      */
-    TMCLOCK const   enmClock  = pTimer->enmClock;
-    AssertReturn((unsigned)enmClock < (unsigned)TMCLOCK_MAX, VERR_TM_IPE_2);
     uint64_t const  u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now);
     pTimer->u64Expire         = u64Expire;
@@ -1528,9 +1529,7 @@
      */
     DBGFTRACE_U64_TAG2(pVM, u64Expire, "tmTimerSetRelativeOptimizedStart", pTimer->szName);
-    PTMTIMERQUEUE const pQueue = &pVM->tm.s.aTimerQueues[enmClock];
     tmTimerQueueLinkActive(pVM, TM_GET_TIMER_QUEUE_CC(pVM, enmClock, pQueue), pQueue, pTimer, u64Expire);
 
     STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeOpt);
-    TM_UNLOCK_TIMERS(pVM);
     return VINF_SUCCESS;
 }
@@ -1630,6 +1629,8 @@
 
     /* Treat virtual sync timers specially. */
-    if (pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC)
+    TMCLOCK enmClock = pTimer->enmClock;
+    if (enmClock == TMCLOCK_VIRTUAL_SYNC)
         return tmTimerVirtualSyncSetRelative(pVM, pTimer, cTicksToNext, pu64Now);
+    AssertReturn((unsigned)enmClock < (unsigned)TMCLOCK_MAX, VERR_TM_IPE_2);
 
     STAM_PROFILE_START(&pVM->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a);
@@ -1670,5 +1671,6 @@
      *       get the innermost locks.
      */
-    bool fOwnTMLock = RT_SUCCESS_NP(TM_TRY_LOCK_TIMERS(pVM));
+    PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[enmClock];
+    bool fOwnTMLock = RT_SUCCESS_NP(PDMCritSectTryEnter(&pQueue->TimerLock));
 #if 1
     if (    fOwnTMLock
@@ -1680,6 +1682,7 @@
                       && tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, enmState)))
         {
-            tmTimerSetRelativeOptimizedStart(pVM, pTimer, cTicksToNext, pu64Now);
+            tmTimerSetRelativeOptimizedStart(pVM, pTimer, cTicksToNext, pu64Now, pQueue, enmClock);
             STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a);
+            PDMCritSectLeave(&pQueue->TimerLock);
             return VINF_SUCCESS;
         }
@@ -1692,6 +1695,5 @@
      * Unoptimized path.
      */
-    int             rc;
-    TMCLOCK const   enmClock = pTimer->enmClock;
+    int rc;
     for (int cRetries = 1000; ; cRetries--)
     {
@@ -1822,5 +1824,5 @@
          */
         if (!fOwnTMLock)
-            fOwnTMLock = RT_SUCCESS_NP(TM_TRY_LOCK_TIMERS(pVM));
+            fOwnTMLock = RT_SUCCESS_NP(PDMCritSectTryEnter(&pQueue->TimerLock));
 
     } /* for (;;) */
@@ -1830,5 +1832,5 @@
      */
     if (fOwnTMLock)
-        TM_UNLOCK_TIMERS(pVM);
+        PDMCritSectLeave(&pQueue->TimerLock);
 
     STAM_PROFILE_STOP(&pVM->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a);
@@ -1872,6 +1874,5 @@
 VMMDECL(int) TMTimerSetFrequencyHint(PVMCC pVM, TMTIMERHANDLE hTimer, uint32_t uHzHint)
 {
-    PTMTIMER pTimer;
-    TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer);
+    TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */
     TMTIMER_ASSERT_CRITSECT(pVM, pTimer);
 
@@ -1879,8 +1880,8 @@
     pTimer->uHzHint = uHzHint;
 
-    uint32_t const uMaxHzHint = pVM->tm.s.uMaxHzHint;
+    uint32_t const uMaxHzHint = pQueue->uMaxHzHint;
     if (   uHzHint    >  uMaxHzHint
         || uHzOldHint >= uMaxHzHint)
-        ASMAtomicWriteBool(&pVM->tm.s.fHzHintNeedsUpdating, true);
+        ASMAtomicOrU64(&pVM->tm.s.HzHint.u64Combined, RT_BIT_32(idxQueue) | RT_BIT_32(idxQueue + 16));
 
     return VINF_SUCCESS;
@@ -1907,13 +1908,14 @@
 
     /* Reset the HZ hint. */
-    if (pTimer->uHzHint)
-    {
-        if (pTimer->uHzHint >= pVM->tm.s.uMaxHzHint)
-            ASMAtomicWriteBool(&pVM->tm.s.fHzHintNeedsUpdating, true);
+    uint32_t uOldHzHint = pTimer->uHzHint;
+    if (uOldHzHint)
+    {
+        if (uOldHzHint >= pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC].uMaxHzHint)
+            ASMAtomicOrU64(&pVM->tm.s.HzHint.u64Combined, RT_BIT_32(TMCLOCK_VIRTUAL_SYNC) | RT_BIT_32(TMCLOCK_VIRTUAL_SYNC + 16));
         pTimer->uHzHint = 0;
     }
 
     /* Update the timer state. */
-    TMTIMERSTATE const      enmState = pTimer->enmState;
+    TMTIMERSTATE const enmState = pTimer->enmState;
     switch (enmState)
     {
@@ -1971,10 +1973,9 @@
 VMMDECL(int) TMTimerStop(PVMCC pVM, TMTIMERHANDLE hTimer)
 {
-    PTMTIMER pTimer;
-    TMTIMER_HANDLE_TO_PTR_RETURN(pVM, hTimer, pTimer);
+    TMTIMER_HANDLE_TO_VARS_RETURN(pVM, hTimer); /* => pTimer, pQueueCC, pQueue, idxTimer, idxQueue */
     STAM_COUNTER_INC(&pTimer->StatStop);
 
     /* Treat virtual sync timers specially. */
-    if (pTimer->enmClock == TMCLOCK_VIRTUAL_SYNC)
+    if (idxQueue == TMCLOCK_VIRTUAL_SYNC)
         return tmTimerVirtualSyncStop(pVM, pTimer);
 
@@ -1985,8 +1986,9 @@
      * Reset the HZ hint.
      */
-    if (pTimer->uHzHint)
-    {
-        if (pTimer->uHzHint >= pVM->tm.s.uMaxHzHint)
-            ASMAtomicWriteBool(&pVM->tm.s.fHzHintNeedsUpdating, true);
+    uint32_t const uOldHzHint = pTimer->uHzHint;
+    if (uOldHzHint)
+    {
+        if (uOldHzHint >= pQueue->uMaxHzHint)
+            ASMAtomicOrU64(&pVM->tm.s.HzHint.u64Combined, RT_BIT_32(idxQueue) | RT_BIT_32(idxQueue + 16));
         pTimer->uHzHint = 0;
     }
@@ -2614,38 +2616,49 @@
 
 /**
- * Gets the highest frequency hint for all the important timers.
+ * The slow path of tmGetFrequencyHint() where we try to recalculate the value.
  *
  * @returns The highest frequency.  0 if no timers care.
- * @param   pVM         The cross context VM structure.
- */
-static uint32_t tmGetFrequencyHint(PVMCC pVM)
-{
+ * @param   pVM             The cross context VM structure.
+ * @param   uOldMaxHzHint   The old global hint.
+ */
+DECL_NO_INLINE(static, uint32_t) tmGetFrequencyHintSlow(PVMCC pVM, uint32_t uOldMaxHzHint)
+{
+    /* Set two bits, though not entirely sure it's needed (too exhaused to think clearly)
+       but it should force other callers thru the slow path while we're recalculating and
+       help us detect changes while we're recalculating. */
+    AssertCompile(RT_ELEMENTS(pVM->tm.s.aTimerQueues) <= 16);
+
     /*
-     * Query the value, recalculate it if necessary.
-     *
      * The "right" highest frequency value isn't so important that we'll block
-     * waiting on the timer semaphore.
+     * waiting on the timer semaphores.
      */
-    uint32_t uMaxHzHint = ASMAtomicUoReadU32(&pVM->tm.s.uMaxHzHint);
-    if (RT_UNLIKELY(ASMAtomicReadBool(&pVM->tm.s.fHzHintNeedsUpdating)))
-    {
-        if (RT_SUCCESS(TM_TRY_LOCK_TIMERS(pVM)))
+    uint32_t uMaxHzHint = 0;
+    for (uint32_t idxQueue = 0; idxQueue < RT_ELEMENTS(pVM->tm.s.aTimerQueues); idxQueue++)
+    {
+        PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[idxQueue];
+
+        /* Get the max Hz hint for the queue. */
+        uint32_t uMaxHzHintQueue;
+        if (  !(ASMAtomicUoReadU64(&pVM->tm.s.HzHint.u64Combined) & (RT_BIT_32(idxQueue) | RT_BIT_32(idxQueue + 16)))
+            || RT_FAILURE_NP(PDMCritSectTryEnter(&pQueue->TimerLock)))
+            uMaxHzHintQueue = ASMAtomicReadU32(&pQueue->uMaxHzHint);
+        else
         {
-            ASMAtomicWriteBool(&pVM->tm.s.fHzHintNeedsUpdating, false);
-
-            /*
-             * Loop over the timers associated with each clock.
-             */
-            uMaxHzHint = 0;
-            for (uint32_t idxQueue = 0; idxQueue < RT_ELEMENTS(pVM->tm.s.aTimerQueues); idxQueue++)
+            /* Is it still necessary to do updating? */
+            if (ASMAtomicUoReadU64(&pVM->tm.s.HzHint.u64Combined) & (RT_BIT_32(idxQueue) | RT_BIT_32(idxQueue + 16)))
             {
-                PTMTIMERQUEUE   pQueue   = &pVM->tm.s.aTimerQueues[idxQueue];
+                ASMAtomicAndU64(&pVM->tm.s.HzHint.u64Combined, ~RT_BIT_64(idxQueue + 16)); /* clear one flag up front */
+
                 PTMTIMERQUEUECC pQueueCC = TM_GET_TIMER_QUEUE_CC(pVM, idxQueue, pQueue);
-                for (PTMTIMER pCur = tmTimerQueueGetHead(pQueueCC, pQueue); pCur; pCur = tmTimerGetNext(pQueueCC, pCur))
+                uMaxHzHintQueue = 0;
+                for (PTMTIMER pCur = tmTimerQueueGetHead(pQueueCC, pQueue);
+                     pCur;
+                     pCur = tmTimerGetNext(pQueueCC, pCur))
                 {
                     uint32_t uHzHint = ASMAtomicUoReadU32(&pCur->uHzHint);
-                    if (uHzHint > uMaxHzHint)
+                    if (uHzHint > uMaxHzHintQueue)
                     {
-                        switch (pCur->enmState)
+                        TMTIMERSTATE enmState = pCur->enmState;
+                        switch (enmState)
                         {
                             case TMTIMERSTATE_ACTIVE:
@@ -2656,5 +2669,5 @@
                             case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:
                             case TMTIMERSTATE_PENDING_RESCHEDULE:
-                                uMaxHzHint = uHzHint;
+                                uMaxHzHintQueue = uHzHint;
                                 break;
 
@@ -2670,11 +2683,58 @@
                     }
                 }
+
+                /* Write the new Hz hint for the quest and clear the other update flag. */
+                ASMAtomicUoWriteU32(&pQueue->uMaxHzHint, uMaxHzHintQueue);
+                ASMAtomicAndU64(&pVM->tm.s.HzHint.u64Combined, ~RT_BIT_64(idxQueue));
             }
-            ASMAtomicWriteU32(&pVM->tm.s.uMaxHzHint, uMaxHzHint);
-            Log(("tmGetFrequencyHint: New value %u Hz\n", uMaxHzHint));
-            TM_UNLOCK_TIMERS(pVM);
+            else
+                uMaxHzHintQueue = ASMAtomicUoReadU32(&pQueue->uMaxHzHint);
+
+            PDMCritSectLeave(&pQueue->TimerLock);
         }
-    }
+
+        /* Update the global max Hz hint. */
+        if (uMaxHzHint < uMaxHzHintQueue)
+            uMaxHzHint = uMaxHzHintQueue;
+    }
+
+    /*
+     * Update the frequency hint if no pending frequency changes and we didn't race anyone thru here.
+     */
+    uint64_t u64Actual = RT_MAKE_U64(0 /*no pending updates*/, uOldMaxHzHint);
+    if (ASMAtomicCmpXchgExU64(&pVM->tm.s.HzHint.u64Combined, RT_MAKE_U64(0, uMaxHzHint), u64Actual, &u64Actual))
+        Log(("tmGetFrequencyHintSlow: New value %u Hz\n", uMaxHzHint));
+    else
+        for (uint32_t iTry = 1;; iTry++)
+        {
+            if (RT_LO_U32(u64Actual) != 0)
+                Log(("tmGetFrequencyHintSlow: Outdated value %u Hz (%#x, try %u)\n", uMaxHzHint, RT_LO_U32(u64Actual), iTry));
+            else if (iTry >= 4)
+                Log(("tmGetFrequencyHintSlow: Unable to set %u Hz (try %u)\n", uMaxHzHint, iTry));
+            else if (ASMAtomicCmpXchgExU64(&pVM->tm.s.HzHint.u64Combined, RT_MAKE_U64(0, uMaxHzHint), u64Actual, &u64Actual))
+                Log(("tmGetFrequencyHintSlow: New value %u Hz (try %u)\n", uMaxHzHint, iTry));
+            else
+                continue;
+            break;
+        }
     return uMaxHzHint;
+}
+
+
+/**
+ * Gets the highest frequency hint for all the important timers.
+ *
+ * @returns The highest frequency.  0 if no timers care.
+ * @param   pVM         The cross context VM structure.
+ */
+DECLINLINE(uint32_t) tmGetFrequencyHint(PVMCC pVM)
+{
+    /*
+     * Query the value, recalculate it if necessary.
+     */
+    uint64_t u64Combined = ASMAtomicReadU64(&pVM->tm.s.HzHint.u64Combined);
+    if (RT_HI_U32(u64Combined) == 0)
+        return RT_LO_U32(u64Combined); /* hopefully somewhat likely */
+    return tmGetFrequencyHintSlow(pVM, RT_LO_U32(u64Combined));
 }
 
Index: /trunk/src/VBox/VMM/VMMR3/TM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/TM.cpp	(revision 87811)
+++ /trunk/src/VBox/VMM/VMMR3/TM.cpp	(revision 87812)
@@ -210,5 +210,4 @@
     AssertCompileMemberAlignment(VM, tm.s, 32);
     AssertCompile(sizeof(pVM->tm.s) <= sizeof(pVM->tm.padding));
-    AssertCompileMemberAlignment(TM, TimerCritSect, 8);
     AssertCompileMemberAlignment(TM, VirtualSyncLock, 8);
 
@@ -217,4 +216,7 @@
      */
     pVM->tm.s.idTimerCpu = pVM->cCpus - 1; /* The last CPU. */
+
+    int rc = PDMR3CritSectInit(pVM, &pVM->tm.s.VirtualSyncLock, RT_SRC_POS, "TM VirtualSync Lock");
+    AssertLogRelRCReturn(rc, rc);
 
     strcpy(pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].szName,      "virtual");
@@ -231,6 +233,10 @@
         pVM->tm.s.aTimerQueues[i].idxSchedule = UINT32_MAX;
         pVM->tm.s.aTimerQueues[i].idxFreeHint = 1;
-        int rc = PDMR3CritSectRwInit(pVM, &pVM->tm.s.aTimerQueues[i].AllocLock, RT_SRC_POS,
-                                     "TM queue %s", pVM->tm.s.aTimerQueues[i].szName);
+        rc = PDMR3CritSectInit(pVM, &pVM->tm.s.aTimerQueues[i].TimerLock, RT_SRC_POS,
+                               "TM %s queue timer lock", pVM->tm.s.aTimerQueues[i].szName);
+        AssertLogRelRCReturn(rc, rc);
+
+        rc = PDMR3CritSectRwInit(pVM, &pVM->tm.s.aTimerQueues[i].AllocLock, RT_SRC_POS,
+                                 "TM %s queue alloc lock", pVM->tm.s.aTimerQueues[i].szName);
         AssertLogRelRCReturn(rc, rc);
     }
@@ -249,5 +255,5 @@
 
     RTHCPHYS HCPhysGIP;
-    int rc = SUPR3GipGetPhys(&HCPhysGIP);
+    rc = SUPR3GipGetPhys(&HCPhysGIP);
     AssertMsgRCReturn(rc, ("Failed to get GIP physical address!\n"), rc);
 
@@ -305,14 +311,4 @@
     AssertRelease(pVM->tm.s.VirtualGetRawDataR0.pu64Prev);
     /* The rest is done in TMR3InitFinalize() since it's too early to call PDM. */
-
-    /*
-     * Init the locks.
-     */
-    rc = PDMR3CritSectInit(pVM, &pVM->tm.s.TimerCritSect, RT_SRC_POS, "TM Timer Lock");
-    if (RT_FAILURE(rc))
-        return rc;
-    rc = PDMR3CritSectInit(pVM, &pVM->tm.s.VirtualSyncLock, RT_SRC_POS, "TM VirtualSync Lock");
-    if (RT_FAILURE(rc))
-        return rc;
 
     /*
@@ -699,5 +695,11 @@
     STAM_REL_REG(     pVM,(void*)&pVM->tm.s.offVirtualSync,               STAMTYPE_U64, "/TM/VirtualSync/CurrentOffset",               STAMUNIT_NS, "The current offset. (subtract GivenUp to get the lag)");
     STAM_REL_REG_USED(pVM,(void*)&pVM->tm.s.offVirtualSyncGivenUp,        STAMTYPE_U64, "/TM/VirtualSync/GivenUp",                     STAMUNIT_NS, "Nanoseconds of the 'CurrentOffset' that's been given up and won't ever be attempted caught up with.");
-    STAM_REL_REG(     pVM,(void*)&pVM->tm.s.uMaxHzHint,                   STAMTYPE_U32, "/TM/MaxHzHint",                               STAMUNIT_HZ, "Max guest timer frequency hint.");
+    STAM_REL_REG(     pVM,(void*)&pVM->tm.s.HzHint.s.uMax,                STAMTYPE_U32, "/TM/MaxHzHint",                               STAMUNIT_HZ, "Max guest timer frequency hint.");
+    for (uint32_t i = 0; i < RT_ELEMENTS(pVM->tm.s.aTimerQueues); i++)
+    {
+        rc = STAMR3RegisterF(pVM, (void *)&pVM->tm.s.aTimerQueues[i].uMaxHzHint, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_HZ,
+                             "", "/TM/MaxHzHint/%s", pVM->tm.s.aTimerQueues[i].szName);
+        AssertRC(rc);
+    }
 
 #ifdef VBOX_WITH_STATISTICS
@@ -709,7 +711,7 @@
     STAM_REG_USED(pVM,(void *)&pVM->tm.s.VirtualGetRawDataRC.cUpdateRaces,STAMTYPE_U32, "/TM/RC/cUpdateRaces",                 STAMUNIT_OCCURENCES, "Thread races when updating the previous timestamp.");
     STAM_REG(pVM, &pVM->tm.s.StatDoQueues,                            STAMTYPE_PROFILE, "/TM/DoQueues",                    STAMUNIT_TICKS_PER_CALL, "Profiling timer TMR3TimerQueuesDo.");
-    STAM_REG(pVM, &pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL],      STAMTYPE_PROFILE_ADV, "/TM/DoQueues/Virtual",            STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual clock queue.");
-    STAM_REG(pVM, &pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], STAMTYPE_PROFILE_ADV, "/TM/DoQueues/VirtualSync",        STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual sync clock queue.");
-    STAM_REG(pVM, &pVM->tm.s.aStatDoQueues[TMCLOCK_REAL],         STAMTYPE_PROFILE_ADV, "/TM/DoQueues/Real",               STAMUNIT_TICKS_PER_CALL, "Time spent on the real clock queue.");
+    STAM_REG(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].StatDo,    STAMTYPE_PROFILE, "/TM/DoQueues/Virtual",            STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual clock queue.");
+    STAM_REG(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC].StatDo,STAMTYPE_PROFILE,"/TM/DoQueues/VirtualSync",        STAMUNIT_TICKS_PER_CALL, "Time spent on the virtual sync clock queue.");
+    STAM_REG(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_REAL].StatDo,       STAMTYPE_PROFILE, "/TM/DoQueues/Real",               STAMUNIT_TICKS_PER_CALL, "Time spent on the real clock queue.");
 
     STAM_REG(pVM, &pVM->tm.s.StatPoll,                                STAMTYPE_COUNTER, "/TM/Poll",                            STAMUNIT_OCCURENCES, "TMTimerPoll calls.");
@@ -1212,5 +1214,4 @@
     LogFlow(("TMR3Reset:\n"));
     VM_ASSERT_EMT(pVM);
-    TM_LOCK_TIMERS(pVM);
 
     /*
@@ -1239,6 +1240,11 @@
      * Process the queues.
      */
-    for (int i = 0; i < TMCLOCK_MAX; i++)
-        tmTimerQueueSchedule(pVM, &pVM->tm.s.aTimerQueues[i], &pVM->tm.s.aTimerQueues[i]);
+    for (uint32_t idxQueue = 0; idxQueue < RT_ELEMENTS(pVM->tm.s.aTimerQueues); idxQueue++)
+    {
+        PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[idxQueue];
+        PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
+        tmTimerQueueSchedule(pVM, pQueue, pQueue);
+        PDMCritSectLeave(&pQueue->TimerLock);
+    }
 #ifdef VBOX_STRICT
     tmTimerQueuesSanityChecks(pVM, "TMR3Reset");
@@ -1292,6 +1298,4 @@
         pVCpu->tm.s.u64TSCLastSeen = 0;
     }
-
-    TM_UNLOCK_TIMERS(pVM);
 }
 
@@ -1693,7 +1697,5 @@
 
 #ifdef VBOX_STRICT
-    TM_LOCK_TIMERS(pVM);
     tmTimerQueuesSanityChecks(pVM, "tmR3TimerCreate");
-    TM_UNLOCK_TIMERS(pVM);
 #endif
 
@@ -1900,5 +1902,6 @@
      */
     PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED);
-    TM_LOCK_TIMERS(pVM);
+    PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
+
     for (int cRetries = 1000;; cRetries--)
     {
@@ -1937,5 +1940,5 @@
             case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:
                 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->szName));
-                TM_UNLOCK_TIMERS(pVM);
+                PDMCritSectLeave(&pQueue->TimerLock);
                 PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
 
@@ -1946,5 +1949,5 @@
 
                 PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED);
-                TM_LOCK_TIMERS(pVM);
+                PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
                 continue;
 
@@ -1954,5 +1957,5 @@
             case TMTIMERSTATE_FREE:
             case TMTIMERSTATE_DESTROY:
-                TM_UNLOCK_TIMERS(pVM);
+                PDMCritSectLeave(&pQueue->TimerLock);
                 PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
                 AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE);
@@ -1960,5 +1963,5 @@
             default:
                 AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, pTimer->szName));
-                TM_UNLOCK_TIMERS(pVM);
+                PDMCritSectLeave(&pQueue->TimerLock);
                 PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
                 return VERR_TM_UNKNOWN_STATE;
@@ -1974,5 +1977,5 @@
             break;
         AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->szName));
-        TM_UNLOCK_TIMERS(pVM);
+        PDMCritSectLeave(&pQueue->TimerLock);
         PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
 
@@ -1981,5 +1984,5 @@
 
         PDMCritSectRwEnterExcl(&pQueue->AllocLock, VERR_IGNORED);
-        TM_LOCK_TIMERS(pVM);
+        PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
     }
 
@@ -2038,5 +2041,5 @@
     tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy");
 #endif
-    TM_UNLOCK_TIMERS(pVM);
+    PDMCritSectLeave(&pQueue->TimerLock);
     PDMCritSectRwLeaveExcl(&pQueue->AllocLock);
     return VINF_SUCCESS;
@@ -2324,5 +2327,4 @@
     Assert(!pVM->tm.s.fRunningQueues);
     ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, true);
-    TM_LOCK_TIMERS(pVM);
 
     /*
@@ -2331,11 +2333,15 @@
     AssertCompile(TMCLOCK_MAX == 4);
 
-    /* TMCLOCK_VIRTUAL_SYNC (see also TMR3VirtualSyncFF) */
-    STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], s1);
+    /*
+     * TMCLOCK_VIRTUAL_SYNC (see also TMR3VirtualSyncFF)
+     */
+    PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC];
+    STAM_PROFILE_START(&pQueue->StatDo, s1);
+    PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
     PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
     ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, true);
     VMCPU_FF_CLEAR(pVCpuDst, VMCPU_FF_TIMER);   /* Clear the FF once we started working for real. */
 
-    Assert(pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL_SYNC].idxSchedule == UINT32_MAX);
+    Assert(pQueue->idxSchedule == UINT32_MAX);
     tmR3TimerQueueRunVirtualSync(pVM);
     if (pVM->tm.s.fVirtualSyncTicking) /** @todo move into tmR3TimerQueueRunVirtualSync - FIXME */
@@ -2344,28 +2350,39 @@
     ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false);
     PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
-    STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL_SYNC], s1);
-
-    /* TMCLOCK_VIRTUAL */
-    STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL], s2);
-    if (pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].idxSchedule != UINT32_MAX)
-        tmTimerQueueSchedule(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL], &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL]);
-    tmR3TimerQueueRun(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL]);
-    STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_VIRTUAL], s2);
-
-    /* TMCLOCK_TSC */
+    PDMCritSectLeave(&pQueue->TimerLock);
+    STAM_PROFILE_STOP(&pQueue->StatDo, s1);
+
+    /*
+     * TMCLOCK_VIRTUAL
+     */
+    pQueue = &pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL];
+    STAM_PROFILE_START(&pQueue->StatDo, s2);
+    PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
+    if (pQueue->idxSchedule != UINT32_MAX)
+        tmTimerQueueSchedule(pVM, pQueue, pQueue);
+    tmR3TimerQueueRun(pVM, pQueue);
+    PDMCritSectLeave(&pQueue->TimerLock);
+    STAM_PROFILE_STOP(&pQueue->StatDo, s2);
+
+    /*
+     * TMCLOCK_TSC
+     */
     Assert(pVM->tm.s.aTimerQueues[TMCLOCK_TSC].idxActive == UINT32_MAX); /* not used */
 
-    /* TMCLOCK_REAL */
-    STAM_PROFILE_ADV_START(&pVM->tm.s.aStatDoQueues[TMCLOCK_REAL], s3);
-    if (pVM->tm.s.aTimerQueues[TMCLOCK_REAL].idxSchedule != UINT32_MAX)
-        tmTimerQueueSchedule(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_REAL], &pVM->tm.s.aTimerQueues[TMCLOCK_REAL]);
-    tmR3TimerQueueRun(pVM, &pVM->tm.s.aTimerQueues[TMCLOCK_REAL]);
-    STAM_PROFILE_ADV_STOP(&pVM->tm.s.aStatDoQueues[TMCLOCK_REAL], s3);
+    /*
+     * TMCLOCK_REAL
+     */
+    pQueue = &pVM->tm.s.aTimerQueues[TMCLOCK_REAL];
+    STAM_PROFILE_START(&pQueue->StatDo, s3);
+    PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
+    if (pQueue->idxSchedule != UINT32_MAX)
+        tmTimerQueueSchedule(pVM, pQueue, pQueue);
+    tmR3TimerQueueRun(pVM, pQueue);
+    PDMCritSectLeave(&pQueue->TimerLock);
+    STAM_PROFILE_STOP(&pQueue->StatDo, s3);
 
 #ifdef VBOX_STRICT
     /* check that we didn't screw up. */
-    TM_LOCK_TIMERS(pVM);
     tmTimerQueuesSanityChecks(pVM, "TMR3TimerQueuesDo");
-    TM_UNLOCK_TIMERS(pVM);
 #endif
 
@@ -2373,5 +2390,4 @@
     Log2(("TMR3TimerQueuesDo: returns void\n"));
     ASMAtomicWriteBool(&pVM->tm.s.fRunningQueues, false);
-    TM_UNLOCK_TIMERS(pVM);
     STAM_PROFILE_STOP(&pVM->tm.s.StatDoQueues, a);
 }
@@ -2649,6 +2665,6 @@
         if (fRc && pTimer->uHzHint)
         {
-            if (pTimer->uHzHint >= pVM->tm.s.uMaxHzHint)
-                ASMAtomicWriteBool(&pVM->tm.s.fHzHintNeedsUpdating, true);
+            if (pTimer->uHzHint >= pQueue->uMaxHzHint)
+                ASMAtomicOrU64(&pVM->tm.s.HzHint.u64Combined, RT_BIT_32(TMCLOCK_VIRTUAL_SYNC) | RT_BIT_32(TMCLOCK_VIRTUAL_SYNC + 16));
             pTimer->uHzHint = 0;
         }
@@ -2825,5 +2841,5 @@
 
             /* try run it. */
-            TM_LOCK_TIMERS(pVM);
+            PDMCritSectEnter(&pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].TimerLock, VERR_IGNORED);
             PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED);
             if (pVM->tm.s.fVirtualSyncTicking)
@@ -2841,7 +2857,7 @@
                 ASMAtomicWriteBool(&pVM->tm.s.fRunningVirtualSyncQueue, false);
             }
+            PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
             STAM_PROFILE_STOP(&pVM->tm.s.StatVirtualSyncFF, a); /* before the unlock! */
-            PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
-            TM_UNLOCK_TIMERS(pVM);
+            PDMCritSectLeave(&pVM->tm.s.aTimerQueues[TMCLOCK_VIRTUAL].TimerLock);
         }
     }
@@ -3152,13 +3168,11 @@
 {
     VMCPU_ASSERT_EMT(pVCpu);
+    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */
 
     /*
      * The shared virtual clock (includes virtual sync which is tied to it).
      */
-    TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
     int rc = tmVirtualPauseLocked(pVM);
-    TM_UNLOCK_TIMERS(pVM);
-    if (RT_FAILURE(rc))
-        return rc;
+    AssertRCReturnStmt(rc, PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock), rc);
 
     /*
@@ -3168,9 +3182,6 @@
     if (!pVM->tm.s.fTSCTiedToExecution)
     {
-        TM_LOCK_TIMERS(pVM);    /* Exploit the timer lock for synchronization. */
         rc = tmCpuTickPauseLocked(pVM, pVCpu);
-        TM_UNLOCK_TIMERS(pVM);
-        if (RT_FAILURE(rc))
-            return rc;
+        AssertRCReturnStmt(rc, PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock), rc);
     }
 
@@ -3198,4 +3209,5 @@
 #endif
 
+    PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
     return VINF_SUCCESS;
 }
@@ -3213,5 +3225,5 @@
 {
     VMCPU_ASSERT_EMT(pVCpu);
-    int rc;
+    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */
 
 #ifndef VBOX_WITHOUT_NS_ACCOUNTING
@@ -3233,9 +3245,6 @@
     if (!pVM->tm.s.fTSCTiedToExecution)
     {
-        TM_LOCK_TIMERS(pVM);    /* Exploit the timer lock for synchronization. */
-        rc = tmCpuTickResumeLocked(pVM, pVCpu);
-        TM_UNLOCK_TIMERS(pVM);
-        if (RT_FAILURE(rc))
-            return rc;
+        int rc = tmCpuTickResumeLocked(pVM, pVCpu);
+        AssertRCReturnStmt(rc, PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock), rc);
     }
 
@@ -3243,8 +3252,7 @@
      * The shared virtual clock (includes virtual sync which is tied to it).
      */
-    TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
-    rc = tmVirtualResumeLocked(pVM);
-    TM_UNLOCK_TIMERS(pVM);
-
+    int rc = tmVirtualResumeLocked(pVM);
+
+    PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
     return rc;
 }
@@ -3288,9 +3296,10 @@
  * TM level and make it affect TMR3UTCNow as well! */
 
+    PDMCritSectEnter(&pVM->tm.s.VirtualSyncLock, VERR_IGNORED); /* Paranoia: Exploiting the virtual sync lock here. */
+
     /*
      * If the time is running we'll have to pause it before we can change
      * the warp drive settings.
      */
-    TM_LOCK_TIMERS(pVM);                        /* Paranoia: Exploiting the timer lock here. */
     bool fPaused = !!pVM->tm.s.cVirtualTicking;
     if (fPaused) /** @todo this isn't really working, but wtf. */
@@ -3305,5 +3314,6 @@
     if (fPaused)
         TMR3NotifyResume(pVM, pVCpu);
-    TM_UNLOCK_TIMERS(pVM);
+
+    PDMCritSectLeave(&pVM->tm.s.VirtualSyncLock);
     return VINF_SUCCESS;
 }
@@ -3896,5 +3906,6 @@
         PTMTIMERQUEUE pQueue = &pVM->tm.s.aTimerQueues[idxQueue];
         PDMCritSectRwEnterShared(&pQueue->AllocLock, VERR_IGNORED);
-        TM_LOCK_TIMERS(pVM);
+        PDMCritSectEnter(&pQueue->TimerLock, VERR_IGNORED);
+
         for (PTMTIMERR3 pTimer = tmTimerQueueGetHead(pQueue, pQueue);
              pTimer;
@@ -3914,5 +3925,6 @@
                             pTimer->szName);
         }
-        TM_UNLOCK_TIMERS(pVM);
+
+        PDMCritSectLeave(&pQueue->TimerLock);
         PDMCritSectRwLeaveShared(&pQueue->AllocLock);
     }
Index: /trunk/src/VBox/VMM/include/TMInline.h
===================================================================
--- /trunk/src/VBox/VMM/include/TMInline.h	(revision 87811)
+++ /trunk/src/VBox/VMM/include/TMInline.h	(revision 87812)
@@ -163,4 +163,71 @@
 }
 
+/** @def TMTIMER_HANDLE_TO_VARS_RETURN_EX
+ * Converts a timer handle to a timer pointer, returning @a a_rcRet if the
+ * handle is invalid.
+ *
+ * This defines the following variables:
+ *      - idxQueue: The queue index.
+ *      - pQueueCC: Pointer to the context specific queue data.
+ *      - pTimer:   The timer pointer.
+ *      - idxTimer: The timer index.
+ *
+ * @param   a_pVM           The cross context VM structure.
+ * @param   a_hTimer        The timer handle to translate.
+ * @param   a_rcRet         What to return on failure.
+ *
+ * @note    This macro has no scoping, so careful when using it around
+ *          conditional statements!
+ */
+#ifdef IN_RING3
+# define TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, a_rcRet) \
+        uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \
+                                 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \
+        AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \
+        PTMTIMERQUEUE const pQueue = &(a_pVM)->tm.s.aTimerQueues[idxQueue]; \
+        PTMTIMERQUEUE const pQueueCC = pQueue; RT_NOREF(pQueueCC); \
+        \
+        uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \
+        AssertReturn(idxQueue < pQueue->cTimersAlloc, a_rcRet); \
+        \
+        PTMTIMER const pTimer = &pQueue->paTimers[idxTimer]; \
+        AssertReturn(pTimer->hSelf == a_hTimer, a_rcRet)
+#else
+# define TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, a_rcRet) \
+        uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \
+                                 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \
+        AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \
+        AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \
+        PTMTIMERQUEUE const   pQueue   = &(a_pVM)->tm.s.aTimerQueues[idxQueue]; RT_NOREF(pQueue); \
+        PTMTIMERQUEUER0 const pQueueCC = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue]; \
+        \
+        uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \
+        AssertReturn(idxQueue < pQueueCC->cTimersAlloc, a_rcRet); \
+        \
+        PTMTIMER const pTimer = &pQueueCC->paTimers[idxTimer]; \
+        AssertReturn(pTimer->hSelf == a_hTimer, a_rcRet); \
+        Assert(pTimer->fFlags & TMTIMER_FLAGS_RING0); \
+        Assert(VM_IS_EMT(pVM))
+#endif
+
+
+/** @def TMTIMER_HANDLE_TO_VARS_RETURN_EX
+ * Converts a timer handle to a timer pointer, returning VERR_INVALID_HANDLE if
+ * the handle is invalid.
+ *
+ * This defines the following variables:
+ *      - idxQueue: The queue index.
+ *      - pQueueCC: Pointer to the context specific queue data.
+ *      - pTimer:   The timer pointer.
+ *      - idxTimer: The timer index.
+ *
+ * @param   a_pVM       The cross context VM structure.
+ * @param   a_hTimer    The timer handle to translate.
+ *
+ * @note    This macro has no scoping, so careful when using it around
+ *          conditional statements!
+ */
+#define TMTIMER_HANDLE_TO_VARS_RETURN(a_pVM, a_hTimer) TMTIMER_HANDLE_TO_VARS_RETURN_EX(a_pVM, a_hTimer, VERR_INVALID_HANDLE)
+
 
 /** @def TMTIMER_HANDLE_TO_PTR_RETURN_EX
Index: /trunk/src/VBox/VMM/include/TMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/TMInternal.h	(revision 87811)
+++ /trunk/src/VBox/VMM/include/TMInternal.h	(revision 87812)
@@ -284,6 +284,15 @@
     bool                    fCannotGrow;
     /** Align on 64-byte boundrary. */
-    bool                    afAlignment[7];
-    /** Lock serializing timer allocation and deallocation. */
+    bool                    afAlignment1[7];
+    /** Time spent doing scheduling and timer callbacks. */
+    STAMPROFILE             StatDo;
+    /** The current max timer Hz hint. */
+    uint32_t volatile       uMaxHzHint;
+    uint32_t                u64Alignment2[7];
+    /** Lock serializing the active timer list and associated work. */
+    PDMCRITSECT             TimerLock;
+    /** Lock serializing timer allocation and deallocation.
+     * @note This may be used in read-mode all over the place if we later
+     *       implement runtime array growing. */
     PDMCRITSECTRW           AllocLock;
 } TMTIMERQUEUE;
@@ -391,4 +400,8 @@
 typedef struct TM
 {
+    /** Timer queues for the different clock types.
+     * @note is first in the structure to ensure cache-line alignment.  */
+    TMTIMERQUEUE                aTimerQueues[TMCLOCK_MAX];
+
     /** The current TSC mode of the VM.
      *  Config variable: Mode (string). */
@@ -496,10 +509,16 @@
     }                           aVirtualSyncCatchUpPeriods[TM_MAX_CATCHUP_PERIODS];
 
-    /** The current max timer Hz hint. */
-    uint32_t volatile           uMaxHzHint;
-    /** Whether to recalulate the HzHint next time its queried. */
-    bool volatile               fHzHintNeedsUpdating;
-    /** Alignment */
-    bool                        afAlignment2[3];
+    union
+    {
+        /** Combined value for updating. */
+        uint64_t volatile       u64Combined;
+        struct
+        {
+            /** Bitmap indicating which timer queues needs their uMaxHzHint updated. */
+            uint32_t volatile   bmNeedsUpdating;
+            /** The current max timer Hz hint. */
+            uint32_t volatile   uMax;
+        } s;
+    } HzHint;
     /** @cfgm{/TM/HostHzMax, uint32_t, Hz, 0, UINT32_MAX, 20000}
      * The max host Hz frequency hint returned by TMCalcHostTimerFrequency.  */
@@ -537,11 +556,9 @@
     R3PTRTYPE(char *)           pszAlignment2b;
 
-    /** Timer queues for the different clock types. */
-    TMTIMERQUEUE                aTimerQueues[TMCLOCK_MAX];
-
     /** Pointer to our RC mapping of the GIP. */
     RCPTRTYPE(void *)           pvGIPRC;
     /** Pointer to our R3 mapping of the GIP. */
     R3PTRTYPE(void *)           pvGIPR3;
+
 
     /** The schedule timer timer handle (runtime timer).
@@ -560,6 +577,4 @@
     bool                        afAlignment3[2];
 
-    /** Lock serializing access to the timer lists. */
-    PDMCRITSECT                 TimerCritSect;
     /** Lock serializing access to the VirtualSync clock and the associated
      * timer queue. */
@@ -572,5 +587,4 @@
      * @{ */
     STAMPROFILE                 StatDoQueues;
-    STAMPROFILEADV              aStatDoQueues[TMCLOCK_MAX];
     /** @} */
     /** tmSchedule
@@ -836,37 +850,5 @@
 DECLCALLBACK(DECLEXPORT(uint64_t))  tmVirtualNanoTSRediscover(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
 DECLCALLBACK(DECLEXPORT(uint64_t))  tmVirtualNanoTSBadCpuIndex(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra,
-                                                               uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
-
-/**
- * Try take the timer lock, wait in ring-3 return VERR_SEM_BUSY in R0/RC.
- *
- * @retval  VINF_SUCCESS on success (always in ring-3).
- * @retval  VERR_SEM_BUSY in RC and R0 if the semaphore is busy.
- *
- * @param   a_pVM       Pointer to the VM.
- *
- * @remarks The virtual sync timer queue requires the virtual sync lock.
- */
-#define TM_LOCK_TIMERS(a_pVM)       PDMCritSectEnter(&(a_pVM)->tm.s.TimerCritSect, VERR_SEM_BUSY)
-
-/**
- * Try take the timer lock, no waiting.
- *
- * @retval  VINF_SUCCESS on success.
- * @retval  VERR_SEM_BUSY if busy.
- *
- * @param   a_pVM       Pointer to the VM.
- *
- * @remarks The virtual sync timer queue requires the virtual sync lock.
- */
-#define TM_TRY_LOCK_TIMERS(a_pVM)   PDMCritSectTryEnter(&(a_pVM)->tm.s.TimerCritSect)
-
-/** Lock the timers (sans the virtual sync queue). */
-#define TM_UNLOCK_TIMERS(a_pVM)     do { PDMCritSectLeave(&(a_pVM)->tm.s.TimerCritSect); } while (0)
-
-/** Checks that the caller owns the timer lock.  */
-#define TM_ASSERT_TIMER_LOCK_OWNERSHIP(a_pVM) \
-    Assert(PDMCritSectIsOwner(&(a_pVM)->tm.s.TimerCritSect))
-
+                                                              uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
 /** @} */
 
@@ -874,3 +856,2 @@
 
 #endif /* !VMM_INCLUDED_SRC_include_TMInternal_h */
-
Index: /trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp	(revision 87811)
+++ /trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp	(revision 87812)
@@ -348,5 +348,5 @@
 
     /* TM */
-    CHECK_MEMBER_ALIGNMENT(TM, TimerCritSect, sizeof(uintptr_t));
+    CHECK_MEMBER_ALIGNMENT(TM, aTimerQueues, 64);
     CHECK_MEMBER_ALIGNMENT(TM, VirtualSyncLock, sizeof(uintptr_t));
 
