Index: trunk/include/VBox/sup.h
===================================================================
--- trunk/include/VBox/sup.h	(revision 54269)
+++ trunk/include/VBox/sup.h	(revision 54270)
@@ -437,4 +437,6 @@
     /** The TSC of the cores are non-stop and have a constant frequency. */
     SUPGIPMODE_INVARIANT_TSC,
+    /** End of valid GIP mode values (exclusive). */
+    SUPGIPMODE_END,
     /** The usual 32-bit hack. */
     SUPGIPMODE_32BIT_HACK = 0x7fffffff
Index: trunk/include/iprt/mangling.h
===================================================================
--- trunk/include/iprt/mangling.h	(revision 54269)
+++ trunk/include/iprt/mangling.h	(revision 54270)
@@ -1719,24 +1719,40 @@
 # define RTTimeMilliTS                                  RT_MANGLER(RTTimeMilliTS)
 # define RTTimeNanoTS                                   RT_MANGLER(RTTimeNanoTS)
-# define RTTimeNanoTSLegacyAsync                        RT_MANGLER(RTTimeNanoTSLegacyAsync)
-# define RTTimeNanoTSLegacyAsync_EndProc                RT_MANGLER(RTTimeNanoTSLegacyAsync_EndProc)
-# define RTTimeNanoTSLegacyInvariantNoDelta             RT_MANGLER(RTTimeNanoTSLegacyInvariantNoDelta)
-# define RTTimeNanoTSLegacyInvariantNoDelta_EndProc     RT_MANGLER(RTTimeNanoTSLegacyInvariantNoDelta_EndProc)
-# define RTTimeNanoTSLegacyInvariantWithDelta           RT_MANGLER(RTTimeNanoTSLegacyInvariantWithDelta)
-# define RTTimeNanoTSLegacyInvariantWithDelta_EndProc   RT_MANGLER(RTTimeNanoTSLegacyInvariantWithDelta_EndProc)
-# define RTTimeNanoTSLegacySyncNoDelta                  RT_MANGLER(RTTimeNanoTSLegacySyncNoDelta)
-# define RTTimeNanoTSLegacySyncNoDelta_EndProc          RT_MANGLER(RTTimeNanoTSLegacySyncNoDelta_EndProc)
-# define RTTimeNanoTSLegacySyncWithDelta                RT_MANGLER(RTTimeNanoTSLegacySyncWithDelta)
-# define RTTimeNanoTSLegacySyncWithDelta_EndProc        RT_MANGLER(RTTimeNanoTSLegacySyncWithDelta_EndProc)
-# define RTTimeNanoTSLFenceAsync                        RT_MANGLER(RTTimeNanoTSLFenceAsync)
-# define RTTimeNanoTSLFenceAsync_EndProc                RT_MANGLER(RTTimeNanoTSLFenceAsync_EndProc)
-# define RTTimeNanoTSLFenceInvariantNoDelta             RT_MANGLER(RTTimeNanoTSLFenceInvariantNoDelta)
-# define RTTimeNanoTSLFenceInvariantNoDelta_EndProc     RT_MANGLER(RTTimeNanoTSLFenceInvariantNoDelta_EndProc)
-# define RTTimeNanoTSLFenceInvariantWithDelta           RT_MANGLER(RTTimeNanoTSLFenceInvariantWithDelta)
-# define RTTimeNanoTSLFenceInvariantWithDelta_EndProc   RT_MANGLER(RTTimeNanoTSLFenceInvariantWithDelta_EndProc)
-# define RTTimeNanoTSLFenceSyncNoDelta                  RT_MANGLER(RTTimeNanoTSLFenceSyncNoDelta)
-# define RTTimeNanoTSLFenceSyncNoDelta_EndProc          RT_MANGLER(RTTimeNanoTSLFenceSyncNoDelta_EndProc)
-# define RTTimeNanoTSLFenceSyncWithDelta                RT_MANGLER(RTTimeNanoTSLFenceSyncWithDelta)
-# define RTTimeNanoTSLFenceSyncWithDelta_EndProc        RT_MANGLER(RTTimeNanoTSLFenceSyncWithDelta_EndProc)
+# define RTTimeNanoTSLegacyAsync                                RT_MANGLER(RTTimeNanoTSLegacyAsync)
+# define RTTimeNanoTSLegacyAsync_EndProc                        RT_MANGLER(RTTimeNanoTSLegacyAsync_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseApicId                       RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicId)
+# define RTTimeNanoTSLegacyAsyncUseApicId_EndProc               RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicId_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseRdtscp                       RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscp)
+# define RTTimeNanoTSLegacyAsyncUseRdtscp_EndProc               RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscp_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseIdtrLim                      RT_MANGLER(RTTimeNanoTSLegacyAsyncUseIdtrLim)
+# define RTTimeNanoTSLegacyAsyncUseIdtrLim_EndProc              RT_MANGLER(RTTimeNanoTSLegacyAsyncUseIdtrLim_EndProc)
+# define RTTimeNanoTSLegacySyncInvarNoDelta                     RT_MANGLER(RTTimeNanoTSLegacySyncInvarNoDelta)
+# define RTTimeNanoTSLegacySyncInvarNoDelta_EndProc             RT_MANGLER(RTTimeNanoTSLegacySyncInvarNoDelta_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDelta                   RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDelta)
+# define RTTimeNanoTSLegacySyncInvarWithDelta_EndProc           RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDelta_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId          RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId_EndProc  RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp          RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp_EndProc  RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim         RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim_EndProc RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim_EndProc)
+# define RTTimeNanoTSLFenceAsync                                RT_MANGLER(RTTimeNanoTSLFenceAsync)
+# define RTTimeNanoTSLFenceAsync_EndProc                        RT_MANGLER(RTTimeNanoTSLFenceAsync_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseApicId                       RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicId)
+# define RTTimeNanoTSLFenceAsyncUseApicId_EndProc               RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicId_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseRdtscp                       RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscp)
+# define RTTimeNanoTSLFenceAsyncUseRdtscp_EndProc               RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscp_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseIdtrLim                      RT_MANGLER(RTTimeNanoTSLFenceAsyncUseIdtrLim)
+# define RTTimeNanoTSLFenceAsyncUseIdtrLim_EndProc              RT_MANGLER(RTTimeNanoTSLFenceAsyncUseIdtrLim_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarNoDelta                     RT_MANGLER(RTTimeNanoTSLFenceSyncInvarNoDelta)
+# define RTTimeNanoTSLFenceSyncInvarNoDelta_EndProc             RT_MANGLER(RTTimeNanoTSLFenceSyncInvarNoDelta_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDelta                   RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDelta)
+# define RTTimeNanoTSLFenceSyncInvarWithDelta_EndProc           RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDelta_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId          RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId_EndProc  RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp          RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp_EndProc  RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim         RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim_EndProc RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim_EndProc)
 # define RTTimeNormalize                                RT_MANGLER(RTTimeNormalize)
 # define RTTimeNow                                      RT_MANGLER(RTTimeNow)
Index: trunk/include/iprt/time.h
===================================================================
--- trunk/include/iprt/time.h	(revision 54269)
+++ trunk/include/iprt/time.h	(revision 54270)
@@ -840,6 +840,16 @@
     DECLCALLBACKMEMBER(uint64_t, pfnRediscover)(PRTTIMENANOTSDATA pData);
 
-    /** Just a dummy alignment member. */
-    void               *pvDummy;
+    /**
+     * Callback for when some CPU index related stuff goes wrong.
+     *
+     * @returns Nanosecond timestamp.
+     * @param   pData           Pointer to this structure.
+     * @param   idApic          The APIC ID if available, otherwise (UINT16_MAX-1).
+     * @param   iCpuSet         The CPU set index if available, otherwise
+     *                          (UINT16_MAX-1).
+     * @param   iGipCpu         The GIP CPU array index if available, otherwise
+     *                          (UINT16_MAX-1).
+     */
+    DECLCALLBACKMEMBER(uint64_t, pfnBadCpuIndex)(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
 
     /** Number of 1ns steps because of overshooting the period. */
@@ -862,5 +872,5 @@
     DECLR3CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
     DECLR3CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
-    RTR3PTR             pvDummy;
+    DECLR3CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
     uint32_t            c1nsSteps;
     uint32_t            cExpired;
@@ -881,5 +891,5 @@
     DECLR0CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
     DECLR0CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
-    RTR0PTR             pvDummy;
+    DECLR0CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
     uint32_t            c1nsSteps;
     uint32_t            cExpired;
@@ -900,5 +910,5 @@
     DECLRCCALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
     DECLRCCALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
-    RCPTRTYPE(void *)   pvDummy;
+    DECLRCCALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
     uint32_t            c1nsSteps;
     uint32_t            cExpired;
@@ -914,15 +924,25 @@
 /** Pointer to an internal RTTimeNanoTS worker (assembly). */
 typedef FNTIMENANOTSINTERNAL *PFNTIMENANOTSINTERNAL;
-
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarNoDelta(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarNoDelta(PRTTIMENANOTSDATA pData);
+#ifdef IN_RING3
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
+#else
 RTDECL(uint64_t) RTTimeNanoTSLegacyAsync(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLegacyInvariantNoDelta(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLegacyInvariantWithDelta(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLegacySyncNoDelta(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLegacySyncWithDelta(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDelta(PRTTIMENANOTSDATA pData);
 RTDECL(uint64_t) RTTimeNanoTSLFenceAsync(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLFenceInvariantNoDelta(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLFenceInvariantWithDelta(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLFenceSyncNoDelta(PRTTIMENANOTSDATA pData);
-RTDECL(uint64_t) RTTimeNanoTSLFenceSyncWithDelta(PRTTIMENANOTSDATA pData);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDelta(PRTTIMENANOTSDATA pData);
+#endif
 
 /** @} */
Index: trunk/src/VBox/Runtime/VBox/VBoxRTImp.def
===================================================================
--- trunk/src/VBox/Runtime/VBox/VBoxRTImp.def	(revision 54269)
+++ trunk/src/VBox/Runtime/VBox/VBoxRTImp.def	(revision 54270)
@@ -1337,14 +1337,18 @@
     RTTimeMilliTS
     RTTimeNanoTS
-    RTTimeNanoTSLegacyInvariantNoDelta
-    RTTimeNanoTSLegacyInvariantWithDelta
-    RTTimeNanoTSLegacySyncNoDelta
-    RTTimeNanoTSLegacySyncWithDelta
-    RTTimeNanoTSLegacyAsync
-    RTTimeNanoTSLFenceInvariantNoDelta
-    RTTimeNanoTSLFenceInvariantWithDelta
-    RTTimeNanoTSLFenceSyncNoDelta
-    RTTimeNanoTSLFenceSyncWithDelta
-    RTTimeNanoTSLFenceAsync
+    RTTimeNanoTSLegacySyncInvarNoDelta
+    RTTimeNanoTSLFenceSyncInvarNoDelta
+    RTTimeNanoTSLegacyAsyncUseApicId
+    RTTimeNanoTSLegacyAsyncUseRdtscp
+    RTTimeNanoTSLegacyAsyncUseIdtrLim
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim
+    RTTimeNanoTSLFenceAsyncUseApicId
+    RTTimeNanoTSLFenceAsyncUseRdtscp
+    RTTimeNanoTSLFenceAsyncUseIdtrLim
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim
     RTTimeNormalize
     RTTimeNow
Index: trunk/src/VBox/Runtime/common/time/timesup.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/time/timesup.cpp	(revision 54269)
+++ trunk/src/VBox/Runtime/common/time/timesup.cpp	(revision 54270)
@@ -52,4 +52,5 @@
 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalFallback(PRTTIMENANOTSDATA pData);
 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalRediscover(PRTTIMENANOTSDATA pData);
+static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalBadCpuIndex(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
 #endif
 
@@ -65,60 +66,54 @@
 static RTTIMENANOTSDATA g_TimeNanoTSData =
 {
-    /* .pu64Prev      = */ &g_TimeNanoTSPrev,
-    /* .pfnBad        = */ rtTimeNanoTSInternalBitch,
-    /* .pfnRediscover = */ rtTimeNanoTSInternalRediscover,
-    /* .pvDummy       = */ NULL,
-    /* .c1nsSteps     = */ 0,
-    /* .cExpired      = */ 0,
-    /* .cBadPrev      = */ 0,
-    /* .cUpdateRaces  = */ 0
+    /* .pu64Prev       = */ &g_TimeNanoTSPrev,
+    /* .pfnBad         = */ rtTimeNanoTSInternalBitch,
+    /* .pfnRediscover  = */ rtTimeNanoTSInternalRediscover,
+    /* .pfnBadCpuIndex = */ rtTimeNanoTSInternalBadCpuIndex,
+    /* .c1nsSteps      = */ 0,
+    /* .cExpired       = */ 0,
+    /* .cBadPrev       = */ 0,
+    /* .cUpdateRaces   = */ 0
 };
 
-/** The index into g_apfnWorkers for the function to use.
- * This cannot be a pointer because that'll break down in GC due to code relocation. */
-static uint32_t             g_iWorker = 0;
+# ifdef IN_RC
 /** Array of rtTimeNanoTSInternal worker functions.
  * This array is indexed by g_iWorker. */
 static const PFNTIMENANOTSINTERNAL g_apfnWorkers[] =
 {
-# define RTTIMENANO_WORKER_DETECT                   0
+#  define RTTIMENANO_WORKER_DETECT                                      0
     rtTimeNanoTSInternalRediscover,
 
-# define RTTIMENANO_WORKER_LEGACY_SYNC_NO_DELTA     1
-    RTTimeNanoTSLegacySyncNoDelta,
-# define RTTIMENANO_WORKER_LEGACY_SYNC_WITH_DELTA   2
-    RTTimeNanoTSLegacySyncWithDelta,
-# define RTTIMENANO_WORKER_LEGACY_ASYNC             3
+#  define RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_NO_DELTA                  1
+    RTTimeNanoTSLegacySyncInvarNoDelta,
+#  define RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_WITH_DELTA                2
+    RTTimeNanoTSLegacySyncInvarWithDelta,
+#  define RTTIMENANO_WORKER_LEGACY_ASYNC                                3
     RTTimeNanoTSLegacyAsync,
-# define RTTIMENANO_WORKER_LEGACY_INVAR_NO_DELTA    4
-    RTTimeNanoTSLFenceInvariantNoDelta,
-# define RTTIMENANO_WORKER_LEGACY_INVAR_WITH_DELTA  5
-    RTTimeNanoTSLFenceInvariantWithDelta,
-
-# define RTTIMENANO_WORKER_LFENCE_SYNC_NO_DELTA     6
-    RTTimeNanoTSLFenceSyncNoDelta,
-# define RTTIMENANO_WORKER_LFENCE_SYNC_WITH_DELTA   7
-    RTTimeNanoTSLFenceSyncWithDelta,
-# define RTTIMENANO_WORKER_LFENCE_ASYNC             8
+
+#  define RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA                  4
+    RTTimeNanoTSLFenceSyncInvarNoDelta,
+#  define RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA                5
+    RTTimeNanoTSLFenceSyncInvarWithDelta,
+#  define RTTIMENANO_WORKER_LFENCE_ASYNC                                6
     RTTimeNanoTSLFenceAsync,
-# define RTTIMENANO_WORKER_LFENCE_INVAR_NO_DELTA    9
-    RTTimeNanoTSLFenceInvariantNoDelta,
-# define RTTIMENANO_WORKER_LFENCE_INVAR_WITH_DELTA  10
-    RTTimeNanoTSLFenceInvariantWithDelta,
-
-# define RTTIMENANO_WORKER_FALLBACK                 11
+
+#  define RTTIMENANO_WORKER_FALLBACK                                    7
     rtTimeNanoTSInternalFallback,
 };
-
-
-/**
- * Helper function that's used by the assembly routines when something goes bust.
- *
- * @param   pData           Pointer to the data structure.
- * @param   u64NanoTS       The calculated nano ts.
- * @param   u64DeltaPrev    The delta relative to the previously returned timestamp.
- * @param   u64PrevNanoTS   The previously returned timestamp (as it was read it).
- */
-static DECLCALLBACK(void) rtTimeNanoTSInternalBitch(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS)
+/** The index into g_apfnWorkers for the function to use.
+ * @remarks This cannot be a pointer because that'll break down in RC due to
+ *          code relocation. */
+static uint32_t                 g_iWorker   = RTTIMENANO_WORKER_DETECT;
+# else
+/** Pointer to the worker */
+static PFNTIMENANOTSINTERNAL    g_pfnWorker = rtTimeNanoTSInternalRediscover;
+# endif /* IN_RC */
+
+
+/**
+ * @interface_method_impl{RTTIMENANOTSDATA, pfnBad}
+ */
+static DECLCALLBACK(void) rtTimeNanoTSInternalBitch(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev,
+                                                    uint64_t u64PrevNanoTS)
 {
     pData->cBadPrev++;
@@ -130,4 +125,20 @@
              u64DeltaPrev, u64PrevNanoTS, u64NanoTS));
 }
+
+/**
+ * @interface_method_impl{RTTIMENANOTSDATA, pfnBadCpuIndex}
+ */
+static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalBadCpuIndex(PRTTIMENANOTSDATA pData, uint16_t idApic,
+                                                              uint16_t iCpuSet, uint16_t iGipCpu)
+{
+# ifndef IN_RC
+    AssertMsgFailed(("idApic=%#x iCpuSet=%#x iGipCpu=%#x\n", idApic, iCpuSet, iGipCpu));
+    return RTTimeSystemNanoTS();
+# else
+    RTAssertReleasePanic();
+    return 0;
+# endif
+}
+
 
 /**
@@ -147,4 +158,5 @@
     return RTTimeSystemNanoTS();
 # else
+    RTAssertReleasePanic();
     return 0;
 # endif
@@ -158,6 +170,10 @@
 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalRediscover(PRTTIMENANOTSDATA pData)
 {
-    uint32_t iWorker;
-    PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
+    PSUPGLOBALINFOPAGE      pGip = g_pSUPGlobalInfoPage;
+# ifdef IN_RC
+    uint32_t                iWorker;
+# else
+    PFNTIMENANOTSINTERNAL   pfnWorker;
+# endif
     if (    pGip
         &&  pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
@@ -167,25 +183,95 @@
     {
         if (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2)
-            iWorker = pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
-                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                      ? RTTIMENANO_WORKER_LFENCE_INVAR_NO_DELTA : RTTIMENANO_WORKER_LFENCE_INVAR_WITH_DELTA
-                    : pGip->u32Mode == SUPGIPMODE_SYNC_TSC
-                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                      ? RTTIMENANO_WORKER_LFENCE_SYNC_NO_DELTA  : RTTIMENANO_WORKER_LFENCE_SYNC_WITH_DELTA
-                    : RTTIMENANO_WORKER_LFENCE_ASYNC;
+        {
+# ifdef IN_RC
+            iWorker   = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC
+                      ? RTTIMENANO_WORKER_LFENCE_ASYNC
+                      : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                      ? RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA
+                      : RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA;
+# elif defined(IN_RING0)
+            pfnWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC
+                      ? RTTimeNanoTSLFenceAsync
+                      : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                      ? RTTimeNanoTSLFenceSyncInvarNoDelta
+                      : RTTimeNanoTSLFenceSyncInvarWithDelta;
+# else
+            if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
+                pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+                          ? RTTimeNanoTSLFenceAsyncUseIdtrLim
+                          : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                          ? RTTimeNanoTSLFenceAsyncUseRdtscp
+                          : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
+                          ? RTTimeNanoTSLFenceAsyncUseApicId
+                          : rtTimeNanoTSInternalFallback;
+           else
+               pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+                         ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
+                           ? RTTimeNanoTSLFenceSyncInvarNoDelta
+                           : RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim
+                         : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                         ?   pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
+                           ? RTTimeNanoTSLFenceSyncInvarNoDelta
+                           : RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp
+                         : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
+                         ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                           ? RTTimeNanoTSLFenceSyncInvarNoDelta
+                           : RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId
+                         : rtTimeNanoTSInternalFallback;
+# endif
+        }
         else
-            iWorker = pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
-                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                      ? RTTIMENANO_WORKER_LEGACY_INVAR_NO_DELTA : RTTIMENANO_WORKER_LEGACY_INVAR_WITH_DELTA
-                    : pGip->u32Mode == SUPGIPMODE_SYNC_TSC
-                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                      ? RTTIMENANO_WORKER_LEGACY_SYNC_NO_DELTA  : RTTIMENANO_WORKER_LEGACY_SYNC_WITH_DELTA
-                    : RTTIMENANO_WORKER_LEGACY_ASYNC;
+        {
+# ifdef IN_RC
+            iWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC
+                    ? RTTIMENANO_WORKER_LEGACY_ASYNC
+                    : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                    ? RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_NO_DELTA :  RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_WITH_DELTA;
+# elif defined(IN_RING0)
+            pfnWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC
+                      ? RTTimeNanoTSLegacyAsync
+                      : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                      ? RTTimeNanoTSLegacySyncInvarNoDelta
+                      : RTTimeNanoTSLegacySyncInvarWithDelta;
+# else
+            if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
+                pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                          ? RTTimeNanoTSLegacyAsyncUseRdtscp
+                          : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+                          ? RTTimeNanoTSLegacyAsyncUseIdtrLim
+                          : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
+                          ? RTTimeNanoTSLegacyAsyncUseApicId
+                          : rtTimeNanoTSInternalFallback;
+           else
+               pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                         ?   pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
+                           ? RTTimeNanoTSLegacySyncInvarNoDelta
+                           : RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp
+                         : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+                         ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
+                           ? RTTimeNanoTSLegacySyncInvarNoDelta
+                           : RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim
+                         : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
+                         ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                           ? RTTimeNanoTSLegacySyncInvarNoDelta
+                           : RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId
+                         : rtTimeNanoTSInternalFallback;
+# endif
+        }
     }
     else
+# ifdef IN_RC
         iWorker = RTTIMENANO_WORKER_FALLBACK;
-
+# else
+        pfnWorker = rtTimeNanoTSInternalFallback;
+# endif
+
+# ifdef IN_RC
     ASMAtomicWriteU32((uint32_t volatile *)&g_iWorker, iWorker);
     return g_apfnWorkers[iWorker](pData);
+# else
+    ASMAtomicWritePtr((void * volatile *)&g_pfnWorker, (void *)(uintptr_t)pfnWorker);
+    return pfnWorker(pData);
+# endif
 }
 
@@ -199,5 +285,9 @@
 {
 #if !defined(IN_GUEST) && !defined(RT_NO_GIP)
+# ifdef IN_RC
     return g_apfnWorkers[g_iWorker](&g_TimeNanoTSData);
+# else
+    return g_pfnWorker(&g_TimeNanoTSData);
+# endif
 #else
     return RTTimeSystemNanoTS();
Index: trunk/src/VBox/Runtime/common/time/timesupA.asm
===================================================================
--- trunk/src/VBox/Runtime/common/time/timesupA.asm	(revision 54269)
+++ trunk/src/VBox/Runtime/common/time/timesupA.asm	(revision 54270)
@@ -29,4 +29,12 @@
 %include "iprt/asmdefs.mac"
 %include "VBox/sup.mac"
+
+;
+; Use the C reference implementation for now.
+;
+%error "This is out of date, use C code.  Not worth it for a couple of ticks in some functions and equal or worse performance in others."
+This is out of date
+This is out of date
+This is out of date
 
 
Index: trunk/src/VBox/Runtime/common/time/timesupref.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/time/timesupref.cpp	(revision 54269)
+++ trunk/src/VBox/Runtime/common/time/timesupref.cpp	(revision 54270)
@@ -37,58 +37,97 @@
 #include <iprt/asm-amd64-x86.h>
 #include <VBox/sup.h>
+#ifdef IN_RC
+# include <VBox/vmm/vmm.h>
+# include <VBox/vmm/vm.h>
+#endif
 #include "internal/time.h"
 
 
-#define GIP_MODE_SYNC_NO_DELTA          1
-#define GIP_MODE_SYNC_WITH_DELTA        2
-#define GIP_MODE_ASYNC                  3
-#define GIP_MODE_INVARIANT_NO_DELTA     4
-#define GIP_MODE_INVARIANT_WITH_DELTA   5
-#define IS_GIP_MODE_WITH_DELTA(a_enmMode) \
-    ((a_enmMode) == GIP_MODE_SYNC_WITH_DELTA || (a_enmMode) == GIP_MODE_INVARIANT_WITH_DELTA)
+#define TMPL_MODE_SYNC_INVAR_NO_DELTA       1
+#define TMPL_MODE_SYNC_INVAR_WITH_DELTA     2
+#define TMPL_MODE_ASYNC                     3
 
 
 /*
- * Use the CPUID instruction for some kind of serialization.
- */
-#define GIP_MODE GIP_MODE_SYNC_NO_DELTA
-#undef  USE_LFENCE
-#define NEED_TRANSACTION_ID
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncNoDelta
+ * Use the XCHG instruction for some kind of serialization.
+ */
+#define TMPL_READ_FENCE()        ASMReadFence()
+
+#undef  TMPL_MODE
+#define TMPL_MODE                TMPL_MODE_SYNC_INVAR_NO_DELTA
+#undef  TMPL_GET_CPU_METHOD
+#define TMPL_GET_CPU_METHOD      0
+#undef  rtTimeNanoTSInternalRef
+#define rtTimeNanoTSInternalRef  RTTimeNanoTSLegacySyncInvarNoDelta
 #include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncNoDelta);
-
-#undef  GIP_MODE
-#define GIP_MODE  GIP_MODE_SYNC_NO_DELTA
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncWithDelta
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncWithDelta);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_ASYNC
-#ifdef IN_RC
-# undef NEED_TRANSACTION_ID
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarNoDelta);
+
+#ifdef IN_RING3
+
+# undef  TMPL_MODE
+# define TMPL_MODE               TMPL_MODE_SYNC_INVAR_WITH_DELTA
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_APIC_ID
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim);
+
+# undef  TMPL_MODE
+# define TMPL_MODE               TMPL_MODE_ASYNC
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_APIC_ID
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseApicId
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseApicId);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseRdtscp
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseRdtscp);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseIdtrLim
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseIdtrLim);
+
+#else  /* IN_RC || IN_RING0: Disable interrupts and call getter function. */
+
+# undef  TMPL_MODE
+# define TMPL_MODE               TMPL_MODE_SYNC_INVAR_WITH_DELTA
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     UINT32_MAX
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDelta
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDelta);
+
+# undef  TMPL_MODE
+# define TMPL_MODE TMPL_MODE_ASYNC
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsync
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsync);
+
 #endif
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsync
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsync);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_INVARIANT_NO_DELTA
-#undef  NEED_TRANSACTION_ID
-#define NEED_TRANSACTION_ID
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyInvariantNoDelta
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyInvariantNoDelta);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_INVARIANT_WITH_DELTA
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyInvariantWithDelta
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyInvariantWithDelta);
 
 
@@ -96,46 +135,83 @@
  * Use LFENCE for load serialization.
  */
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_SYNC_NO_DELTA
-#define USE_LFENCE
-#undef  NEED_TRANSACTION_ID
-#define NEED_TRANSACTION_ID
+#undef  TMPL_READ_FENCE
+#define TMPL_READ_FENCE()        ASMReadFenceSSE2()
+
+#undef  TMPL_MODE
+#define TMPL_MODE                TMPL_MODE_SYNC_INVAR_NO_DELTA
+#undef  TMPL_GET_CPU_METHOD
+#define TMPL_GET_CPU_METHOD      0
 #undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncNoDelta
+#define rtTimeNanoTSInternalRef  RTTimeNanoTSLFenceSyncInvarNoDelta
 #include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncNoDelta);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_SYNC_WITH_DELTA
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncWithDelta
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncWithDelta);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_ASYNC
-#ifdef IN_RC
-# undef NEED_TRANSACTION_ID
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarNoDelta);
+
+#ifdef IN_RING3
+
+# undef  TMPL_MODE
+# define TMPL_MODE               TMPL_MODE_SYNC_INVAR_WITH_DELTA
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_APIC_ID
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim);
+
+# undef  TMPL_MODE
+# define TMPL_MODE               TMPL_MODE_ASYNC
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_APIC_ID
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseApicId
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseApicId);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseRdtscp
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseRdtscp);
+
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseIdtrLim
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseIdtrLim);
+
+#else  /* IN_RC || IN_RING0: Disable interrupts and call getter function. */
+
+# undef  TMPL_MODE
+# define TMPL_MODE               TMPL_MODE_SYNC_INVAR_WITH_DELTA
+# undef  TMPL_GET_CPU_METHOD
+# define TMPL_GET_CPU_METHOD     UINT32_MAX
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDelta
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDelta);
+
+# undef  TMPL_MODE
+# define TMPL_MODE TMPL_MODE_ASYNC
+# undef  rtTimeNanoTSInternalRef
+# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsync
+# include "timesupref.h"
+RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsync);
+
 #endif
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsync
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsync);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_INVARIANT_NO_DELTA
-#undef  NEED_TRANSACTION_ID
-#define NEED_TRANSACTION_ID
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceInvariantNoDelta
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceInvariantNoDelta);
-
-#undef  GIP_MODE
-#define GIP_MODE GIP_MODE_INVARIANT_WITH_DELTA
-#undef  rtTimeNanoTSInternalRef
-#define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceInvariantWithDelta
-#include "timesupref.h"
-RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceInvariantWithDelta);
 
 
Index: trunk/src/VBox/Runtime/common/time/timesupref.h
===================================================================
--- trunk/src/VBox/Runtime/common/time/timesupref.h	(revision 54269)
+++ trunk/src/VBox/Runtime/common/time/timesupref.h	(revision 54270)
@@ -45,6 +45,9 @@
 {
     uint64_t    u64Delta;
-#if IS_GIP_MODE_WITH_DELTA(GIP_MODE)
+#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
     int64_t     i64TscDelta;
+# ifdef IN_RING3
+    PSUPGIPCPU  pGipCpuAttemptedTscRecalibration = NULL;
+# endif
 #endif
     uint32_t    u32NanoTSFactor0;
@@ -53,4 +56,5 @@
     uint32_t    u32UpdateIntervalTSC;
     uint64_t    u64PrevNanoTS;
+    AssertCompile(RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS));
 
     /*
@@ -59,63 +63,224 @@
     for (;;)
     {
+#ifndef IN_RING3 /* This simplifies and improves everything. */
+        RTCCUINTREG const  uFlags = ASMIntDisableFlags();
+#endif
+
+        /*
+         * Check that the GIP is sane and that the premises for this worker function
+         * hasn't changed (CPU onlined with bad delta or missing features).
+         */
         PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
-#ifdef IN_RING3
-        if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC))
-            return pData->pfnRediscover(pData);
-#endif
-#if GIP_MODE == GIP_MODE_ASYNC || IS_GIP_MODE_WITH_DELTA(GIP_MODE)
-        uint8_t const u8ApicId  = ASMGetApicId();
-        PSUPGIPCPU pGipCpu      = &pGip->aCPUs[pGip->aiCpuFromApicId[u8ApicId]];
-#endif
-
-#ifdef NEED_TRANSACTION_ID
-# if GIP_MODE == GIP_MODE_ASYNC
-        uint32_t u32TransactionId = pGipCpu->u32TransactionId;
+        if (   RT_LIKELY(pGip)
+            && RT_LIKELY(pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC)
+#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
+            && RT_LIKELY(pGip->enmUseTscDelta >= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
+#else
+            && RT_LIKELY(pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+#endif
+#if defined(IN_RING3) && TMPL_GET_CPU_METHOD != 0 && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID
+            && RT_LIKELY(pGip->fGetGipCpu & TMPL_GET_CPU_METHOD)
+#endif
+           )
+        {
+            /*
+             * Resolve pGipCpu if needed.  If the instruction is serializing, we
+             * read the transaction id first if possible.
+             */
+#if TMPL_MODE == TMPL_MODE_ASYNC || TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
+# if   defined(IN_RING0)
+            uint32_t const  iCpuSet  = RTMpCpuIdToSetIndex(RTMpCpuId());
+            uint16_t const  iGipCpu  = iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)
+                                     ? pGip->aiCpuFromCpuSetIdx[iCpuSet] : UINT16_MAX;
+# elif defined(IN_RC)
+            uint32_t const  iCpuSet  = VMMGetCpu(&g_VM)->iHostCpuSet;
+            uint16_t const  iGipCpu  = iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)
+                                     ? pGip->aiCpuFromCpuSetIdx[iCpuSet] : UINT16_MAX;
+# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_APIC_ID
+#  if TMPL_MODE != TMPL_MODE_ASYNC
+            uint32_t const  u32TransactionId = pGip->aCPUs[0].u32TransactionId;
+#  endif
+            uint8_t  const  idApic   = ASMGetApicId();
+            uint16_t const  iGipCpu  = pGip->aiCpuFromApicId[idApic];
+# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+#  if TMPL_MODE != TMPL_MODE_ASYNC
+            uint32_t const  u32TransactionId = pGip->aCPUs[0].u32TransactionId;
+#  endif
+            uint32_t        uAux;
+            ASMReadTscWithAux(&uAux);
+            uint16_t const  iCpuSet  = uAux & (RTCPUSET_MAX_CPUS - 1);
+            uint16_t const  iGipCpu  = pGip->aiCpuFromCpuSetIdx[iCpuSet];
+# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+            uint16_t const  cbLim    = ASMGetIdtrLimit();
+            uint16_t const  iCpuSet  = (cbLim - 256 * (ARCH_BITS == 64 ? 16 : 8)) & (RTCPUSET_MAX_CPUS - 1);
+            uint16_t const  iGipCpu  = pGip->aiCpuFromCpuSetIdx[iCpuSet];
 # else
-        uint32_t u32TransactionId = pGip->aCPUs[0].u32TransactionId;
-# endif
-# ifdef USE_LFENCE
-        ASMReadFenceSSE2();
+#  error "What?"
+# endif
+            if (RT_LIKELY(iGipCpu < pGip->cCpus))
+            {
+                PSUPGIPCPU pGipCpu = &pGip->aCPUs[iGipCpu];
+#else
+            {
+#endif
+                /*
+                 * Get the transaction ID if necessary and we haven't already
+                 * read it before a serializing instruction above.  We can skip
+                 * this for ASYNC_TSC mode in ring-0 and raw-mode context since
+                 * we disable interrupts.
+                 */
+#if TMPL_MODE == TMPL_MODE_ASYNC && defined(IN_RING3)
+                uint32_t const u32TransactionId = pGipCpu->u32TransactionId;
+                ASMCompilerBarrier();
+                TMPL_READ_FENCE();
+#elif TMPL_MODE != TMPL_MODE_ASYNC \
+   && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID \
+   && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                uint32_t const u32TransactionId = pGip->aCPUs[0].u32TransactionId;
+                ASMCompilerBarrier();
+                TMPL_READ_FENCE();
+#endif
+
+                /*
+                 * Gather all the data we need.  The mess at the end is to make
+                 * sure all loads are done before we recheck the transaction ID
+                 * without triggering serializing twice.
+                 */
+                u32NanoTSFactor0        = pGip->u32UpdateIntervalNS;
+#if TMPL_MODE == TMPL_MODE_ASYNC
+                u32UpdateIntervalTSC    = pGipCpu->u32UpdateIntervalTSC;
+                u64NanoTS               = pGipCpu->u64NanoTS;
+                u64TSC                  = pGipCpu->u64TSC;
+#else
+                u32UpdateIntervalTSC    = pGip->aCPUs[0].u32UpdateIntervalTSC;
+                u64NanoTS               = pGip->aCPUs[0].u64NanoTS;
+                u64TSC                  = pGip->aCPUs[0].u64TSC;
+# if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
+                i64TscDelta             = pGipCpu->i64TSCDelta;
+# endif
+#endif
+#if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                u64PrevNanoTS           = ASMAtomicUoReadU64(pData->pu64Prev);
+                ASMCompilerBarrier();
+                uint32_t uAux2;
+                u64Delta                = ASMReadTscWithAux(&uAux2); /* serializing */
+#else
+                u64Delta                = ASMReadTSC();
+                u64PrevNanoTS           = ASMAtomicUoReadU64(pData->pu64Prev);
+                ASMCompilerBarrier();
+# if TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID /* getting APIC will serialize  */ \
+  && (defined(IN_RING3) || TMPL_MODE != TMPL_MODE_ASYNC)
+                TMPL_READ_FENCE(); /* Expensive (~30 ticks).  Would like convincing argumentation that let us remove it. */
+# endif
+#endif
+
+                /*
+                 * Check that we didn't change CPU.
+                 */
+#if defined(IN_RING3) && ( TMPL_MODE == TMPL_MODE_ASYNC || TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA )
+# if   TMPL_GET_CPU_METHOD == SUPGIPGETCPU_APIC_ID
+                if (RT_LIKELY(ASMGetApicId() == idApic))
+# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
+                if (RT_LIKELY(uAux2 == uAux))
+# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
+                if (RT_LIKELY(ASMGetIdtrLimit() == cbLim))
+# endif
+#endif
+                {
+                    /*
+                     * Check the transaction ID (see above for R0/RC + ASYNC).
+                     */
+#if defined(IN_RING3) || TMPL_MODE != TMPL_MODE_ASYNC
+# if TMPL_MODE == TMPL_MODE_ASYNC
+                    if (RT_LIKELY(pGipCpu->u32TransactionId       == u32TransactionId && !(u32TransactionId & 1) ))
 # else
-        ASMReadFence();
-# endif
-#endif
-
-#if GIP_MODE == GIP_MODE_ASYNC
-        u32UpdateIntervalTSC    = pGipCpu->u32UpdateIntervalTSC;
-        u64NanoTS               = pGipCpu->u64NanoTS;
-        u64TSC                  = pGipCpu->u64TSC;
-#else
-        u32UpdateIntervalTSC    = pGip->aCPUs[0].u32UpdateIntervalTSC;
-        u64NanoTS               = pGip->aCPUs[0].u64NanoTS;
-        u64TSC                  = pGip->aCPUs[0].u64TSC;
-# if IS_GIP_MODE_WITH_DELTA(GIP_MODE)
-        i64TscDelta             = pGipCpu->i64TSCDelta;
-# endif
-#endif
-        u32NanoTSFactor0        = pGip->u32UpdateIntervalNS;
-        u64Delta                = ASMReadTSC();
-        u64PrevNanoTS           = ASMAtomicReadU64(pData->pu64Prev);
-
-#ifdef NEED_TRANSACTION_ID
-# if GIP_MODE == GIP_MODE_ASYNC || IS_GIP_MODE_WITH_DELTA(GIP_MODE)
-        if (RT_UNLIKELY(u8ApicId != ASMGetApicId()))
-            continue;
-# elif defined(USE_LFENCE)
-        ASMWriteFenceSSE();
+                    if (RT_LIKELY(pGip->aCPUs[0].u32TransactionId == u32TransactionId && !(u32TransactionId & 1) ))
+# endif
+#endif
+                    {
+
+                        /*
+                         * Apply the TSC delta.  If the delta is invalid and the
+                         * execution allows it, try trigger delta recalibration.
+                         */
+#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA && defined(IN_RING3)
+                        if (RT_LIKELY(   i64TscDelta != INT64_MAX
+                                      || pGipCpu == pGipCpuAttemptedTscRecalibration))
+#endif
+                        {
+#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
+# ifndef IN_RING3
+                            if (RT_LIKELY(i64TscDelta != INT64_MAX))
+# endif
+                                u64Delta -= i64TscDelta;
+#endif
+
+                            /*
+                             * Bingo! We've got a consistent set of data.
+                             */
+#ifndef IN_RING3
+                            ASMSetFlags(uFlags);
+#endif
+                            break;
+                        }
+#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA && defined(IN_RING3)
+                        /*
+                         * Call into the support driver to try make it recalculate the delta. We
+                         * remember which GIP CPU structure we're probably working on so we won't
+                         * end up in a loop if the driver for some reason cannot get the job done.
+                         */
+                        else /* else is unecessary, but helps checking the preprocessor spaghetti. */
+                        {
+                            pGipCpuAttemptedTscRecalibration = pGipCpu;
+                            uint64_t u64TscTmp;
+                            uint16_t idApicUpdate;
+                            int rc = SUPR3ReadTsc(&u64TscTmp, &idApicUpdate);
+                            if (RT_SUCCESS(rc) && idApicUpdate <= RT_ELEMENTS(pGip->aiCpuFromApicId))
+                            {
+                                uint32_t iUpdateGipCpu = pGip->aiCpuFromApicId[idApicUpdate];
+                                if (iUpdateGipCpu < pGip->cCpus)
+                                    pGipCpuAttemptedTscRecalibration = &pGip->aCPUs[iUpdateGipCpu];
+                            }
+                        }
+#endif
+                    }
+                }
+
+                /*
+                 * No joy must try again.
+                 */
+#ifndef IN_RING3
+                ASMSetFlags(uFlags);
+#endif
+                ASMNopPause();
+                continue;
+            }
+
+#if TMPL_MODE == TMPL_MODE_ASYNC || TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
+            /*
+             * We've got a bad CPU or APIC index of some kind.
+             */
+            else /* else is unecessary, but helps checking the preprocessor spaghetti. */
+            {
+# ifndef IN_RING3
+                ASMSetFlags(uFlags);
+# endif
+# if defined(IN_RING0) || defined(IN_RC) || TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID
+                return pData->pfnBadCpuIndex(pData, UINT16_MAX-1, iCpuSet, iGipCpu);
 # else
-        ASMWriteFence();
-# endif
-# if GIP_MODE == GIP_MODE_ASYNC
-        if (RT_UNLIKELY(   pGipCpu->u32TransactionId != u32TransactionId
-                        || (u32TransactionId & 1)))
-            continue;
-# else
-        if (RT_UNLIKELY(   pGip->aCPUs[0].u32TransactionId != u32TransactionId
-                        || (u32TransactionId & 1)))
-            continue;
-# endif
-#endif
-        break;
+                return pData->pfnBadCpuIndex(pData, idApic, UINT16_MAX-1, iGipCpu);
+# endif
+            }
+#endif
+        }
+
+        /*
+         * Something changed in the GIP config or it was unmapped, figure out
+         * the right worker function to use now.
+         */
+#ifndef IN_RING3
+        ASMSetFlags(uFlags);
+#endif
+        return pData->pfnRediscover(pData);
     }
 
@@ -124,8 +289,4 @@
      */
     u64Delta -= u64TSC;
-#if IS_GIP_MODE_WITH_DELTA(GIP_MODE)
-    if (RT_LIKELY(i64TscDelta != INT64_MAX))
-        u64Delta -= i64TscDelta;
-#endif
     if (RT_UNLIKELY(u64Delta > u32UpdateIntervalTSC))
     {
Index: trunk/src/VBox/Runtime/r3/win/VBoxRT-win32.def
===================================================================
--- trunk/src/VBox/Runtime/r3/win/VBoxRT-win32.def	(revision 54269)
+++ trunk/src/VBox/Runtime/r3/win/VBoxRT-win32.def	(revision 54270)
@@ -28,13 +28,17 @@
     ASMMultU64ByU32DivByU32
 
-    RTTimeNanoTSLegacyInvariantNoDelta
-    RTTimeNanoTSLegacyInvariantWithDelta
-    RTTimeNanoTSLegacySyncNoDelta
-    RTTimeNanoTSLegacySyncWithDelta
-    RTTimeNanoTSLegacyAsync
-    RTTimeNanoTSLFenceInvariantNoDelta
-    RTTimeNanoTSLFenceInvariantWithDelta
-    RTTimeNanoTSLFenceSyncNoDelta
-    RTTimeNanoTSLFenceSyncWithDelta
-    RTTimeNanoTSLFenceAsync
+    RTTimeNanoTSLegacySyncInvarNoDelta
+    RTTimeNanoTSLFenceSyncInvarNoDelta
+    RTTimeNanoTSLegacyAsyncUseApicId
+    RTTimeNanoTSLegacyAsyncUseRdtscp
+    RTTimeNanoTSLegacyAsyncUseIdtrLim
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim
+    RTTimeNanoTSLFenceAsyncUseApicId
+    RTTimeNanoTSLFenceAsyncUseRdtscp
+    RTTimeNanoTSLFenceAsyncUseIdtrLim
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim
 
Index: trunk/src/VBox/Runtime/r3/win/VBoxRT-win64.def
===================================================================
--- trunk/src/VBox/Runtime/r3/win/VBoxRT-win64.def	(revision 54269)
+++ trunk/src/VBox/Runtime/r3/win/VBoxRT-win64.def	(revision 54270)
@@ -40,13 +40,17 @@
     ASMNopPause
 
-    RTTimeNanoTSLegacyInvariantNoDelta
-    RTTimeNanoTSLegacyInvariantWithDelta
-    RTTimeNanoTSLegacySyncNoDelta
-    RTTimeNanoTSLegacySyncWithDelta
-    RTTimeNanoTSLegacyAsync
-    RTTimeNanoTSLFenceInvariantNoDelta
-    RTTimeNanoTSLFenceInvariantWithDelta
-    RTTimeNanoTSLFenceSyncNoDelta
-    RTTimeNanoTSLFenceSyncWithDelta
-    RTTimeNanoTSLFenceAsync
+    RTTimeNanoTSLegacySyncInvarNoDelta
+    RTTimeNanoTSLFenceSyncInvarNoDelta
+    RTTimeNanoTSLegacyAsyncUseApicId
+    RTTimeNanoTSLegacyAsyncUseRdtscp
+    RTTimeNanoTSLegacyAsyncUseIdtrLim
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp
+    RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim
+    RTTimeNanoTSLFenceAsyncUseApicId
+    RTTimeNanoTSLFenceAsyncUseRdtscp
+    RTTimeNanoTSLFenceAsyncUseIdtrLim
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp
+    RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim
 
Index: trunk/src/VBox/Runtime/testcase/Makefile.kmk
===================================================================
--- trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 54269)
+++ trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 54270)
@@ -371,11 +371,8 @@
  	$(PATH_STAGE_LIB)/DisasmRC$(VBOX_SUFF_LIB) \
  	$(PATH_STAGE_LIB)/RuntimeRC$(VBOX_SUFF_LIB)
- ifeq ($(VBOX_LDR_FMT32),pe)
+ if1of ($(VBOX_LDR_FMT32),lx pe)
  tstLdrObj_LIBS += \
- 	$(PATH_STAGE_LIB)/VMMRCBuiltin$(VBOX_SUFF_LIB)
- endif # PE
- ifeq ($(VBOX_LDR_FMT32),lx)
- tstLdrObj_LIBS += \
- 	$(PATH_STAGE_LIB)/VMMRCBuiltin$(VBOX_SUFF_LIB)
+ 	$(PATH_STAGE_LIB)/VMMRCBuiltin$(VBOX_SUFF_LIB) \
+ 	$(PATH_STAGE_LIB)/VMMRCImp$(VBOX_SUFF_LIB)
  endif
 endif # VBOX_WITH_RAW_MODE
Index: trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp	(revision 54269)
+++ trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp	(revision 54270)
@@ -44,43 +44,108 @@
 
 /**
- * Helper function that's used by the assembly routines when something goes bust.
- *
- * @param   pData           Pointer to the data structure.
- * @param   u64NanoTS       The calculated nano ts.
- * @param   u64DeltaPrev    The delta relative to the previously returned timestamp.
- * @param   u64PrevNanoTS   The previously returned timestamp (as it was read it).
- */
-DECLEXPORT(void) tmVirtualNanoTSBad(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS)
-{
-    //PVM pVM = (PVM)((uint8_t *)pData - RT_OFFSETOF(VM, CTXALLSUFF(s.tm.VirtualGetRawData)));
+ * @interface_method_impl{RTTIMENANOTSDATA, pfnBadPrev}
+ */
+DECLEXPORT(void) tmVirtualNanoTSBadPrev(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev,
+                                        uint64_t u64PrevNanoTS)
+{
+    PVM pVM = RT_FROM_MEMBER(pData, VM, CTX_SUFF(tm.s.VirtualGetRawData));
     pData->cBadPrev++;
     if ((int64_t)u64DeltaPrev < 0)
-        LogRel(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64\n",
-                u64DeltaPrev, u64PrevNanoTS, u64NanoTS));
+        LogRel(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 pVM=%p\n",
+                u64DeltaPrev, u64PrevNanoTS, u64NanoTS, pVM));
     else
-        Log(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 (debugging?)\n",
-             u64DeltaPrev, u64PrevNanoTS, u64NanoTS));
-}
-
-
-/**
- * Called the first time somebody asks for the time or when the GIP
- * is mapped/unmapped.
- *
- * This should never ever happen.
+        Log(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 pVM=%p (debugging?)\n",
+             u64DeltaPrev, u64PrevNanoTS, u64NanoTS, pVM));
+}
+
+
+/**
+ * @interface_method_impl{RTTIMENANOTSDATA, pfnRediscover}
+ *
+ * This is the initial worker, so the first call in each context ends up here.
+ * It is also used should the delta rating of the host CPUs change or if the
+ * fGetGipCpu feature the current worker relies upon becomes unavailable.  The
+ * last two events may occur as CPUs are taken online.
  */
 DECLEXPORT(uint64_t) tmVirtualNanoTSRediscover(PRTTIMENANOTSDATA pData)
 {
-    NOREF(pData);
-    //PVM pVM = (PVM)((uint8_t *)pData - RT_OFFSETOF(VM, CTXALLSUFF(s.tm.VirtualGetRawData)));
+    PVM pVM = RT_FROM_MEMBER(pData, VM, CTX_SUFF(tm.s.VirtualGetRawData));
+
+    /*
+     * We require a valid GIP for the selection below.  Invalid GIP is fatal.
+     */
     PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
-    AssertFatalMsgFailed(("pGip=%p u32Magic=%#x\n", pGip, VALID_PTR(pGip) ? pGip->u32Magic : 0));
+    AssertFatalMsg(RT_VALID_PTR(pGip), ("pVM=%p pGip=%p\n", pVM, pGip));
+    AssertFatalMsg(pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC, ("pVM=%p pGip=%p u32Magic=%#x\n", pVM, pGip, pGip->u32Magic));
+    AssertFatalMsg(pGip->u32Mode > SUPGIPMODE_INVALID && pGip->u32Mode < SUPGIPMODE_END,
+                   ("pVM=%p pGip=%p u32Mode=%#x\n", pVM, pGip, pGip->u32Mode));
+
+    /*
+     * Determine the new worker.
+     */
+    PFNTIMENANOTSINTERNAL   pfnWorker;
+    bool const              fLFence = RT_BOOL(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2);
+    switch (pGip->u32Mode)
+    {
+        case SUPGIPMODE_SYNC_TSC:
+        case SUPGIPMODE_INVARIANT_TSC:
+#if defined(IN_RC) || defined(IN_RING0)
+            if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+                pfnWorker = fLFence ? RTTimeNanoTSLFenceSyncInvarNoDelta    : RTTimeNanoTSLegacySyncInvarNoDelta;
+            else
+                pfnWorker = fLFence ? RTTimeNanoTSLFenceSyncInvarWithDelta  : RTTimeNanoTSLegacySyncInvarWithDelta;
+#else
+            if (pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS)
+                pfnWorker = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
+                          ? fLFence ? RTTimeNanoTSLFenceSyncInvarNoDelta    : RTTimeNanoTSLegacySyncInvarNoDelta
+                          : fLFence ? RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim : RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim;
+            else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
+                pfnWorker = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
+                          ? fLFence ? RTTimeNanoTSLFenceSyncInvarNoDelta    : RTTimeNanoTSLegacySyncInvarNoDelta
+                          : fLFence ? RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp : RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp;
+            else
+                pfnWorker = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
+                          ? fLFence ? RTTimeNanoTSLFenceSyncInvarNoDelta    : RTTimeNanoTSLegacySyncInvarNoDelta
+                          : fLFence ? RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId : RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId;
+#endif
+            break;
+
+        case SUPGIPMODE_ASYNC_TSC:
+#if defined(IN_RC) || defined(IN_RING0)
+            pfnWorker = fLFence ? RTTimeNanoTSLFenceAsync : RTTimeNanoTSLegacyAsync;
+#else
+            if (pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS)
+                pfnWorker = fLFence ? RTTimeNanoTSLFenceAsyncUseIdtrLim     : RTTimeNanoTSLegacyAsyncUseIdtrLim;
+            else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
+                pfnWorker = fLFence ? RTTimeNanoTSLFenceAsyncUseRdtscp      : RTTimeNanoTSLegacyAsyncUseRdtscp;
+            else
+                pfnWorker = fLFence ? RTTimeNanoTSLFenceAsyncUseApicId      : RTTimeNanoTSLegacyAsyncUseApicId;
+#endif
+            break;
+
+        default:
+            AssertFatalMsgFailed(("pVM=%p pGip=%p u32Mode=%#x\n", pVM, pGip, pGip->u32Mode));
+    }
+
+    /*
+     * Update the pfnVirtualGetRaw pointer and call the worker we selected.
+     */
+    ASMAtomicWritePtr((void * volatile *)&CTX_SUFF(pVM->tm.s.pfnVirtualGetRaw), (void *)(uintptr_t)pfnWorker);
+    return pfnWorker(pData);
+}
+
+
+/**
+ * @interface_method_impl{RTTIMENANOTSDATA, pfnBadGipIndex}
+ */
+DECLEXPORT(uint64_t) tmVirtualNanoTSBadCpuIndex(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu)
+{
+    PVM pVM = RT_FROM_MEMBER(pData, VM, CTX_SUFF(tm.s.VirtualGetRawData));
+    AssertFatalMsgFailed(("pVM=%p idApic=%#x iCpuSet=%#x iGipCpu=%#x\n", pVM, idApic, iCpuSet, iGipCpu));
 #ifndef _MSC_VER
-    return 0; /* gcc false positive warning */
+    return UINT64_MAX;
 #endif
 }
 
