Changeset 54270 in vbox for trunk/src/VBox/Runtime/common/time
- Timestamp:
- Feb 18, 2015 4:11:34 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 98341
- Location:
- trunk/src/VBox/Runtime/common/time
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/time/timesup.cpp
r54252 r54270 52 52 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalFallback(PRTTIMENANOTSDATA pData); 53 53 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalRediscover(PRTTIMENANOTSDATA pData); 54 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalBadCpuIndex(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu); 54 55 #endif 55 56 … … 65 66 static RTTIMENANOTSDATA g_TimeNanoTSData = 66 67 { 67 /* .pu64Prev = */ &g_TimeNanoTSPrev,68 /* .pfnBad = */ rtTimeNanoTSInternalBitch,69 /* .pfnRediscover = */ rtTimeNanoTSInternalRediscover,70 /* .p vDummy = */ NULL,71 /* .c1nsSteps = */ 0,72 /* .cExpired = */ 0,73 /* .cBadPrev = */ 0,74 /* .cUpdateRaces = */ 068 /* .pu64Prev = */ &g_TimeNanoTSPrev, 69 /* .pfnBad = */ rtTimeNanoTSInternalBitch, 70 /* .pfnRediscover = */ rtTimeNanoTSInternalRediscover, 71 /* .pfnBadCpuIndex = */ rtTimeNanoTSInternalBadCpuIndex, 72 /* .c1nsSteps = */ 0, 73 /* .cExpired = */ 0, 74 /* .cBadPrev = */ 0, 75 /* .cUpdateRaces = */ 0 75 76 }; 76 77 77 /** The index into g_apfnWorkers for the function to use. 78 * This cannot be a pointer because that'll break down in GC due to code relocation. */ 79 static uint32_t g_iWorker = 0; 78 # ifdef IN_RC 80 79 /** Array of rtTimeNanoTSInternal worker functions. 81 80 * This array is indexed by g_iWorker. */ 82 81 static const PFNTIMENANOTSINTERNAL g_apfnWorkers[] = 83 82 { 84 # define RTTIMENANO_WORKER_DETECT083 # define RTTIMENANO_WORKER_DETECT 0 85 84 rtTimeNanoTSInternalRediscover, 86 85 87 # define RTTIMENANO_WORKER_LEGACY_SYNC_NO_DELTA188 RTTimeNanoTSLegacySync NoDelta,89 # define RTTIMENANO_WORKER_LEGACY_SYNC_WITH_DELTA290 RTTimeNanoTSLegacySync WithDelta,91 # define RTTIMENANO_WORKER_LEGACY_ASYNC386 # define RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_NO_DELTA 1 87 RTTimeNanoTSLegacySyncInvarNoDelta, 88 # define RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_WITH_DELTA 2 89 RTTimeNanoTSLegacySyncInvarWithDelta, 90 # define RTTIMENANO_WORKER_LEGACY_ASYNC 3 92 91 RTTimeNanoTSLegacyAsync, 93 # define RTTIMENANO_WORKER_LEGACY_INVAR_NO_DELTA 4 94 RTTimeNanoTSLFenceInvariantNoDelta, 95 # define RTTIMENANO_WORKER_LEGACY_INVAR_WITH_DELTA 5 96 RTTimeNanoTSLFenceInvariantWithDelta, 97 98 # define RTTIMENANO_WORKER_LFENCE_SYNC_NO_DELTA 6 99 RTTimeNanoTSLFenceSyncNoDelta, 100 # define RTTIMENANO_WORKER_LFENCE_SYNC_WITH_DELTA 7 101 RTTimeNanoTSLFenceSyncWithDelta, 102 # define RTTIMENANO_WORKER_LFENCE_ASYNC 8 92 93 # define RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA 4 94 RTTimeNanoTSLFenceSyncInvarNoDelta, 95 # define RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA 5 96 RTTimeNanoTSLFenceSyncInvarWithDelta, 97 # define RTTIMENANO_WORKER_LFENCE_ASYNC 6 103 98 RTTimeNanoTSLFenceAsync, 104 # define RTTIMENANO_WORKER_LFENCE_INVAR_NO_DELTA 9 105 RTTimeNanoTSLFenceInvariantNoDelta, 106 # define RTTIMENANO_WORKER_LFENCE_INVAR_WITH_DELTA 10 107 RTTimeNanoTSLFenceInvariantWithDelta, 108 109 # define RTTIMENANO_WORKER_FALLBACK 11 99 100 # define RTTIMENANO_WORKER_FALLBACK 7 110 101 rtTimeNanoTSInternalFallback, 111 102 }; 112 113 114 /** 115 * Helper function that's used by the assembly routines when something goes bust. 116 * 117 * @param pData Pointer to the data structure. 118 * @param u64NanoTS The calculated nano ts. 119 * @param u64DeltaPrev The delta relative to the previously returned timestamp. 120 * @param u64PrevNanoTS The previously returned timestamp (as it was read it). 121 */ 122 static DECLCALLBACK(void) rtTimeNanoTSInternalBitch(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS) 103 /** The index into g_apfnWorkers for the function to use. 104 * @remarks This cannot be a pointer because that'll break down in RC due to 105 * code relocation. */ 106 static uint32_t g_iWorker = RTTIMENANO_WORKER_DETECT; 107 # else 108 /** Pointer to the worker */ 109 static PFNTIMENANOTSINTERNAL g_pfnWorker = rtTimeNanoTSInternalRediscover; 110 # endif /* IN_RC */ 111 112 113 /** 114 * @interface_method_impl{RTTIMENANOTSDATA, pfnBad} 115 */ 116 static DECLCALLBACK(void) rtTimeNanoTSInternalBitch(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, 117 uint64_t u64PrevNanoTS) 123 118 { 124 119 pData->cBadPrev++; … … 130 125 u64DeltaPrev, u64PrevNanoTS, u64NanoTS)); 131 126 } 127 128 /** 129 * @interface_method_impl{RTTIMENANOTSDATA, pfnBadCpuIndex} 130 */ 131 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalBadCpuIndex(PRTTIMENANOTSDATA pData, uint16_t idApic, 132 uint16_t iCpuSet, uint16_t iGipCpu) 133 { 134 # ifndef IN_RC 135 AssertMsgFailed(("idApic=%#x iCpuSet=%#x iGipCpu=%#x\n", idApic, iCpuSet, iGipCpu)); 136 return RTTimeSystemNanoTS(); 137 # else 138 RTAssertReleasePanic(); 139 return 0; 140 # endif 141 } 142 132 143 133 144 /** … … 147 158 return RTTimeSystemNanoTS(); 148 159 # else 160 RTAssertReleasePanic(); 149 161 return 0; 150 162 # endif … … 158 170 static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalRediscover(PRTTIMENANOTSDATA pData) 159 171 { 160 uint32_t iWorker; 161 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; 172 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; 173 # ifdef IN_RC 174 uint32_t iWorker; 175 # else 176 PFNTIMENANOTSINTERNAL pfnWorker; 177 # endif 162 178 if ( pGip 163 179 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC … … 167 183 { 168 184 if (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2) 169 iWorker = pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC 170 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 171 ? RTTIMENANO_WORKER_LFENCE_INVAR_NO_DELTA : RTTIMENANO_WORKER_LFENCE_INVAR_WITH_DELTA 172 : pGip->u32Mode == SUPGIPMODE_SYNC_TSC 173 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 174 ? RTTIMENANO_WORKER_LFENCE_SYNC_NO_DELTA : RTTIMENANO_WORKER_LFENCE_SYNC_WITH_DELTA 175 : RTTIMENANO_WORKER_LFENCE_ASYNC; 185 { 186 # ifdef IN_RC 187 iWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC 188 ? RTTIMENANO_WORKER_LFENCE_ASYNC 189 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 190 ? RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA 191 : RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA; 192 # elif defined(IN_RING0) 193 pfnWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC 194 ? RTTimeNanoTSLFenceAsync 195 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 196 ? RTTimeNanoTSLFenceSyncInvarNoDelta 197 : RTTimeNanoTSLFenceSyncInvarWithDelta; 198 # else 199 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 200 pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 201 ? RTTimeNanoTSLFenceAsyncUseIdtrLim 202 : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 203 ? RTTimeNanoTSLFenceAsyncUseRdtscp 204 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID 205 ? RTTimeNanoTSLFenceAsyncUseApicId 206 : rtTimeNanoTSInternalFallback; 207 else 208 pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 209 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO 210 ? RTTimeNanoTSLFenceSyncInvarNoDelta 211 : RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim 212 : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 213 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO 214 ? RTTimeNanoTSLFenceSyncInvarNoDelta 215 : RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp 216 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID 217 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 218 ? RTTimeNanoTSLFenceSyncInvarNoDelta 219 : RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId 220 : rtTimeNanoTSInternalFallback; 221 # endif 222 } 176 223 else 177 iWorker = pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC 178 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 179 ? RTTIMENANO_WORKER_LEGACY_INVAR_NO_DELTA : RTTIMENANO_WORKER_LEGACY_INVAR_WITH_DELTA 180 : pGip->u32Mode == SUPGIPMODE_SYNC_TSC 181 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 182 ? RTTIMENANO_WORKER_LEGACY_SYNC_NO_DELTA : RTTIMENANO_WORKER_LEGACY_SYNC_WITH_DELTA 183 : RTTIMENANO_WORKER_LEGACY_ASYNC; 224 { 225 # ifdef IN_RC 226 iWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC 227 ? RTTIMENANO_WORKER_LEGACY_ASYNC 228 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 229 ? RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_NO_DELTA : RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_WITH_DELTA; 230 # elif defined(IN_RING0) 231 pfnWorker = pGip->u32Mode == SUPGIPMODE_ASYNC_TSC 232 ? RTTimeNanoTSLegacyAsync 233 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 234 ? RTTimeNanoTSLegacySyncInvarNoDelta 235 : RTTimeNanoTSLegacySyncInvarWithDelta; 236 # else 237 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 238 pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 239 ? RTTimeNanoTSLegacyAsyncUseRdtscp 240 : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 241 ? RTTimeNanoTSLegacyAsyncUseIdtrLim 242 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID 243 ? RTTimeNanoTSLegacyAsyncUseApicId 244 : rtTimeNanoTSInternalFallback; 245 else 246 pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 247 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO 248 ? RTTimeNanoTSLegacySyncInvarNoDelta 249 : RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp 250 : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 251 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO 252 ? RTTimeNanoTSLegacySyncInvarNoDelta 253 : RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim 254 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID 255 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO 256 ? RTTimeNanoTSLegacySyncInvarNoDelta 257 : RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId 258 : rtTimeNanoTSInternalFallback; 259 # endif 260 } 184 261 } 185 262 else 263 # ifdef IN_RC 186 264 iWorker = RTTIMENANO_WORKER_FALLBACK; 187 265 # else 266 pfnWorker = rtTimeNanoTSInternalFallback; 267 # endif 268 269 # ifdef IN_RC 188 270 ASMAtomicWriteU32((uint32_t volatile *)&g_iWorker, iWorker); 189 271 return g_apfnWorkers[iWorker](pData); 272 # else 273 ASMAtomicWritePtr((void * volatile *)&g_pfnWorker, (void *)(uintptr_t)pfnWorker); 274 return pfnWorker(pData); 275 # endif 190 276 } 191 277 … … 199 285 { 200 286 #if !defined(IN_GUEST) && !defined(RT_NO_GIP) 287 # ifdef IN_RC 201 288 return g_apfnWorkers[g_iWorker](&g_TimeNanoTSData); 289 # else 290 return g_pfnWorker(&g_TimeNanoTSData); 291 # endif 202 292 #else 203 293 return RTTimeSystemNanoTS(); -
trunk/src/VBox/Runtime/common/time/timesupA.asm
r54202 r54270 29 29 %include "iprt/asmdefs.mac" 30 30 %include "VBox/sup.mac" 31 32 ; 33 ; Use the C reference implementation for now. 34 ; 35 %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." 36 This is out of date 37 This is out of date 38 This is out of date 31 39 32 40 -
trunk/src/VBox/Runtime/common/time/timesupref.cpp
r54202 r54270 37 37 #include <iprt/asm-amd64-x86.h> 38 38 #include <VBox/sup.h> 39 #ifdef IN_RC 40 # include <VBox/vmm/vmm.h> 41 # include <VBox/vmm/vm.h> 42 #endif 39 43 #include "internal/time.h" 40 44 41 45 42 #define GIP_MODE_SYNC_NO_DELTA 1 43 #define GIP_MODE_SYNC_WITH_DELTA 2 44 #define GIP_MODE_ASYNC 3 45 #define GIP_MODE_INVARIANT_NO_DELTA 4 46 #define GIP_MODE_INVARIANT_WITH_DELTA 5 47 #define IS_GIP_MODE_WITH_DELTA(a_enmMode) \ 48 ((a_enmMode) == GIP_MODE_SYNC_WITH_DELTA || (a_enmMode) == GIP_MODE_INVARIANT_WITH_DELTA) 46 #define TMPL_MODE_SYNC_INVAR_NO_DELTA 1 47 #define TMPL_MODE_SYNC_INVAR_WITH_DELTA 2 48 #define TMPL_MODE_ASYNC 3 49 49 50 50 51 51 /* 52 * Use the CPUID instruction for some kind of serialization. 53 */ 54 #define GIP_MODE GIP_MODE_SYNC_NO_DELTA 55 #undef USE_LFENCE 56 #define NEED_TRANSACTION_ID 57 #define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncNoDelta 52 * Use the XCHG instruction for some kind of serialization. 53 */ 54 #define TMPL_READ_FENCE() ASMReadFence() 55 56 #undef TMPL_MODE 57 #define TMPL_MODE TMPL_MODE_SYNC_INVAR_NO_DELTA 58 #undef TMPL_GET_CPU_METHOD 59 #define TMPL_GET_CPU_METHOD 0 60 #undef rtTimeNanoTSInternalRef 61 #define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarNoDelta 58 62 #include "timesupref.h" 59 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncNoDelta); 60 61 #undef GIP_MODE 62 #define GIP_MODE GIP_MODE_SYNC_NO_DELTA 63 #undef rtTimeNanoTSInternalRef 64 #define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncWithDelta 65 #include "timesupref.h" 66 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncWithDelta); 67 68 #undef GIP_MODE 69 #define GIP_MODE GIP_MODE_ASYNC 70 #ifdef IN_RC 71 # undef NEED_TRANSACTION_ID 63 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarNoDelta); 64 65 #ifdef IN_RING3 66 67 # undef TMPL_MODE 68 # define TMPL_MODE TMPL_MODE_SYNC_INVAR_WITH_DELTA 69 # undef TMPL_GET_CPU_METHOD 70 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_APIC_ID 71 # undef rtTimeNanoTSInternalRef 72 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId 73 # include "timesupref.h" 74 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId); 75 76 # undef TMPL_GET_CPU_METHOD 77 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 78 # undef rtTimeNanoTSInternalRef 79 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp 80 # include "timesupref.h" 81 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp); 82 83 # undef TMPL_GET_CPU_METHOD 84 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 85 # undef rtTimeNanoTSInternalRef 86 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim 87 # include "timesupref.h" 88 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim); 89 90 # undef TMPL_MODE 91 # define TMPL_MODE TMPL_MODE_ASYNC 92 # undef TMPL_GET_CPU_METHOD 93 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_APIC_ID 94 # undef rtTimeNanoTSInternalRef 95 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseApicId 96 # include "timesupref.h" 97 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseApicId); 98 99 # undef TMPL_GET_CPU_METHOD 100 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 101 # undef rtTimeNanoTSInternalRef 102 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseRdtscp 103 # include "timesupref.h" 104 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseRdtscp); 105 106 # undef TMPL_GET_CPU_METHOD 107 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 108 # undef rtTimeNanoTSInternalRef 109 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseIdtrLim 110 # include "timesupref.h" 111 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseIdtrLim); 112 113 #else /* IN_RC || IN_RING0: Disable interrupts and call getter function. */ 114 115 # undef TMPL_MODE 116 # define TMPL_MODE TMPL_MODE_SYNC_INVAR_WITH_DELTA 117 # undef TMPL_GET_CPU_METHOD 118 # define TMPL_GET_CPU_METHOD UINT32_MAX 119 # undef rtTimeNanoTSInternalRef 120 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacySyncInvarWithDelta 121 # include "timesupref.h" 122 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacySyncInvarWithDelta); 123 124 # undef TMPL_MODE 125 # define TMPL_MODE TMPL_MODE_ASYNC 126 # undef rtTimeNanoTSInternalRef 127 # define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsync 128 # include "timesupref.h" 129 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsync); 130 72 131 #endif 73 #undef rtTimeNanoTSInternalRef74 #define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsync75 #include "timesupref.h"76 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsync);77 78 #undef GIP_MODE79 #define GIP_MODE GIP_MODE_INVARIANT_NO_DELTA80 #undef NEED_TRANSACTION_ID81 #define NEED_TRANSACTION_ID82 #undef rtTimeNanoTSInternalRef83 #define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyInvariantNoDelta84 #include "timesupref.h"85 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyInvariantNoDelta);86 87 #undef GIP_MODE88 #define GIP_MODE GIP_MODE_INVARIANT_WITH_DELTA89 #undef rtTimeNanoTSInternalRef90 #define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyInvariantWithDelta91 #include "timesupref.h"92 RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyInvariantWithDelta);93 132 94 133 … … 96 135 * Use LFENCE for load serialization. 97 136 */ 98 #undef GIP_MODE 99 #define GIP_MODE GIP_MODE_SYNC_NO_DELTA 100 #define USE_LFENCE 101 #undef NEED_TRANSACTION_ID 102 #define NEED_TRANSACTION_ID 137 #undef TMPL_READ_FENCE 138 #define TMPL_READ_FENCE() ASMReadFenceSSE2() 139 140 #undef TMPL_MODE 141 #define TMPL_MODE TMPL_MODE_SYNC_INVAR_NO_DELTA 142 #undef TMPL_GET_CPU_METHOD 143 #define TMPL_GET_CPU_METHOD 0 103 144 #undef rtTimeNanoTSInternalRef 104 #define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncNoDelta145 #define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarNoDelta 105 146 #include "timesupref.h" 106 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncNoDelta); 107 108 #undef GIP_MODE 109 #define GIP_MODE GIP_MODE_SYNC_WITH_DELTA 110 #undef rtTimeNanoTSInternalRef 111 #define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncWithDelta 112 #include "timesupref.h" 113 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncWithDelta); 114 115 #undef GIP_MODE 116 #define GIP_MODE GIP_MODE_ASYNC 117 #ifdef IN_RC 118 # undef NEED_TRANSACTION_ID 147 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarNoDelta); 148 149 #ifdef IN_RING3 150 151 # undef TMPL_MODE 152 # define TMPL_MODE TMPL_MODE_SYNC_INVAR_WITH_DELTA 153 # undef TMPL_GET_CPU_METHOD 154 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_APIC_ID 155 # undef rtTimeNanoTSInternalRef 156 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId 157 # include "timesupref.h" 158 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId); 159 160 # undef TMPL_GET_CPU_METHOD 161 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 162 # undef rtTimeNanoTSInternalRef 163 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp 164 # include "timesupref.h" 165 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp); 166 167 # undef TMPL_GET_CPU_METHOD 168 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 169 # undef rtTimeNanoTSInternalRef 170 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim 171 # include "timesupref.h" 172 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim); 173 174 # undef TMPL_MODE 175 # define TMPL_MODE TMPL_MODE_ASYNC 176 # undef TMPL_GET_CPU_METHOD 177 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_APIC_ID 178 # undef rtTimeNanoTSInternalRef 179 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseApicId 180 # include "timesupref.h" 181 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseApicId); 182 183 # undef TMPL_GET_CPU_METHOD 184 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 185 # undef rtTimeNanoTSInternalRef 186 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseRdtscp 187 # include "timesupref.h" 188 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseRdtscp); 189 190 # undef TMPL_GET_CPU_METHOD 191 # define TMPL_GET_CPU_METHOD SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 192 # undef rtTimeNanoTSInternalRef 193 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseIdtrLim 194 # include "timesupref.h" 195 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseIdtrLim); 196 197 #else /* IN_RC || IN_RING0: Disable interrupts and call getter function. */ 198 199 # undef TMPL_MODE 200 # define TMPL_MODE TMPL_MODE_SYNC_INVAR_WITH_DELTA 201 # undef TMPL_GET_CPU_METHOD 202 # define TMPL_GET_CPU_METHOD UINT32_MAX 203 # undef rtTimeNanoTSInternalRef 204 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceSyncInvarWithDelta 205 # include "timesupref.h" 206 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceSyncInvarWithDelta); 207 208 # undef TMPL_MODE 209 # define TMPL_MODE TMPL_MODE_ASYNC 210 # undef rtTimeNanoTSInternalRef 211 # define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsync 212 # include "timesupref.h" 213 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsync); 214 119 215 #endif 120 #undef rtTimeNanoTSInternalRef121 #define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsync122 #include "timesupref.h"123 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsync);124 125 #undef GIP_MODE126 #define GIP_MODE GIP_MODE_INVARIANT_NO_DELTA127 #undef NEED_TRANSACTION_ID128 #define NEED_TRANSACTION_ID129 #undef rtTimeNanoTSInternalRef130 #define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceInvariantNoDelta131 #include "timesupref.h"132 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceInvariantNoDelta);133 134 #undef GIP_MODE135 #define GIP_MODE GIP_MODE_INVARIANT_WITH_DELTA136 #undef rtTimeNanoTSInternalRef137 #define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceInvariantWithDelta138 #include "timesupref.h"139 RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceInvariantWithDelta);140 216 141 217 -
trunk/src/VBox/Runtime/common/time/timesupref.h
r54202 r54270 45 45 { 46 46 uint64_t u64Delta; 47 #if IS_GIP_MODE_WITH_DELTA(GIP_MODE)47 #if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA 48 48 int64_t i64TscDelta; 49 # ifdef IN_RING3 50 PSUPGIPCPU pGipCpuAttemptedTscRecalibration = NULL; 51 # endif 49 52 #endif 50 53 uint32_t u32NanoTSFactor0; … … 53 56 uint32_t u32UpdateIntervalTSC; 54 57 uint64_t u64PrevNanoTS; 58 AssertCompile(RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS)); 55 59 56 60 /* … … 59 63 for (;;) 60 64 { 65 #ifndef IN_RING3 /* This simplifies and improves everything. */ 66 RTCCUINTREG const uFlags = ASMIntDisableFlags(); 67 #endif 68 69 /* 70 * Check that the GIP is sane and that the premises for this worker function 71 * hasn't changed (CPU onlined with bad delta or missing features). 72 */ 61 73 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage; 62 #ifdef IN_RING3 63 if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC)) 64 return pData->pfnRediscover(pData); 65 #endif 66 #if GIP_MODE == GIP_MODE_ASYNC || IS_GIP_MODE_WITH_DELTA(GIP_MODE) 67 uint8_t const u8ApicId = ASMGetApicId(); 68 PSUPGIPCPU pGipCpu = &pGip->aCPUs[pGip->aiCpuFromApicId[u8ApicId]]; 69 #endif 70 71 #ifdef NEED_TRANSACTION_ID 72 # if GIP_MODE == GIP_MODE_ASYNC 73 uint32_t u32TransactionId = pGipCpu->u32TransactionId; 74 if ( RT_LIKELY(pGip) 75 && RT_LIKELY(pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC) 76 #if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA 77 && RT_LIKELY(pGip->enmUseTscDelta >= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO) 78 #else 79 && RT_LIKELY(pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO) 80 #endif 81 #if defined(IN_RING3) && TMPL_GET_CPU_METHOD != 0 && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID 82 && RT_LIKELY(pGip->fGetGipCpu & TMPL_GET_CPU_METHOD) 83 #endif 84 ) 85 { 86 /* 87 * Resolve pGipCpu if needed. If the instruction is serializing, we 88 * read the transaction id first if possible. 89 */ 90 #if TMPL_MODE == TMPL_MODE_ASYNC || TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA 91 # if defined(IN_RING0) 92 uint32_t const iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId()); 93 uint16_t const iGipCpu = iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx) 94 ? pGip->aiCpuFromCpuSetIdx[iCpuSet] : UINT16_MAX; 95 # elif defined(IN_RC) 96 uint32_t const iCpuSet = VMMGetCpu(&g_VM)->iHostCpuSet; 97 uint16_t const iGipCpu = iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx) 98 ? pGip->aiCpuFromCpuSetIdx[iCpuSet] : UINT16_MAX; 99 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_APIC_ID 100 # if TMPL_MODE != TMPL_MODE_ASYNC 101 uint32_t const u32TransactionId = pGip->aCPUs[0].u32TransactionId; 102 # endif 103 uint8_t const idApic = ASMGetApicId(); 104 uint16_t const iGipCpu = pGip->aiCpuFromApicId[idApic]; 105 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 106 # if TMPL_MODE != TMPL_MODE_ASYNC 107 uint32_t const u32TransactionId = pGip->aCPUs[0].u32TransactionId; 108 # endif 109 uint32_t uAux; 110 ASMReadTscWithAux(&uAux); 111 uint16_t const iCpuSet = uAux & (RTCPUSET_MAX_CPUS - 1); 112 uint16_t const iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet]; 113 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 114 uint16_t const cbLim = ASMGetIdtrLimit(); 115 uint16_t const iCpuSet = (cbLim - 256 * (ARCH_BITS == 64 ? 16 : 8)) & (RTCPUSET_MAX_CPUS - 1); 116 uint16_t const iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet]; 74 117 # else 75 uint32_t u32TransactionId = pGip->aCPUs[0].u32TransactionId; 76 # endif 77 # ifdef USE_LFENCE 78 ASMReadFenceSSE2(); 118 # error "What?" 119 # endif 120 if (RT_LIKELY(iGipCpu < pGip->cCpus)) 121 { 122 PSUPGIPCPU pGipCpu = &pGip->aCPUs[iGipCpu]; 123 #else 124 { 125 #endif 126 /* 127 * Get the transaction ID if necessary and we haven't already 128 * read it before a serializing instruction above. We can skip 129 * this for ASYNC_TSC mode in ring-0 and raw-mode context since 130 * we disable interrupts. 131 */ 132 #if TMPL_MODE == TMPL_MODE_ASYNC && defined(IN_RING3) 133 uint32_t const u32TransactionId = pGipCpu->u32TransactionId; 134 ASMCompilerBarrier(); 135 TMPL_READ_FENCE(); 136 #elif TMPL_MODE != TMPL_MODE_ASYNC \ 137 && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID \ 138 && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 139 uint32_t const u32TransactionId = pGip->aCPUs[0].u32TransactionId; 140 ASMCompilerBarrier(); 141 TMPL_READ_FENCE(); 142 #endif 143 144 /* 145 * Gather all the data we need. The mess at the end is to make 146 * sure all loads are done before we recheck the transaction ID 147 * without triggering serializing twice. 148 */ 149 u32NanoTSFactor0 = pGip->u32UpdateIntervalNS; 150 #if TMPL_MODE == TMPL_MODE_ASYNC 151 u32UpdateIntervalTSC = pGipCpu->u32UpdateIntervalTSC; 152 u64NanoTS = pGipCpu->u64NanoTS; 153 u64TSC = pGipCpu->u64TSC; 154 #else 155 u32UpdateIntervalTSC = pGip->aCPUs[0].u32UpdateIntervalTSC; 156 u64NanoTS = pGip->aCPUs[0].u64NanoTS; 157 u64TSC = pGip->aCPUs[0].u64TSC; 158 # if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA 159 i64TscDelta = pGipCpu->i64TSCDelta; 160 # endif 161 #endif 162 #if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 163 u64PrevNanoTS = ASMAtomicUoReadU64(pData->pu64Prev); 164 ASMCompilerBarrier(); 165 uint32_t uAux2; 166 u64Delta = ASMReadTscWithAux(&uAux2); /* serializing */ 167 #else 168 u64Delta = ASMReadTSC(); 169 u64PrevNanoTS = ASMAtomicUoReadU64(pData->pu64Prev); 170 ASMCompilerBarrier(); 171 # if TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID /* getting APIC will serialize */ \ 172 && (defined(IN_RING3) || TMPL_MODE != TMPL_MODE_ASYNC) 173 TMPL_READ_FENCE(); /* Expensive (~30 ticks). Would like convincing argumentation that let us remove it. */ 174 # endif 175 #endif 176 177 /* 178 * Check that we didn't change CPU. 179 */ 180 #if defined(IN_RING3) && ( TMPL_MODE == TMPL_MODE_ASYNC || TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA ) 181 # if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_APIC_ID 182 if (RT_LIKELY(ASMGetApicId() == idApic)) 183 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 184 if (RT_LIKELY(uAux2 == uAux)) 185 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 186 if (RT_LIKELY(ASMGetIdtrLimit() == cbLim)) 187 # endif 188 #endif 189 { 190 /* 191 * Check the transaction ID (see above for R0/RC + ASYNC). 192 */ 193 #if defined(IN_RING3) || TMPL_MODE != TMPL_MODE_ASYNC 194 # if TMPL_MODE == TMPL_MODE_ASYNC 195 if (RT_LIKELY(pGipCpu->u32TransactionId == u32TransactionId && !(u32TransactionId & 1) )) 79 196 # else 80 ASMReadFence(); 81 # endif 82 #endif 83 84 #if GIP_MODE == GIP_MODE_ASYNC 85 u32UpdateIntervalTSC = pGipCpu->u32UpdateIntervalTSC; 86 u64NanoTS = pGipCpu->u64NanoTS; 87 u64TSC = pGipCpu->u64TSC; 88 #else 89 u32UpdateIntervalTSC = pGip->aCPUs[0].u32UpdateIntervalTSC; 90 u64NanoTS = pGip->aCPUs[0].u64NanoTS; 91 u64TSC = pGip->aCPUs[0].u64TSC; 92 # if IS_GIP_MODE_WITH_DELTA(GIP_MODE) 93 i64TscDelta = pGipCpu->i64TSCDelta; 94 # endif 95 #endif 96 u32NanoTSFactor0 = pGip->u32UpdateIntervalNS; 97 u64Delta = ASMReadTSC(); 98 u64PrevNanoTS = ASMAtomicReadU64(pData->pu64Prev); 99 100 #ifdef NEED_TRANSACTION_ID 101 # if GIP_MODE == GIP_MODE_ASYNC || IS_GIP_MODE_WITH_DELTA(GIP_MODE) 102 if (RT_UNLIKELY(u8ApicId != ASMGetApicId())) 103 continue; 104 # elif defined(USE_LFENCE) 105 ASMWriteFenceSSE(); 197 if (RT_LIKELY(pGip->aCPUs[0].u32TransactionId == u32TransactionId && !(u32TransactionId & 1) )) 198 # endif 199 #endif 200 { 201 202 /* 203 * Apply the TSC delta. If the delta is invalid and the 204 * execution allows it, try trigger delta recalibration. 205 */ 206 #if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA && defined(IN_RING3) 207 if (RT_LIKELY( i64TscDelta != INT64_MAX 208 || pGipCpu == pGipCpuAttemptedTscRecalibration)) 209 #endif 210 { 211 #if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA 212 # ifndef IN_RING3 213 if (RT_LIKELY(i64TscDelta != INT64_MAX)) 214 # endif 215 u64Delta -= i64TscDelta; 216 #endif 217 218 /* 219 * Bingo! We've got a consistent set of data. 220 */ 221 #ifndef IN_RING3 222 ASMSetFlags(uFlags); 223 #endif 224 break; 225 } 226 #if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA && defined(IN_RING3) 227 /* 228 * Call into the support driver to try make it recalculate the delta. We 229 * remember which GIP CPU structure we're probably working on so we won't 230 * end up in a loop if the driver for some reason cannot get the job done. 231 */ 232 else /* else is unecessary, but helps checking the preprocessor spaghetti. */ 233 { 234 pGipCpuAttemptedTscRecalibration = pGipCpu; 235 uint64_t u64TscTmp; 236 uint16_t idApicUpdate; 237 int rc = SUPR3ReadTsc(&u64TscTmp, &idApicUpdate); 238 if (RT_SUCCESS(rc) && idApicUpdate <= RT_ELEMENTS(pGip->aiCpuFromApicId)) 239 { 240 uint32_t iUpdateGipCpu = pGip->aiCpuFromApicId[idApicUpdate]; 241 if (iUpdateGipCpu < pGip->cCpus) 242 pGipCpuAttemptedTscRecalibration = &pGip->aCPUs[iUpdateGipCpu]; 243 } 244 } 245 #endif 246 } 247 } 248 249 /* 250 * No joy must try again. 251 */ 252 #ifndef IN_RING3 253 ASMSetFlags(uFlags); 254 #endif 255 ASMNopPause(); 256 continue; 257 } 258 259 #if TMPL_MODE == TMPL_MODE_ASYNC || TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA 260 /* 261 * We've got a bad CPU or APIC index of some kind. 262 */ 263 else /* else is unecessary, but helps checking the preprocessor spaghetti. */ 264 { 265 # ifndef IN_RING3 266 ASMSetFlags(uFlags); 267 # endif 268 # if defined(IN_RING0) || defined(IN_RC) || TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID 269 return pData->pfnBadCpuIndex(pData, UINT16_MAX-1, iCpuSet, iGipCpu); 106 270 # else 107 ASMWriteFence(); 108 # endif 109 # if GIP_MODE == GIP_MODE_ASYNC 110 if (RT_UNLIKELY( pGipCpu->u32TransactionId != u32TransactionId 111 || (u32TransactionId & 1))) 112 continue; 113 # else 114 if (RT_UNLIKELY( pGip->aCPUs[0].u32TransactionId != u32TransactionId 115 || (u32TransactionId & 1))) 116 continue; 117 # endif 118 #endif 119 break; 271 return pData->pfnBadCpuIndex(pData, idApic, UINT16_MAX-1, iGipCpu); 272 # endif 273 } 274 #endif 275 } 276 277 /* 278 * Something changed in the GIP config or it was unmapped, figure out 279 * the right worker function to use now. 280 */ 281 #ifndef IN_RING3 282 ASMSetFlags(uFlags); 283 #endif 284 return pData->pfnRediscover(pData); 120 285 } 121 286 … … 124 289 */ 125 290 u64Delta -= u64TSC; 126 #if IS_GIP_MODE_WITH_DELTA(GIP_MODE)127 if (RT_LIKELY(i64TscDelta != INT64_MAX))128 u64Delta -= i64TscDelta;129 #endif130 291 if (RT_UNLIKELY(u64Delta > u32UpdateIntervalTSC)) 131 292 {
Note:
See TracChangeset
for help on using the changeset viewer.