VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/time/timesup.cpp@ 107192

Last change on this file since 107192 was 107192, checked in by vboxsync, 7 weeks ago

IPRT,VMM/TM: Support for GIP time on win.arm64. jiraref:VBP-1266

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 22.1 KB
Line 
1/* $Id: timesup.cpp 107192 2024-11-29 14:42:15Z vboxsync $ */
2/** @file
3 * IPRT - Time using SUPLib.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_TIME
42#include <iprt/time.h>
43#include "internal/iprt.h"
44
45#include <iprt/assert.h>
46#include <iprt/errcore.h>
47#include <iprt/log.h>
48#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
49# include <iprt/asm.h>
50# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
51# include <iprt/asm-amd64-x86.h>
52# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
53# include <iprt/asm-arm.h>
54# else
55# error "port me"
56# endif
57# include <iprt/x86.h>
58# include <VBox/sup.h>
59#endif
60#include "internal/time.h"
61
62
63/*********************************************************************************************************************************
64* Defined Constants And Macros *
65*********************************************************************************************************************************/
66#ifdef IN_RING3
67# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
68# define APPLICABLE_GET_CPU_FLAGS ( SUPGIPGETCPU_APIC_ID \
69 | SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS \
70 | SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS \
71 | SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL \
72 | SUPGIPGETCPU_APIC_ID_EXT_0B \
73 | SUPGIPGETCPU_APIC_ID_EXT_8000001E)
74# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
75# define APPLICABLE_GET_CPU_FLAGS (SUPGIPGETCPU_TPIDRRO_EL0)
76# else
77# error "port me"
78# endif
79#endif /* IN_RING3 */
80
81
82/*********************************************************************************************************************************
83* Internal Functions *
84*********************************************************************************************************************************/
85#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
86static DECLCALLBACK(void) rtTimeNanoTSInternalComplain(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev,
87 uint64_t u64PrevNanoTS);
88static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalFallback(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
89static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalRediscover(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
90static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalBadCpuIndex(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra,
91 uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
92#endif
93
94
95/*********************************************************************************************************************************
96* Global Variables *
97*********************************************************************************************************************************/
98#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
99/** The previous timestamp value returned by RTTimeNanoTS. */
100static uint64_t g_TimeNanoTSPrev = 0;
101
102/** The RTTimeNanoTS data structure that's passed down to the worker functions. */
103static RTTIMENANOTSDATA g_TimeNanoTSData =
104{
105 /* .pu64Prev = */ &g_TimeNanoTSPrev,
106 /* .pfnBad = */ rtTimeNanoTSInternalComplain,
107 /* .pfnRediscover = */ rtTimeNanoTSInternalRediscover,
108 /* .pfnBadCpuIndex = */ rtTimeNanoTSInternalBadCpuIndex,
109 /* .c1nsSteps = */ 0,
110 /* .cExpired = */ 0,
111 /* .cBadPrev = */ 0,
112 /* .cUpdateRaces = */ 0
113};
114
115# ifdef IN_RC
116/** Array of rtTimeNanoTSInternal worker functions.
117 * This array is indexed by g_iWorker. */
118static const PFNTIMENANOTSINTERNAL g_apfnWorkers[] =
119{
120# define RTTIMENANO_WORKER_DETECT 0
121 rtTimeNanoTSInternalRediscover,
122
123# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
124# define RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_NO_DELTA 1
125 RTTimeNanoTSLegacySyncInvarNoDelta,
126# define RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_WITH_DELTA 2
127 RTTimeNanoTSLegacySyncInvarWithDelta,
128# define RTTIMENANO_WORKER_LEGACY_ASYNC 3
129 RTTimeNanoTSLegacyAsync,
130
131# define RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA 4
132 RTTimeNanoTSLFenceSyncInvarNoDelta,
133# define RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA 5
134 RTTimeNanoTSLFenceSyncInvarWithDelta,
135# define RTTIMENANO_WORKER_LFENCE_ASYNC 6
136 RTTimeNanoTSLFenceAsync,
137# else
138# error "port me"
139# endif
140
141# define RTTIMENANO_WORKER_FALLBACK 7
142 rtTimeNanoTSInternalFallback,
143};
144/** The index into g_apfnWorkers for the function to use.
145 * @remarks This cannot be a pointer because that'll break down in RC due to
146 * code relocation. */
147static uint32_t g_iWorker = RTTIMENANO_WORKER_DETECT;
148# else /* !IN_RC */
149/** Pointer to the worker */
150static PFNTIMENANOTSINTERNAL g_pfnWorker = rtTimeNanoTSInternalRediscover;
151# endif /* !IN_RC */
152
153
154/**
155 * @interface_method_impl{RTTIMENANOTSDATA,pfnBad}
156 */
157static DECLCALLBACK(void) rtTimeNanoTSInternalComplain(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev,
158 uint64_t u64PrevNanoTS)
159{
160 pData->cBadPrev++;
161 if ((int64_t)u64DeltaPrev < 0)
162 LogRel(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64\n",
163 u64DeltaPrev, u64PrevNanoTS, u64NanoTS));
164 else
165 Log(("TM: u64DeltaPrev=%RI64 u64PrevNanoTS=0x%016RX64 u64NanoTS=0x%016RX64 (debugging?)\n",
166 u64DeltaPrev, u64PrevNanoTS, u64NanoTS));
167}
168
169/**
170 * @interface_method_impl{RTTIMENANOTSDATA,pfnBadCpuIndex}
171 */
172static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalBadCpuIndex(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra,
173 uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu)
174{
175 RT_NOREF_PV(pData); RT_NOREF_PV(idApic); RT_NOREF_PV(iCpuSet); RT_NOREF_PV(iGipCpu);
176# ifndef IN_RC
177 AssertMsgFailed(("idApic=%#x iCpuSet=%#x iGipCpu=%#x\n", idApic, iCpuSet, iGipCpu));
178 if (pExtra)
179 pExtra->uTSCValue = ASMReadTSC();
180 return RTTimeSystemNanoTS();
181# else
182 RTAssertReleasePanic();
183 return 0;
184# endif
185}
186
187
188/**
189 * Fallback function.
190 */
191static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalFallback(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra)
192{
193 RT_NOREF(pData);
194 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
195 uint32_t uMode;
196 if ( pGip
197 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
198 && ( (uMode = pGip->u32Mode) == SUPGIPMODE_INVARIANT_TSC
199 || uMode == SUPGIPMODE_SYNC_TSC
200 || uMode == SUPGIPMODE_ASYNC_TSC)
201# ifdef IN_RING3
202 && ( (pGip->fGetGipCpu & APPLICABLE_GET_CPU_FLAGS) != 0
203 || ( pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
204 && uMode != SUPGIPMODE_ASYNC_TSC))
205# endif
206 )
207 return rtTimeNanoTSInternalRediscover(pData, pExtra);
208# ifndef IN_RC
209 if (pExtra)
210 pExtra->uTSCValue = ASMReadTSC();
211 return RTTimeSystemNanoTS();
212# else
213 RTAssertReleasePanic();
214 return 0;
215# endif
216}
217
218
219/**
220 * Called the first time somebody asks for the time or when the GIP
221 * is mapped/unmapped.
222 */
223static DECLCALLBACK(uint64_t) rtTimeNanoTSInternalRediscover(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra)
224{
225 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
226# ifdef IN_RC
227 uint32_t iWorker;
228# else
229 PFNTIMENANOTSINTERNAL pfnWorker;
230# endif
231 uint32_t uMode;
232 if ( pGip
233 && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
234 && ( (uMode = pGip->u32Mode) == SUPGIPMODE_INVARIANT_TSC
235 || uMode == SUPGIPMODE_SYNC_TSC
236 || uMode == SUPGIPMODE_ASYNC_TSC))
237 {
238# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
239 if (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2)
240 {
241# ifdef IN_RC
242 iWorker = uMode == SUPGIPMODE_ASYNC_TSC
243 ? RTTIMENANO_WORKER_LFENCE_ASYNC
244 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
245 ? RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA
246 : RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA;
247# elif defined(IN_RING0)
248 pfnWorker = uMode == SUPGIPMODE_ASYNC_TSC
249 ? RTTimeNanoTSLFenceAsync
250 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
251 ? RTTimeNanoTSLFenceSyncInvarNoDelta
252 : RTTimeNanoTSLFenceSyncInvarWithDelta;
253# else
254 if (uMode == SUPGIPMODE_ASYNC_TSC)
255 {
256 if ( pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS)
257 pfnWorker = RTTimeNanoTSLFenceAsyncUseIdtrLim;
258 else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
259 pfnWorker = RTTimeNanoTSLFenceAsyncUseRdtscp;
260 else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL)
261 pfnWorker = RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl;
262 else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B)
263 pfnWorker = RTTimeNanoTSLFenceAsyncUseApicIdExt0B;
264 else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E)
265 pfnWorker = RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E;
266 else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID)
267 pfnWorker = RTTimeNanoTSLFenceAsyncUseApicId;
268 else
269 pfnWorker = rtTimeNanoTSInternalFallback;
270 }
271 else
272 {
273 if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
274 pfnWorker = RTTimeNanoTSLFenceSyncInvarNoDelta;
275 else if (pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS)
276 pfnWorker = RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim;
277 else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
278 pfnWorker = RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp;
279 else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B)
280 pfnWorker = RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B;
281 else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E)
282 pfnWorker = RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E;
283 else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID)
284 pfnWorker = RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId;
285 else
286 pfnWorker = rtTimeNanoTSInternalFallback;
287 }
288# endif
289 }
290 else
291 {
292# ifdef IN_RC
293 iWorker = uMode == SUPGIPMODE_ASYNC_TSC
294 ? RTTIMENANO_WORKER_LEGACY_ASYNC
295 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
296 ? RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_NO_DELTA : RTTIMENANO_WORKER_LEGACY_SYNC_INVAR_WITH_DELTA;
297# elif defined(IN_RING0)
298 pfnWorker = uMode == SUPGIPMODE_ASYNC_TSC
299 ? RTTimeNanoTSLegacyAsync
300 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
301 ? RTTimeNanoTSLegacySyncInvarNoDelta
302 : RTTimeNanoTSLegacySyncInvarWithDelta;
303# else
304 if (uMode == SUPGIPMODE_ASYNC_TSC)
305 pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
306 ? RTTimeNanoTSLegacyAsyncUseRdtscp
307 : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
308 ? RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl
309 : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
310 ? RTTimeNanoTSLegacyAsyncUseIdtrLim
311 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B
312 ? RTTimeNanoTSLegacyAsyncUseApicIdExt0B
313 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E
314 ? RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E
315 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
316 ? RTTimeNanoTSLegacyAsyncUseApicId
317 : rtTimeNanoTSInternalFallback;
318 else
319 pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
320 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
321 ? RTTimeNanoTSLegacySyncInvarNoDelta
322 : RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp
323 : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
324 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO
325 ? RTTimeNanoTSLegacySyncInvarNoDelta
326 : RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim
327 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B
328 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
329 ? RTTimeNanoTSLegacySyncInvarNoDelta
330 : RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B
331 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E
332 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
333 ? RTTimeNanoTSLegacySyncInvarNoDelta
334 : RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E
335 : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
336 ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
337 ? RTTimeNanoTSLegacySyncInvarNoDelta
338 : RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId
339 : rtTimeNanoTSInternalFallback;
340# endif
341 }
342# else /* !AMD64 && !X86 */
343# ifdef IN_RC
344# error "port me"
345 iWorker = uMode == SUPGIPMODE_ASYNC_TSC
346 ? RTTIMENANO_WORKER_LFENCE_ASYNC
347 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
348 ? RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_NO_DELTA
349 : RTTIMENANO_WORKER_LFENCE_SYNC_INVAR_WITH_DELTA;
350# elif defined(IN_RING0)
351 pfnWorker = uMode == SUPGIPMODE_ASYNC_TSC
352 ? RTTimeNanoTSAsync
353 : pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
354 ? RTTimeNanoTSSyncInvarNoDelta
355 : RTTimeNanoTSSyncInvarWithDelta;
356# else
357 if (uMode == SUPGIPMODE_ASYNC_TSC)
358 {
359 if (pGip->fGetGipCpu & SUPGIPGETCPU_TPIDRRO_EL0)
360 pfnWorker = RTTimeNanoTSAsyncUseTpIdRRo;
361 else
362 pfnWorker = rtTimeNanoTSInternalFallback;
363 }
364 else
365 {
366 if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
367 pfnWorker = RTTimeNanoTSSyncInvarNoDelta;
368 else if (pGip->fGetGipCpu & SUPGIPGETCPU_TPIDRRO_EL0)
369 pfnWorker = RTTimeNanoTSSyncInvarWithDeltaUseTpIdRRo;
370 else
371 pfnWorker = rtTimeNanoTSInternalFallback;
372 }
373# endif
374
375# endif /* !AMD64 && !X86 */
376 }
377 else
378# ifdef IN_RC
379 iWorker = RTTIMENANO_WORKER_FALLBACK;
380# else
381 pfnWorker = rtTimeNanoTSInternalFallback;
382# endif
383
384# ifdef IN_RC
385 ASMAtomicWriteU32((uint32_t volatile *)&g_iWorker, iWorker);
386 return g_apfnWorkers[iWorker](pData, pExtra);
387# else
388 ASMAtomicWritePtr((void * volatile *)&g_pfnWorker, (void *)(uintptr_t)pfnWorker);
389 return pfnWorker(pData, pExtra);
390# endif
391}
392
393
394# if defined(IN_RING3) || defined(IN_RING0)
395RTDECL(const char *) RTTimeNanoTSWorkerName(void)
396{
397 static const struct { PFNTIMENANOTSINTERNAL pfnWorker; const char *pszName; } s_aWorkersAndNames[] =
398 {
399# define ENTRY(a_fn) { a_fn, #a_fn }
400# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
401 ENTRY(RTTimeNanoTSLegacySyncInvarNoDelta),
402 ENTRY(RTTimeNanoTSLFenceSyncInvarNoDelta),
403# ifdef IN_RING3
404 ENTRY(RTTimeNanoTSLegacyAsyncUseApicId),
405 ENTRY(RTTimeNanoTSLegacyAsyncUseApicIdExt0B),
406 ENTRY(RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E),
407 ENTRY(RTTimeNanoTSLegacyAsyncUseRdtscp),
408 ENTRY(RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl),
409 ENTRY(RTTimeNanoTSLegacyAsyncUseIdtrLim),
410 ENTRY(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId),
411 ENTRY(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B),
412 ENTRY(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E),
413 ENTRY(RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp),
414 ENTRY(RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim),
415 ENTRY(RTTimeNanoTSLFenceAsyncUseApicId),
416 ENTRY(RTTimeNanoTSLFenceAsyncUseApicIdExt0B),
417 ENTRY(RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E),
418 ENTRY(RTTimeNanoTSLFenceAsyncUseRdtscp),
419 ENTRY(RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl),
420 ENTRY(RTTimeNanoTSLFenceAsyncUseIdtrLim),
421 ENTRY(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId),
422 ENTRY(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B),
423 ENTRY(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E),
424 ENTRY(RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp),
425 ENTRY(RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim),
426# else
427 ENTRY(RTTimeNanoTSLegacyAsync),
428 ENTRY(RTTimeNanoTSLegacySyncInvarWithDelta),
429 ENTRY(RTTimeNanoTSLFenceAsync),
430 ENTRY(RTTimeNanoTSLFenceSyncInvarWithDelta),
431# endif
432# else /* !AMD64 && !X86 */
433 ENTRY(RTTimeNanoTSSyncInvarNoDelta),
434# ifdef IN_RING3
435# ifdef RT_ARCH_ARM64
436 ENTRY(RTTimeNanoTSSyncInvarWithDeltaUseTpIdRRo),
437 ENTRY(RTTimeNanoTSAsyncUseTpIdRRo),
438# endif
439# else
440 ENTRY(RTTimeNanoTSAsync),
441 ENTRY(RTTimeNanoTSSyncInvarWithDelta),
442# endif
443# endif /* !AMD64 && !X86 */
444 ENTRY(rtTimeNanoTSInternalFallback),
445# undef ENTRY
446 };
447 PFNTIMENANOTSINTERNAL pfnWorker = g_pfnWorker;
448 if (pfnWorker == rtTimeNanoTSInternalRediscover)
449 {
450 RTTimeNanoTS();
451 pfnWorker = g_pfnWorker;
452 }
453
454 for (unsigned i = 0; i < RT_ELEMENTS(s_aWorkersAndNames); i++)
455 if (s_aWorkersAndNames[i].pfnWorker == pfnWorker)
456 return s_aWorkersAndNames[i].pszName;
457 AssertFailed();
458 return NULL;
459}
460# endif /* IN_RING3 || IN_RING0 */
461
462#endif /* !IN_GUEST && !RT_NO_GIP */
463
464
465/**
466 * Internal worker for getting the current nanosecond timestamp.
467 */
468DECLINLINE(uint64_t) rtTimeNanoTSInternal(void)
469{
470#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
471# ifdef IN_RC
472 return g_apfnWorkers[g_iWorker](&g_TimeNanoTSData, NULL /*pExtra*/);
473# else
474 return g_pfnWorker(&g_TimeNanoTSData, NULL /*pExtra*/);
475# endif
476#else
477 return RTTimeSystemNanoTS();
478#endif
479}
480
481
482/**
483 * Gets the current nanosecond timestamp.
484 *
485 * @returns nanosecond timestamp.
486 */
487RTDECL(uint64_t) RTTimeNanoTS(void)
488{
489 return rtTimeNanoTSInternal();
490}
491RT_EXPORT_SYMBOL(RTTimeNanoTS);
492
493
494/**
495 * Gets the current millisecond timestamp.
496 *
497 * @returns millisecond timestamp.
498 */
499RTDECL(uint64_t) RTTimeMilliTS(void)
500{
501 return rtTimeNanoTSInternal() / 1000000;
502}
503RT_EXPORT_SYMBOL(RTTimeMilliTS);
504
505
506#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
507/**
508 * Debugging the time api.
509 *
510 * @returns the number of 1ns steps which has been applied by RTTimeNanoTS().
511 */
512RTDECL(uint32_t) RTTimeDbgSteps(void)
513{
514 return g_TimeNanoTSData.c1nsSteps;
515}
516RT_EXPORT_SYMBOL(RTTimeDbgSteps);
517
518
519/**
520 * Debugging the time api.
521 *
522 * @returns the number of times the TSC interval expired RTTimeNanoTS().
523 */
524RTDECL(uint32_t) RTTimeDbgExpired(void)
525{
526 return g_TimeNanoTSData.cExpired;
527}
528RT_EXPORT_SYMBOL(RTTimeDbgExpired);
529
530
531/**
532 * Debugging the time api.
533 *
534 * @returns the number of bad previous values encountered by RTTimeNanoTS().
535 */
536RTDECL(uint32_t) RTTimeDbgBad(void)
537{
538 return g_TimeNanoTSData.cBadPrev;
539}
540RT_EXPORT_SYMBOL(RTTimeDbgBad);
541
542
543/**
544 * Debugging the time api.
545 *
546 * @returns the number of update races in RTTimeNanoTS().
547 */
548RTDECL(uint32_t) RTTimeDbgRaces(void)
549{
550 return g_TimeNanoTSData.cUpdateRaces;
551}
552RT_EXPORT_SYMBOL(RTTimeDbgRaces);
553#endif /* !IN_GUEST && !RT_NO_GIP */
554
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette