Index: trunk/src/VBox/VMM/VMMAll/TMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/TMAll.cpp	(revision 19628)
+++ trunk/src/VBox/VMM/VMMAll/TMAll.cpp	(revision 19660)
@@ -188,12 +188,18 @@
         tmUnlock(pVM);
     }
-    else if (!VM_FF_ISSET(pVM, VM_FF_TIMER))  /**@todo only do this when arming the timer. */
-    {
-        STAM_COUNTER_INC(&pVM->tm.s.StatScheduleSetFF);
-        VM_FF_SET(pVM, VM_FF_TIMER);
+    else
+    {
+        /** @todo FIXME: don't use FF for scheduling! */
+        PVMCPU pVCpuDst = &pVM->aCpus[pVM->tm.s.idTimerCpu];
+        if (!VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER))  /**@todo only do this when arming the timer. */
+        {
+            Log5(("TMAll(%u): FF: 0 -> 1\n", __LINE__));
+            VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
 #ifdef IN_RING3
-        REMR3NotifyTimerPending(pVM);
-        VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
-#endif
+            REMR3NotifyTimerPending(pVM, pVCpuDst);
+            VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
+#endif
+            STAM_COUNTER_INC(&pVM->tm.s.StatScheduleSetFF);
+        }
     }
 }
@@ -268,23 +274,32 @@
  * This function is called before FFs are checked in the inner execution EM loops.
  *
- * @returns Virtual timer ticks to the next event.
+ * @returns Virtual timer ticks to the next event. (I.e. 0 means that an timer
+ *          has expired or some important rescheduling is pending.)
  * @param   pVM         Pointer to the shared VM structure.
+ * @param   pVCpu       Pointer to the shared VMCPU structure of the caller.
  * @thread  The emulation thread.
  */