-
-#if 1
 
 /**
@@ -100,181 +165,4 @@
     return u64;
 }
-
-#else
-
-/**
- * This is (mostly) the same as rtTimeNanoTSInternal() except
- * for the two globals which live in TM.
- *
- * @returns Nanosecond timestamp.
- * @param   pVM     Pointer to the VM.
- */
-static uint64_t tmVirtualGetRawNanoTS(PVM pVM)
-{
-    uint64_t    u64Delta;
-    uint32_t    u32NanoTSFactor0;
-    uint64_t    u64TSC;
-    uint64_t    u64NanoTS;
-    uint32_t    u32UpdateIntervalTSC;
-    uint64_t    u64PrevNanoTS;
-
-    /*
-     * Read the GIP data and the previous value.
-     */
-    for (;;)
-    {
-        uint32_t u32TransactionId;
-        PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
-#ifdef IN_RING3
-        if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC))
-            return RTTimeSystemNanoTS();
-#endif
-
-        if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
-        {
-            u32TransactionId = pGip->aCPUs[0].u32TransactionId;
-#ifdef RT_OS_L4
-            Assert((u32TransactionId & 1) == 0);
-#endif
-            u32UpdateIntervalTSC = pGip->aCPUs[0].u32UpdateIntervalTSC;
-            u64NanoTS = pGip->aCPUs[0].u64NanoTS;
-            u64TSC = pGip->aCPUs[0].u64TSC;
-            u32NanoTSFactor0 = pGip->u32UpdateIntervalNS;
-            u64Delta = ASMReadTSC();
-            u64PrevNanoTS = ASMAtomicReadU64(&pVM->tm.s.u64VirtualRawPrev);
-            if (RT_UNLIKELY(    pGip->aCPUs[0].u32TransactionId != u32TransactionId
-                            ||  (u32TransactionId & 1)))
-                continue;
-        }
-        else
-        {
-            /* SUPGIPMODE_ASYNC_TSC */
-            PSUPGIPCPU pGipCpu;
-
-            uint8_t u8ApicId = ASMGetApicId();
-            if (RT_LIKELY(u8ApicId < RT_ELEMENTS(pGip->aCPUs)))
-                pGipCpu = &pGip->aCPUs[u8ApicId];
-            else
-            {
-                AssertMsgFailed(("%x\n", u8ApicId));
-                pGipCpu = &pGip->aCPUs[0];
-            }
-
-            u32TransactionId = pGipCpu->u32TransactionId;
-#ifdef RT_OS_L4
-            Assert((u32TransactionId & 1) == 0);
-#endif
-            u32UpdateIntervalTSC = pGipCpu->u32UpdateIntervalTSC;
-            u64NanoTS = pGipCpu->u64NanoTS;
-            u64TSC = pGipCpu->u64TSC;
-            u32NanoTSFactor0 = pGip->u32UpdateIntervalNS;
-            u64Delta = ASMReadTSC();
-            u64PrevNanoTS = ASMAtomicReadU64(&pVM->tm.s.u64VirtualRawPrev);
-#ifdef IN_RC
-            Assert(!(ASMGetFlags() & X86_EFL_IF));
-#else
-            if (RT_UNLIKELY(u8ApicId != ASMGetApicId()))
-                continue;
-            if (RT_UNLIKELY(    pGipCpu->u32TransactionId != u32TransactionId
-                            ||  (u32TransactionId & 1)))
-                continue;
-#endif
-        }
-        break;
-    }
-
-    /*
-     * Calc NanoTS delta.
-     */
-    u64Delta -= u64TSC;
-    if (u64Delta > u32UpdateIntervalTSC)
-    {
-        /*
-         * We've expired the interval, cap it. If we're here for the 2nd
-         * time without any GIP update in-between, the checks against
-         * pVM->tm.s.u64VirtualRawPrev below will force 1ns stepping.
-         */
-        u64Delta = u32UpdateIntervalTSC;
-    }
-#if !defined(_MSC_VER) || defined(RT_ARCH_AMD64) /* GCC makes very pretty code from these two inline calls, while MSC cannot. */
-    u64Delta = ASMMult2xU32RetU64((uint32_t)u64Delta, u32NanoTSFactor0);
-    u64Delta = ASMDivU64ByU32RetU32(u64Delta, u32UpdateIntervalTSC);
-#else
-    __asm
-    {
-        mov     eax, dword ptr [u64Delta]
-        mul     dword ptr [u32NanoTSFactor0]
-        div     dword ptr [u32UpdateIntervalTSC]
-        mov     dword ptr [u64Delta], eax
-        xor     edx, edx
-        mov     dword ptr [u64Delta + 4], edx
-    }
-#endif
-
-    /*
-     * Calculate the time and compare it with the previously returned value.
-     *
-     * Since this function is called *very* frequently when the VM is running
-     * and then mostly on EMT, we can restrict the valid range of the delta
-     * (-1s to 2*GipUpdates) and simplify/optimize the default path.
-     */
-    u64NanoTS += u64Delta;
-    uint64_t u64DeltaPrev = u64NanoTS - u64PrevNanoTS;
-    if (RT_LIKELY(u64DeltaPrev < 1000000000 /* 1s */))
-        /* frequent - less than 1s since last call. */;
-    else if (   (int64_t)u64DeltaPrev < 0
-             && (int64_t)u64DeltaPrev + u32NanoTSFactor0 * 2 > 0)
-    {
-        /* occasional - u64NanoTS is in the 'past' relative to previous returns. */
-        ASMAtomicIncU32(&pVM->tm.s.CTX_SUFF(VirtualGetRawData).c1nsSteps);
-        u64NanoTS = u64PrevNanoTS + 1;
-#ifndef IN_RING3
-        VM_FF_SET(pVM, VM_FF_TO_R3); /* S10 hack */
-#endif
-    }
-    else if (u64PrevNanoTS)
-    {
-        /* Something has gone bust, if negative offset it's real bad. */
-        ASMAtomicIncU32(&pVM->tm.s.CTX_SUFF(VirtualGetRawData).cBadPrev);
-        if ((int64_t)u64DeltaPrev < 0)
-            LogRel(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 u64Delta=%#RX64\n",
-                    u64DeltaPrev, u64PrevNanoTS, u64NanoTS, u64Delta));
-        else
-            Log(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 u64Delta=%#RX64 (debugging?)\n",
-                 u64DeltaPrev, u64PrevNanoTS, u64NanoTS, u64Delta));
-#ifdef DEBUG_bird
-        /** @todo there are some hickups during boot and reset that can cause 2-5 seconds delays. Investigate... */
-        AssertMsg(u64PrevNanoTS > UINT64_C(100000000000) /* 100s */,
-                  ("u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 u64Delta=%#RX64\n",
-                  u64DeltaPrev, u64PrevNanoTS, u64NanoTS, u64Delta));
-#endif
-    }
-    /* else: We're resuming (see TMVirtualResume). */
-    if (RT_LIKELY(ASMAtomicCmpXchgU64(&pVM->tm.s.u64VirtualRawPrev, u64NanoTS, u64PrevNanoTS)))
-        return u64NanoTS;
-
-    /*
-     * Attempt updating the previous value, provided we're still ahead of it.
-     *
-     * There is no point in recalculating u64NanoTS because we got preempted or if
-     * we raced somebody while the GIP was updated, since these are events
-     * that might occur at any point in the return path as well.
-     */
-    for (int cTries = 50;;)
-    {
-        u64PrevNanoTS = ASMAtomicReadU64(&pVM->tm.s.u64VirtualRawPrev);
-        if (u64PrevNanoTS >= u64NanoTS)
-            break;
-        if (ASMAtomicCmpXchgU64(&pVM->tm.s.u64VirtualRawPrev, u64NanoTS, u64PrevNanoTS))
-            break;
-        AssertBreak(--cTries <= 0);
-        if (cTries < 25 && !VM_IS_EMT(pVM)) /* give up early */
-            break;
-    }
-
-    return u64NanoTS;
-}
-
-#endif
 
 
Index: trunk/src/VBox/VMM/VMMR0/VMMR0.def
===================================================================
--- trunk/src/VBox/VMM/VMMR0/VMMR0.def	(revision 54269)
+++ trunk/src/VBox/VMM/VMMR0/VMMR0.def	(revision 54270)
@@ -88,13 +88,9 @@
     RTCrc32
     RTOnceSlow
-    RTTimeNanoTSLegacyInvariantNoDelta
-    RTTimeNanoTSLegacyInvariantWithDelta
-    RTTimeNanoTSLegacySyncNoDelta
-    RTTimeNanoTSLegacySyncWithDelta
+    RTTimeNanoTSLegacySyncInvarNoDelta
+    RTTimeNanoTSLegacySyncInvarWithDelta
     RTTimeNanoTSLegacyAsync
-    RTTimeNanoTSLFenceInvariantNoDelta
-    RTTimeNanoTSLFenceInvariantWithDelta
-    RTTimeNanoTSLFenceSyncNoDelta
-    RTTimeNanoTSLFenceSyncWithDelta
+    RTTimeNanoTSLFenceSyncInvarNoDelta
+    RTTimeNanoTSLFenceSyncInvarWithDelta
     RTTimeNanoTSLFenceAsync
     RTTimeSystemNanoTS
Index: trunk/src/VBox/VMM/VMMR3/TM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/TM.cpp	(revision 54269)
+++ trunk/src/VBox/VMM/VMMR3/TM.cpp	(revision 54270)
@@ -271,32 +271,11 @@
      * Setup the VirtualGetRaw backend.
      */
-    pVM->tm.s.VirtualGetRawDataR3.pu64Prev = &pVM->tm.s.u64VirtualRawPrev;
-    pVM->tm.s.VirtualGetRawDataR3.pfnBad = tmVirtualNanoTSBad;
-    pVM->tm.s.VirtualGetRawDataR3.pfnRediscover = tmVirtualNanoTSRediscover;
-    if (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2)
-    {
-        if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
-            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                                         ? RTTimeNanoTSLFenceInvariantNoDelta : RTTimeNanoTSLFenceInvariantWithDelta;
-        else if (pGip->u32Mode == SUPGIPMODE_SYNC_TSC)
-            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                                         ? RTTimeNanoTSLFenceSyncNoDelta      : RTTimeNanoTSLFenceSyncWithDelta;
-        else
-            pVM->tm.s.pfnVirtualGetRawR3 = RTTimeNanoTSLFenceAsync;
-    }
-    else
-    {
-        if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
-            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                                         ? RTTimeNanoTSLegacyInvariantNoDelta   : RTTimeNanoTSLegacyInvariantWithDelta;
-        else if (pGip->u32Mode == SUPGIPMODE_SYNC_TSC)
-            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
-                                         ? RTTimeNanoTSLegacySyncNoDelta        : RTTimeNanoTSLegacySyncWithDelta;
-        else
-            pVM->tm.s.pfnVirtualGetRawR3 = RTTimeNanoTSLegacyAsync;
-    }
-
-    pVM->tm.s.VirtualGetRawDataRC.pu64Prev = MMHyperR3ToRC(pVM, (void *)&pVM->tm.s.u64VirtualRawPrev);
-    pVM->tm.s.VirtualGetRawDataR0.pu64Prev = MMHyperR3ToR0(pVM, (void *)&pVM->tm.s.u64VirtualRawPrev);
+    pVM->tm.s.pfnVirtualGetRawR3                 = tmVirtualNanoTSRediscover;
+    pVM->tm.s.VirtualGetRawDataR3.pfnRediscover  = tmVirtualNanoTSRediscover;
+    pVM->tm.s.VirtualGetRawDataR3.pfnBad         = tmVirtualNanoTSBadPrev;
+    pVM->tm.s.VirtualGetRawDataR3.pfnBadCpuIndex = tmVirtualNanoTSBadCpuIndex;
+    pVM->tm.s.VirtualGetRawDataR3.pu64Prev       = &pVM->tm.s.u64VirtualRawPrev;
+    pVM->tm.s.VirtualGetRawDataRC.pu64Prev       = MMHyperR3ToRC(pVM, (void *)&pVM->tm.s.u64VirtualRawPrev);
+    pVM->tm.s.VirtualGetRawDataR0.pu64Prev       = MMHyperR3ToR0(pVM, (void *)&pVM->tm.s.u64VirtualRawPrev);
     AssertRelease(pVM->tm.s.VirtualGetRawDataR0.pu64Prev);
     /* The rest is done in TMR3InitFinalize since it's too early to call PDM. */