-VMMDECL(uint64_t) TMTimerPoll(PVM pVM)
-{
-    int rc = tmLock(pVM); /* play safe for now */
+VMMDECL(uint64_t) TMTimerPoll(PVM pVM, PVMCPU pVCpu)
+{
+    static const uint64_t   s_u64OtherRet = 500000000; /* 500 ms for non-timer EMTs. */
+    PVMCPU  pVCpuDst = &pVM->aCpus[pVM->tm.s.idTimerCpu];
+    STAM_COUNTER_INC(&pVM->tm.s.StatPoll);
 
     /*
-     * Return straight away if the timer FF is already set.
+     * Return straight away if the timer FF is already set ...
      */
-    if (VM_FF_ISSET(pVM, VM_FF_TIMER))
+    if (VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER))
     {
         STAM_COUNTER_INC(&pVM->tm.s.StatPollAlreadySet);
-#ifndef IN_RING3
-        if (RT_SUCCESS(rc))
-#endif
-            tmUnlock(pVM);
-        return 0;
+        return pVCpu == pVCpuDst ? 0 : s_u64OtherRet;
+    }
+
+    /*
+     * ... or if timers are being run.
+     */
+    if (pVM->tm.s.fRunningQueues)
+    {
+        STAM_COUNTER_INC(&pVM->tm.s.StatPollRunning);
+        return s_u64OtherRet;
     }
 
@@ -292,11 +307,12 @@
      * Get current time and check the expire times of the two relevant queues.
      */
-    const uint64_t u64Now = TMVirtualGet(pVM);
+    int             rc     = tmLock(pVM); /** @todo FIXME: Stop playing safe here... */
+    const uint64_t  u64Now = TMVirtualGetNoCheck(pVM);
 
     /*
      * TMCLOCK_VIRTUAL
      */
-    const uint64_t u64Expire1 = pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire;
-    const int64_t i64Delta1 = u64Expire1 - u64Now;
+    const uint64_t  u64Expire1 = pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire;
+    const int64_t   i64Delta1  = u64Expire1 - u64Now;
     if (i64Delta1 <= 0)
     {
@@ -307,9 +323,10 @@
 #endif
             tmUnlock(pVM);
-        VM_FF_SET(pVM, VM_FF_TIMER);
+        Log5(("TMAll(%u): FF: %d -> 1\n", __LINE__, VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
+        VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
 #ifdef IN_RING3
-        REMR3NotifyTimerPending(pVM);
-#endif
-        return 0;
+        REMR3NotifyTimerPending(pVM, pVCpuDst);
+#endif
+        return pVCpu == pVCpuDst ? 0 : s_u64OtherRet;
     }
 
@@ -345,4 +362,13 @@
     if (i64Delta2 <= 0)
     {
+        if (    !pVM->tm.s.fRunningQueues
+            &&  !VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER))
+        {
+            Log5(("TMAll(%u): FF: %d -> 1\n", __LINE__, VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
+            VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
+#ifdef IN_RING3
+            REMR3NotifyTimerPending(pVM, pVCpuDst);
+#endif
+        }
         STAM_COUNTER_INC(&pVM->tm.s.StatPollVirtualSync);
 #ifndef IN_RING3
@@ -351,9 +377,5 @@
             tmUnlock(pVM);
         LogFlow(("TMTimerPoll: expire2=%RU64 <= now=%RU64\n", u64Expire2, u64Now));
-        VM_FF_SET(pVM, VM_FF_TIMER);
-#ifdef IN_RING3
-        REMR3NotifyTimerPending(pVM);
-#endif
-        return 0;
+        return pVCpu == pVCpuDst ? 0 : s_u64OtherRet;
     }
     if (pVM->tm.s.fVirtualSyncCatchUp)
@@ -380,33 +402,44 @@
  *          0 if the next event has already expired.
  * @param   pVM         Pointer to the shared VM structure.
- * @param   pVM         Pointer to the shared VM structure.
+ * @param   pVCpu       Pointer to the shared VMCPU structure of the caller.
  * @param   pu64Delta   Where to store the delta.
  * @thread  The emulation thread.
  */
-VMMDECL(uint64_t) TMTimerPollGIP(PVM pVM, uint64_t *pu64Delta)
-{
-    int rc = tmLock(pVM); /* play safe for now. */
+VMMDECL(uint64_t) TMTimerPollGIP(PVM pVM, PVMCPU pVCpu, uint64_t *pu64Delta)
+{
+    static const uint64_t   s_u64OtherRet = 500000000; /* 500 million GIP ticks for non-timer EMTs. */
+    PVMCPU                  pVCpuDst      = &pVM->aCpus[pVM->tm.s.idTimerCpu];
+    const uint64_t          u64Now        = TMVirtualGetNoCheck(pVM);
+    STAM_COUNTER_INC(&pVM->tm.s.StatPollGIP);
 
     /*
-     * Return straight away if the timer FF is already set.
+     * Return straight away if the timer FF is already set ...
      */
-    if (VM_FF_ISSET(pVM, VM_FF_TIMER))
-    {
-        STAM_COUNTER_INC(&pVM->tm.s.StatPollAlreadySet);
-#ifndef IN_RING3
-        if (RT_SUCCESS(rc))
-#endif
-            tmUnlock(pVM);
-        *pu64Delta = 0;
-        return 0;
+    if (VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER))
+    {
+        STAM_COUNTER_INC(&pVM->tm.s.StatPollGIPAlreadySet);
+        if (pVCpuDst == pVCpu)
+        {
+            *pu64Delta = 0;
+            return 0;
+        }
+        *pu64Delta = s_u64OtherRet;
+        return u64Now + pVM->tm.s.u64VirtualOffset + s_u64OtherRet;
     }
 
     /*
-     * Get current time and check the expire times of the two relevant queues.
+     * ... or if timers are being run.
      */
-    const uint64_t  u64Now = TMVirtualGet(pVM);
+    if (pVM->tm.s.fRunningQueues)
+    {
+        STAM_COUNTER_INC(&pVM->tm.s.StatPollGIPRunning);
+        *pu64Delta = s_u64OtherRet;
+        return u64Now + pVM->tm.s.u64VirtualOffset + s_u64OtherRet;
+    }
+
+    int rc = tmLock(pVM); /** @todo FIXME: Stop playin safe... */
 
     /*
-     * TMCLOCK_VIRTUAL
+     * Check for TMCLOCK_VIRTUAL expiration.
      */
     const uint64_t  u64Expire1 = pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire;
@@ -414,5 +447,10 @@
     if (i64Delta1 <= 0)
     {
-        STAM_COUNTER_INC(&pVM->tm.s.StatPollVirtual);
+        STAM_COUNTER_INC(&pVM->tm.s.StatPollGIPVirtual);
+        Log5(("TMAll(%u): FF: %d -> 1\n", __LINE__, VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
+        VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
+#ifdef IN_RING3
+        REMR3NotifyTimerPending(pVM, pVCpuDst);
+#endif
 #ifndef IN_RING3
         if (RT_SUCCESS(rc))
@@ -420,14 +458,15 @@
             tmUnlock(pVM);
         LogFlow(("TMTimerPoll: expire1=%RU64 <= now=%RU64\n", u64Expire1, u64Now));
-        VM_FF_SET(pVM, VM_FF_TIMER);
-#ifdef IN_RING3
-        REMR3NotifyTimerPending(pVM);
-#endif
-        *pu64Delta = 0;
-        return 0;
+        if (pVCpuDst == pVCpu)
+        {
+            *pu64Delta = 0;
+            return 0;
+        }
+        *pu64Delta = s_u64OtherRet;
+        return u64Now + pVM->tm.s.u64VirtualOffset + s_u64OtherRet;
     }
 
     /*
-     * TMCLOCK_VIRTUAL_SYNC
+     * Check for TMCLOCK_VIRTUAL_SYNC expiration.
      * This isn't quite as stright forward if in a catch-up, not only do
      * we have to adjust the 'now' but when have to adjust the delta as well.
@@ -460,5 +499,14 @@
     if (i64Delta2 <= 0)
     {
-        STAM_COUNTER_INC(&pVM->tm.s.StatPollVirtualSync);
+        if (!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_TIMER))
+        {
+            Log5(("TMAll(%u): FF: 0 -> 1\n", __LINE__));
+            VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER /** @todo poke */);
+#ifdef IN_RING3
+            REMR3NotifyTimerPending(pVM, pVCpuDst);
+#endif
+        }
+        STAM_COUNTER_INC(&pVM->tm.s.StatPollGIPVirtualSync);
+
 #ifndef IN_RING3
         if (RT_SUCCESS(rc))
@@ -466,30 +514,39 @@
             tmUnlock(pVM);
         LogFlow(("TMTimerPoll: expire2=%RU64 <= now=%RU64\n", u64Expire2, u64Now));
-        VM_FF_SET(pVM, VM_FF_TIMER);
-#ifdef IN_RING3
-        REMR3NotifyTimerPending(pVM);
-#endif
-        *pu64Delta = 0;
-        return 0;
+        if (pVCpuDst == pVCpu)
+        {
+            *pu64Delta = 0;
+            return 0;
+        }
+        *pu64Delta = s_u64OtherRet;
+        return u64Now + pVM->tm.s.u64VirtualOffset + s_u64OtherRet;
     }
     if (pVM->tm.s.fVirtualSyncCatchUp)
         i64Delta2 = ASMMultU64ByU32DivByU32(i64Delta2, 100, pVM->tm.s.u32VirtualSyncCatchUpPercentage + 100);
 
-    /*
-     * Return the GIP time of the next event.
-     * This is the reverse of what tmVirtualGetRaw is doing.
-     */
-    STAM_COUNTER_INC(&pVM->tm.s.StatPollMiss);
-    uint64_t u64GipTime = RT_MIN(i64Delta1, i64Delta2);
-    *pu64Delta = u64GipTime;
-    u64GipTime += u64Now + pVM->tm.s.u64VirtualOffset;
-    if (RT_UNLIKELY(!pVM->tm.s.fVirtualWarpDrive))
-    {
-        u64GipTime -= pVM->tm.s.u64VirtualWarpDriveStart; /* the start is GIP time. */
-        u64GipTime *= 100;
-        u64GipTime /= pVM->tm.s.u32VirtualWarpDrivePercentage;
-        u64GipTime += pVM->tm.s.u64VirtualWarpDriveStart;
-    }
-
+    uint64_t u64GipTime;
+    if (pVCpuDst == pVCpu)
+    {
+        /*
+         * Return the GIP time of the next event.
+         * This is the reverse of what tmVirtualGetRaw is doing.
+         */
+        STAM_COUNTER_INC(&pVM->tm.s.StatPollGIPMiss);
+        u64GipTime = RT_MIN(i64Delta1, i64Delta2);
+        *pu64Delta = u64GipTime;
+        u64GipTime += u64Now + pVM->tm.s.u64VirtualOffset;
+        if (RT_UNLIKELY(!pVM->tm.s.fVirtualWarpDrive))
+        {
+            u64GipTime -= pVM->tm.s.u64VirtualWarpDriveStart; /* the start is GIP time. */
+            u64GipTime *= 100;
+            u64GipTime /= pVM->tm.s.u32VirtualWarpDrivePercentage;
+            u64GipTime += pVM->tm.s.u64VirtualWarpDriveStart;
+        }
+    }
+    else
+    {
+        *pu64Delta = s_u64OtherRet;
+        u64GipTime = u64Now + pVM->tm.s.u64VirtualOffset + s_u64OtherRet;
+    }
 #ifndef IN_RING3
     if (RT_SUCCESS(rc))
Index: trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp	(revision 19628)
+++ trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp	(revision 19660)
@@ -330,20 +330,25 @@
          * Use the chance to check for expired timers.
          */
-        if (    fCheckTimers
-            &&  !VM_FF_ISSET(pVM, VM_FF_TIMER)
-            &&  !pVM->tm.s.fRunningQueues
-            &&  (   pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64
-                 || (   pVM->tm.s.fVirtualSyncTicking
-                     && pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire <= u64 - pVM->tm.s.offVirtualSync
+        if (fCheckTimers)
+        {
+            PVMCPU pVCpuDst = &pVM->aCpus[pVM->tm.s.idTimerCpu];
+            if (    !VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER)
+                &&  !pVM->tm.s.fRunningQueues
+                &&  (   pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64
+                     || (   pVM->tm.s.fVirtualSyncTicking
+                         && pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire <= u64 - pVM->tm.s.offVirtualSync
+                        )
                     )
-                )
-           )
-        {
-            VM_FF_SET(pVM, VM_FF_TIMER);
-            STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSetFF);
+                &&  !pVM->tm.s.fRunningQueues
+               )
+            {
+                STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSetFF);
+                Log5(("TMAllVirtual(%u): FF: %d -> 1\n", __LINE__, VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
+                VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
 #ifdef IN_RING3
-            REMR3NotifyTimerPending(pVM);
-            VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
-#endif
+                REMR3NotifyTimerPending(pVM, pVCpuDst);
+                VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
+#endif
+            }
         }
     }
@@ -372,18 +377,17 @@
 
 /**
- * Gets the current TMCLOCK_VIRTUAL time
+ * Gets the current TMCLOCK_VIRTUAL time without checking
+ * timers or anything.
+ *
+ * Meaning, this has no side effect on FFs like TMVirtualGet may have.
  *
  * @returns The timestamp.
- * @param   pVM             VM handle.
- * @param   fCheckTimers    Check timers or not
- *
- * @remark  While the flow of time will never go backwards, the speed of the
- *          progress varies due to inaccurate RTTimeNanoTS and TSC. The latter can be
- *          influenced by power saving (SpeedStep, PowerNow!), while the former
- *          makes use of TSC and kernel timers.
- */
-VMMDECL(uint64_t) TMVirtualGetEx(PVM pVM, bool fCheckTimers)
-{
-    return tmVirtualGet(pVM, fCheckTimers);
+ * @param   pVM     VM handle.
+ *
+ * @remarks See TMVirtualGet.
+ */
+VMMDECL(uint64_t) TMVirtualGetNoCheck(PVM pVM)
+{
+    return tmVirtualGet(pVM, false /*fCheckTimers*/);
 }
 
@@ -397,10 +401,12 @@
  * @thread  EMT.
  */
-VMMDECL(uint64_t) TMVirtualSyncGetEx(PVM pVM, bool fCheckTimers)
-{
-    uint64_t u64;
+DECLINLINE(uint64_t) tmVirtualSyncGetEx(PVM pVM, bool fCheckTimers)
+{
+    STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSync);
+    uint64_t    u64;
+
     if (pVM->tm.s.fVirtualSyncTicking)
     {
-        STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSync);
+        PVMCPU pVCpuDst = &pVM->aCpus[pVM->tm.s.idTimerCpu];
 
         /*
@@ -409,14 +415,17 @@
         Assert(pVM->tm.s.cVirtualTicking);
         u64 = tmVirtualGetRaw(pVM);
-        if (    fCheckTimers
-            &&  !VM_FF_ISSET(pVM, VM_FF_TIMER)
-            &&  pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64)
+        if (fCheckTimers)
         {
-            VM_FF_SET(pVM, VM_FF_TIMER);
+            if (    !VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER)
+                &&  pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64)
+            {
+                Log5(("TMAllVirtual(%u): FF: 0 -> 1\n", __LINE__));
+                VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
 #ifdef IN_RING3
-            REMR3NotifyTimerPending(pVM);
-            VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
-#endif
-            STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSyncSetFF);
+                REMR3NotifyTimerPending(pVM, pVCpuDst);
+                VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM /** @todo |VMNOTIFYFF_FLAGS_POKE*/);
+#endif
+                STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSyncSetFF);
+            }
         }
 
@@ -490,18 +499,20 @@
         {
             u64 = u64Expire;
-            int rc = tmTryLock(pVM); /** @todo SMP: Here be dragons... Need to get back to this later. */
+            int rc = tmTryLock(pVM); /** @todo SMP: Here be dragons... Need to get back to this later. FIXME */
             if (RT_SUCCESS(rc))
             {
                 ASMAtomicXchgU64(&pVM->tm.s.u64VirtualSync, u64);
                 ASMAtomicXchgBool(&pVM->tm.s.fVirtualSyncTicking, false);
+                VM_FF_SET(pVM, VM_FF_TM_VIRTUAL_SYNC);
                 tmUnlock(pVM);
             }
             if (    fCheckTimers
-                &&  !VM_FF_ISSET(pVM, VM_FF_TIMER))
+                &&  !VMCPU_FF_ISSET(pVCpuDst, VMCPU_FF_TIMER))
             {
-                VM_FF_SET(pVM, VM_FF_TIMER);
+                Log5(("TMAllVirtual(%u): FF: %d -> 1\n", __LINE__, VMCPU_FF_ISPENDING(pVCpuDst, VMCPU_FF_TIMER)));
+                VMCPU_FF_SET(pVCpuDst, VMCPU_FF_TIMER);
 #ifdef IN_RING3
-                REMR3NotifyTimerPending(pVM);
-                VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
+                REMR3NotifyTimerPending(pVM, pVCpuDst);
+                VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
 #endif
                 STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSyncSetFF);
@@ -516,25 +527,6 @@
         u64 = pVM->tm.s.u64VirtualSync;
 
-        /*
-         * If it looks like a halt caused by pending timers, make sure the FF is raised.
-         * This is a safeguard against timer queue runner leaving the virtual sync clock stopped.
-         */
-        if (    fCheckTimers
-            &&  pVM->tm.s.cVirtualTicking
-            &&  !VM_FF_ISSET(pVM, VM_FF_TIMER))
-        {
-            const uint64_t u64Expire = pVM->tm.s.CTX_SUFF(paTimerQueues)[TMCLOCK_VIRTUAL_SYNC].u64Expire;
-            if (u64 >= u64Expire)
-            {
-                VM_FF_SET(pVM, VM_FF_TIMER);
-#ifdef IN_RING3
-                REMR3NotifyTimerPending(pVM);
-                VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
-#endif
-                STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGetSyncSetFF);
-                Log4(("TM: %RU64/%RU64: exp tmr=>ff (!)\n", u64, pVM->tm.s.offVirtualSync - pVM->tm.s.offVirtualSyncGivenUp));
-            }
-        }
-    }
+    }
+
     return u64;
 }
@@ -547,8 +539,39 @@
  * @param   pVM             VM handle.
  * @thread  EMT.
+ * @remarks May set the timer and virtual sync FFs.
  */
 VMMDECL(uint64_t) TMVirtualSyncGet(PVM pVM)
 {
-    return TMVirtualSyncGetEx(pVM, true /* check timers */);
+    return tmVirtualSyncGetEx(pVM, true /* check timers */);
+}
+
+
+/**
+ * Gets the current TMCLOCK_VIRTUAL_SYNC time without checking timers running on
+ * TMCLOCK_VIRTUAL.
+ *
+ * @returns The timestamp.
+ * @param   pVM             VM handle.
+ * @thread  EMT.
+ * @remarks May set the timer and virtual sync FFs.
+ */
+VMMDECL(uint64_t) TMVirtualSyncGetNoCheck(PVM pVM)
+{
+    return tmVirtualSyncGetEx(pVM, false /* check timers */);
+}
+
+
+/**
+ * Gets the current TMCLOCK_VIRTUAL_SYNC time.
+ *
+ * @returns The timestamp.
+ * @param   pVM     VM handle.
+ * @param   fCheckTimers    Check timers on the virtual clock or not.
+ * @thread  EMT.
+ * @remarks May set the timer and virtual sync FFs.
+ */
+VMMDECL(uint64_t) TMVirtualSyncGetEx(PVM pVM, bool fCheckTimers)
+{
+    return tmVirtualSyncGetEx(pVM, fCheckTimers);
 }
 