@@ -1038,48 +1017,4 @@
 
 /**
- * Translation of pfnVirtualGetRawR3 to symbol names.
- *
- * @remarks This is a global variable because some gcc versions have their
- *          attribute/visibility warnings messed up.
- */
-static const struct
-{
-    PFNTIMENANOTSINTERNAL   pfnR3Worker;
-    const char             *pszName;
-} g_aNanoTsWorkers[] =
-{
-#define ENTRY(a) { a, #a }
-    ENTRY(RTTimeNanoTSLegacyAsync),
-    ENTRY(RTTimeNanoTSLegacyInvariantNoDelta),
-    ENTRY(RTTimeNanoTSLegacyInvariantWithDelta),
-    ENTRY(RTTimeNanoTSLegacySyncNoDelta),
-    ENTRY(RTTimeNanoTSLegacySyncWithDelta),
-    ENTRY(RTTimeNanoTSLFenceAsync),
-    ENTRY(RTTimeNanoTSLFenceInvariantNoDelta),
-    ENTRY(RTTimeNanoTSLFenceInvariantWithDelta),
-    ENTRY(RTTimeNanoTSLFenceSyncNoDelta),
-    ENTRY(RTTimeNanoTSLFenceSyncWithDelta),
-#undef ENTRY
-};
-
-
-/**
- * Translates TM::pfnVirtualGetRawR3 to a symbol name that we can find in ring-0
- * and raw-mode context.
- *
- * @returns Symbol name.
- * @param   pfnWorkerR3         The TM::pfnVirtualGetRawR3 value.
- */
-static const char *tmR3GetRTTimeNanoName(PFNTIMENANOTSINTERNAL pfnR3Worker)
-{
-    for (uint32_t iNanoTs = 0; iNanoTs < RT_ELEMENTS(g_aNanoTsWorkers); iNanoTs++)
-        if (pfnR3Worker == g_aNanoTsWorkers[iNanoTs].pfnR3Worker)
-            return g_aNanoTsWorkers[iNanoTs].pszName;
-    AssertFatalFailed();
-    return NULL;
-}
-
-
-/**
  * Finalizes the TM initialization.
  *
@@ -1094,21 +1029,22 @@
      * Resolve symbols.
      */
-    const char *pszRTTimeNanoTS = tmR3GetRTTimeNanoName(pVM->tm.s.pfnVirtualGetRawR3);
     if (!HMIsEnabled(pVM))
     {
-        rc = PDMR3LdrGetSymbolRC(pVM, NULL, "tmVirtualNanoTSBad",           &pVM->tm.s.VirtualGetRawDataRC.pfnBad);
+        rc = PDMR3LdrGetSymbolRC(pVM, NULL, "tmVirtualNanoTSBadPrev",       &pVM->tm.s.VirtualGetRawDataRC.pfnBad);
+        AssertRCReturn(rc, rc);
+        rc = PDMR3LdrGetSymbolRC(pVM, NULL, "tmVirtualNanoTSBadCpuIndex",   &pVM->tm.s.VirtualGetRawDataRC.pfnBadCpuIndex);
         AssertRCReturn(rc, rc);
         rc = PDMR3LdrGetSymbolRC(pVM, NULL, "tmVirtualNanoTSRediscover",    &pVM->tm.s.VirtualGetRawDataRC.pfnRediscover);
         AssertRCReturn(rc, rc);
-        rc = PDMR3LdrGetSymbolRC(pVM, NULL, pszRTTimeNanoTS,                &pVM->tm.s.pfnVirtualGetRawRC);
-        AssertRCReturn(rc, rc);
-    }
-
-    rc = PDMR3LdrGetSymbolR0(pVM, NULL, "tmVirtualNanoTSBad",           &pVM->tm.s.VirtualGetRawDataR0.pfnBad);
+        pVM->tm.s.pfnVirtualGetRawRC = pVM->tm.s.VirtualGetRawDataRC.pfnRediscover;
+    }
+
+    rc = PDMR3LdrGetSymbolR0(pVM, NULL, "tmVirtualNanoTSBadPrev",       &pVM->tm.s.VirtualGetRawDataR0.pfnBad);
+    AssertRCReturn(rc, rc);
+    rc = PDMR3LdrGetSymbolR0(pVM, NULL, "tmVirtualNanoTSBadCpuIndex",   &pVM->tm.s.VirtualGetRawDataR0.pfnBadCpuIndex);
     AssertRCReturn(rc, rc);
     rc = PDMR3LdrGetSymbolR0(pVM, NULL, "tmVirtualNanoTSRediscover",    &pVM->tm.s.VirtualGetRawDataR0.pfnRediscover);
     AssertRCReturn(rc, rc);
-    rc = PDMR3LdrGetSymbolR0(pVM, NULL, pszRTTimeNanoTS,                &pVM->tm.s.pfnVirtualGetRawR0);
-    AssertRCReturn(rc, rc);
+    pVM->tm.s.pfnVirtualGetRawR0 = pVM->tm.s.VirtualGetRawDataR0.pfnRediscover;
 
 #ifndef VBOX_WITHOUT_NS_ACCOUNTING
@@ -1140,7 +1076,5 @@
 VMM_INT_DECL(void) TMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
 {
-    int rc;
     LogFlow(("TMR3Relocate\n"));
-    NOREF(offDelta);
 
     pVM->tm.s.paTimerQueuesR0 = MMHyperR3ToR0(pVM, pVM->tm.s.paTimerQueuesR3);
@@ -1148,15 +1082,11 @@
     if (!HMIsEnabled(pVM))
     {
-        pVM->tm.s.pvGIPRC = MMHyperR3ToRC(pVM, pVM->tm.s.pvGIPR3);
-        pVM->tm.s.paTimerQueuesRC = MMHyperR3ToRC(pVM, pVM->tm.s.paTimerQueuesR3);
-        pVM->tm.s.VirtualGetRawDataRC.pu64Prev = MMHyperR3ToRC(pVM, (void *)&pVM->tm.s.u64VirtualRawPrev);
-        AssertFatal(pVM->tm.s.VirtualGetRawDataRC.pu64Prev);
-        rc = PDMR3LdrGetSymbolRC(pVM, NULL, "tmVirtualNanoTSBad",           &pVM->tm.s.VirtualGetRawDataRC.pfnBad);
-        AssertFatalRC(rc);
-        rc = PDMR3LdrGetSymbolRC(pVM, NULL, "tmVirtualNanoTSRediscover",    &pVM->tm.s.VirtualGetRawDataRC.pfnRediscover);
-        AssertFatalRC(rc);
-        const char *pszRTTimeNanoTS = tmR3GetRTTimeNanoName(pVM->tm.s.pfnVirtualGetRawR3);
-        rc = PDMR3LdrGetSymbolRC(pVM, NULL, pszRTTimeNanoTS,                &pVM->tm.s.pfnVirtualGetRawRC);
-        AssertFatalRC(rc);
+        pVM->tm.s.pvGIPRC           = MMHyperR3ToRC(pVM, pVM->tm.s.pvGIPR3);
+        pVM->tm.s.paTimerQueuesRC   = MMHyperR3ToRC(pVM, pVM->tm.s.paTimerQueuesR3);
+        pVM->tm.s.VirtualGetRawDataRC.pu64Prev       += offDelta;
+        pVM->tm.s.VirtualGetRawDataRC.pfnBad         += offDelta;
+        pVM->tm.s.VirtualGetRawDataRC.pfnBadCpuIndex += offDelta;
+        pVM->tm.s.VirtualGetRawDataRC.pfnRediscover  += offDelta;
+        pVM->tm.s.pfnVirtualGetRawRC                 += offDelta;
     }
 
Index: trunk/src/VBox/VMM/VMMRC/VMMRC.def
===================================================================
--- trunk/src/VBox/VMM/VMMRC/VMMRC.def	(revision 54269)
+++ trunk/src/VBox/VMM/VMMRC/VMMRC.def	(revision 54270)
@@ -65,4 +65,5 @@
     MMGCRamWriteNoTrapHandler
     MMGCRamReadNoTrapHandler
+    VMMGetCpu
     VMMGetSvnRev
     VMMRCProbeFire
@@ -92,13 +93,9 @@
     RTAssertShouldPanic
     RTLogDefaultInstance
-    RTTimeNanoTSLegacyInvariantNoDelta
-    RTTimeNanoTSLegacyInvariantWithDelta
-    RTTimeNanoTSLegacySyncNoDelta
-    RTTimeNanoTSLegacySyncWithDelta
+    RTTimeNanoTSLegacySyncInvarNoDelta
+    RTTimeNanoTSLegacySyncInvarWithDelta
     RTTimeNanoTSLegacyAsync
-    RTTimeNanoTSLFenceInvariantNoDelta
-    RTTimeNanoTSLFenceInvariantWithDelta
-    RTTimeNanoTSLFenceSyncNoDelta
-    RTTimeNanoTSLFenceSyncWithDelta
+    RTTimeNanoTSLFenceSyncInvarNoDelta
+    RTTimeNanoTSLFenceSyncInvarWithDelta
     RTTimeNanoTSLFenceAsync
     RTTimeNanoTS
Index: trunk/src/VBox/VMM/include/TMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/TMInternal.h	(revision 54269)
+++ trunk/src/VBox/VMM/include/TMInternal.h	(revision 54270)
@@ -766,6 +766,8 @@
 int                     tmVirtualPauseLocked(PVM pVM);
 int                     tmVirtualResumeLocked(PVM pVM);
-DECLEXPORT(void)        tmVirtualNanoTSBad(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS);
+DECLEXPORT(void)        tmVirtualNanoTSBadPrev(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS,
+                                               uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS);
 DECLEXPORT(uint64_t)    tmVirtualNanoTSRediscover(PRTTIMENANOTSDATA pData);
+DECLEXPORT(uint64_t)    tmVirtualNanoTSBadCpuIndex(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
 
 #ifdef IN_RING3
