VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/time/timesupA.mac@ 53442

最後變更 在這個檔案從53442是 53430,由 vboxsync 提交於 10 年 前

VMM/TM: First step in introducing the invariant TM mode.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 21.0 KB
 
1; $Id: timesupA.mac 53430 2014-12-03 13:18:41Z vboxsync $
2;; @file
3; IPRT - Time using SUPLib, the Assembly Code Template.
4;
5
6;
7; Copyright (C) 2006-2014 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.alldomusa.eu.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; The contents of this file may alternatively be used under the terms
18; of the Common Development and Distribution License Version 1.0
19; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20; VirtualBox OSE distribution, in which case the provisions of the
21; CDDL are applicable instead of those of the GPL.
22;
23; You may elect to license modified versions of this file under the
24; terms and conditions of either the GPL or the CDDL or both.
25;
26
27%ifdef RT_ARCH_X86
28;;
29; The x86 assembly implementation of the assembly routines.
30;
31; @returns Nanosecond timestamp.
32; @param pData Pointer to the nanosecond timestamp data.
33;
34BEGINPROC rtTimeNanoTSInternalAsm
35 ;
36 ; Variable definitions.
37 ;
38%define pData [ebp + 08h]
39%define u64RetNanoTS_Hi [ebp - 04h]
40%define u64RetNanoTS [ebp - 08h]
41%define u32UpdateIntervalNS [ebp - 0ch]
42%define u32UpdateIntervalTSC [ebp - 10h]
43%define u64TSC_Hi [ebp - 14h]
44%define u64TSC [ebp - 18h]
45%define u64CurNanoTS_Hi [ebp - 1ch]
46%define u64CurNanoTS [ebp - 20h]
47%define u64PrevNanoTS_Hi [ebp - 24h]
48%define u64PrevNanoTS [ebp - 28h]
49%define u32TransactionId [ebp - 2ch]
50%define u32ApicIdPlus [ebp - 30h]
51%define TmpVar [ebp - 34h]
52%define SavedEBX [ebp - 38h]
53%define SavedEDI [ebp - 3ch]
54%define SavedESI [ebp - 40h]
55
56 ;
57 ; Prolog.
58 ;
59 push ebp
60 mov ebp, esp
61 sub esp, 40h
62 mov SavedEBX, ebx
63 mov SavedEDI, edi
64 mov SavedESI, esi
65
66
67 ;;
68 ;; Read the GIP data and the previous value.
69 ;;
70.ReadGip:
71
72
73 ;
74 ; Load pGip and calc pGipCPU, setting u32ApicIdPlus if necessary.
75 ;
76%ifdef IMPORTED_SUPLIB
77 %ifdef IN_RING0
78 mov esi, IMP(g_SUPGlobalInfoPage)
79 %else
80 mov esi, IMP(g_pSUPGlobalInfoPage)
81 mov esi, [esi]
82 %endif
83%else
84 mov esi, [NAME(g_pSUPGlobalInfoPage)]
85%endif
86 or esi, esi
87 jz .Rediscover
88 cmp dword [esi + SUPGLOBALINFOPAGE.u32Magic], SUPGLOBALINFOPAGE_MAGIC
89 jne .Rediscover
90%ifdef ASYNC_GIP
91 ; u8ApicId = ASMGetApicId();
92 mov eax, 1
93 cpuid ; expensive
94 %ifdef NEED_TRANSACTION_ID
95 mov u32ApicIdPlus, ebx
96 %endif
97 ; pGipCpu = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]];
98 shr ebx, 24
99 movzx ebx, word [esi + ebx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId]
100 mov eax, SUPGIPCPU_size
101 mul ebx
102 lea edi, [esi + eax + SUPGLOBALINFOPAGE.aCPUs] ; edi == &pGip->aCPU[u8ApicId];
103%else
104 lea edi, [esi + SUPGLOBALINFOPAGE.aCPUs] ; edi == &pGip->aCPU[0];
105%endif
106
107%ifdef NEED_TRANSACTION_ID
108 ;
109 ; Serialized loading of u32TransactionId.
110 ;
111 mov ebx, [edi + SUPGIPCPU.u32TransactionId]
112 mov u32TransactionId, ebx
113 %ifdef USE_LFENCE
114 lfence
115 %else
116 lock xor dword TmpVar, 0
117 %endif
118%endif
119
120 ;
121 ; Load the data and TSC.
122 ;
123 mov eax, [esi + SUPGLOBALINFOPAGE.u32UpdateIntervalNS]
124 mov u32UpdateIntervalNS, eax ; esi is now free
125 mov edx, [edi + SUPGIPCPU.u32UpdateIntervalTSC]
126 mov u32UpdateIntervalTSC, edx
127 rdtsc
128 SupTscDeltaApply edi ; Apply inter-cpu TSC-delta to have the normalized TSC value in edx:eax
129 mov ecx, [edi + SUPGIPCPU.u64NanoTS]
130 mov u64CurNanoTS, ecx
131 mov esi, [edi + SUPGIPCPU.u64NanoTS + 4]
132 mov u64CurNanoTS_Hi, esi
133 mov ebx, [edi + SUPGIPCPU.u64TSC]
134 mov u64TSC, ebx
135 mov ecx, [edi + SUPGIPCPU.u64TSC + 4]
136 mov u64TSC_Hi, ecx
137
138 ; u64PrevNanoTS = ASMAtomicReadU64(pu64Prev);
139 ; This serializes load/save. And with the dependency on the
140 ; RDTSC result, we try to make sure it has completed as well.
141 mov esi, pData
142 mov esi, [esi + RTTIMENANOTSDATA.pu64Prev]
143 mov ebx, eax
144 mov ecx, edx
145 lock cmpxchg8b [esi]
146 mov u64PrevNanoTS, eax
147 mov u64PrevNanoTS_Hi, edx
148
149%undef SAVED_u64RetNanoTS
150%ifdef NEED_TRANSACTION_ID
151 ;
152 ; Check that the GIP and CPU didn't change.
153 ; We've already serialized all the loads and stores at this point.
154 ;
155 %ifdef ASYNC_GIP
156 mov u64RetNanoTS, ebx
157 mov u64RetNanoTS_Hi, ecx
158 %define SAVED_u64RetNanoTS
159 mov eax, 1
160 cpuid
161 cmp u32ApicIdPlus, ebx
162 jne .ReadGip
163 %endif
164 mov esi, [edi + SUPGIPCPU.u32TransactionId]
165 cmp esi, u32TransactionId
166 jne .ReadGip
167 test esi, 1
168 jnz .ReadGip
169%endif ; NEED_TRANSACTION_ID
170%ifdef SAVED_u64RetNanoTS
171 mov ebx, u64RetNanoTS
172 mov ecx, u64RetNanoTS_Hi
173%endif
174
175 ;;
176 ;; Calc the timestamp.
177 ;;
178 ; u64RetNanoTS -= u64TSC;
179 sub ebx, u64TSC
180 sbb ecx, u64TSC_Hi
181
182 ; if (u64RetNanoTS > u32UpdateIntervalTSC) -> jump
183 or ecx, ecx
184 jnz .OverFlow
185 cmp ebx, u32UpdateIntervalTSC
186 ja .OverFlow
187 mov eax, ebx
188.ContinueCalcs: ; eax <= u32UpdateIntervalTSC
189 mul dword u32UpdateIntervalNS
190 div dword u32UpdateIntervalTSC
191 xor edx, edx
192
193 ; u64RetNanoTS += u64CurNanoTS;
194 add eax, u64CurNanoTS
195 adc edx, u64CurNanoTS_Hi
196
197 ;;
198 ;; Compare it with the previous one.
199 ;;
200 ; if (RT_LIKELY( u64RetNanoTS > u64PrevNanoTS
201 ; && u64RetNanoTS < u64PrevNanoTS + UINT64_C(86000000000000) /* 24h */))
202 ;; @todo optimize this compare (/me too tired).
203 mov ecx, u64PrevNanoTS_Hi
204 mov ebx, u64PrevNanoTS
205 cmp edx, ecx
206 ja .Compare2
207 jb .DeltaPrevTooBig
208 cmp eax, ebx
209 jbe .DeltaPrevTooBig
210
211.Compare2:
212 add ebx, 0x6F736000
213 adc ecx, 0x00004E37
214 cmp edx, ecx
215 jb .CompareDone
216 ja .DeltaPrevTooBig
217 cmp eax, ebx
218 jae .DeltaPrevTooBig
219.CompareDone:
220
221
222 ;;
223 ;; Update the previous value with the u64RetNanoTS value.
224 ;;
225.Update:
226 ; if (RT_LIKELY(ASMAtomicCmpXchgU64(&pData->u64Prev, u64RetNanoTS, u64PrevNanoTS)))
227 mov ebx, eax
228 mov ecx, edx
229 mov esi, pData
230 mov esi, [esi + RTTIMENANOTSDATA.pu64Prev]
231 mov eax, u64PrevNanoTS
232 mov edx, u64PrevNanoTS_Hi
233 lock cmpxchg8b [esi]
234 jnz .UpdateFailed
235
236.Updated:
237 mov eax, ebx
238 mov edx, ecx
239
240.Done:
241 mov esi, SavedESI
242 mov edi, SavedEDI
243 mov ebx, SavedEBX
244 leave
245 ret
246
247
248 ;;
249 ;; We've expired the interval, cap it. If we're here for the 2nd
250 ;; time without any GIP update in-between, the checks against
251 ;; pData->u64Prev below will force 1ns stepping.
252 ;;
253.OverFlow:
254 ; u64Delta = u32UpdateIntervalTSC;
255 mov esi, pData
256 inc dword [esi + RTTIMENANOTSDATA.cExpired]
257 mov eax, u32UpdateIntervalTSC
258 jmp .ContinueCalcs
259
260
261 ;;
262 ;; u64DeltaPrev >= 24h
263 ;;
264 ;; eax:edx = u64RetNanoTS (to be adjusted)
265 ;;
266.DeltaPrevTooBig:
267 ; uint64_t u64DeltaPrev = u64RetNanoTS - u64PrevNanoTS;
268 mov ebx, eax
269 sub ebx, u64PrevNanoTS
270 mov ecx, edx
271 sbb ecx, u64PrevNanoTS_Hi ; ebx:ecx = u64DeltaPrev
272
273 ; else if ( (int64_t)u64DeltaPrev <= 0
274 ; && (int64_t)u64DeltaPrev + u32UpdateIntervalNS * 2 >= 0)
275 ; {
276 ; /* Occasional - u64RetNanoTS is in the recent 'past' relative the previous call. */
277 ; pData->c1nsSteps++;
278 ; u64RetNanoTS = u64PrevNanoTS + 1;
279 ; }
280 mov esi, u32UpdateIntervalNS
281 cmp ecx, 0
282 jl .PrevNotZero2ndTest
283 jg .DeltaPrevNotInRecentPast
284 cmp ebx, 0
285 ja .DeltaPrevNotInRecentPast
286
287.PrevNotZero2ndTest:
288 add esi, esi ; ASSUMES: u32UpdateIntervalNS * 2 <= 32-bit.
289 xor edi, edi
290 add esi, ebx
291 adc edi, ecx
292 test edi, edi
293 js .DeltaPrevNotInRecentPast
294
295.DeltaPrevInRecentPast:
296 mov esi, pData
297 inc dword [esi + RTTIMENANOTSDATA.c1nsSteps]
298 mov eax, u64PrevNanoTS
299 mov edx, u64PrevNanoTS_Hi
300 add eax, 1
301 adc edx, 0
302 jmp .Update
303
304.DeltaPrevNotInRecentPast:
305 ; else if (!u64PrevNanoTS) /* We're resuming (see TMVirtualResume). */
306 ; /* do nothing */;
307 cmp dword u64PrevNanoTS, 0
308 jne .DeltaPrevNotZero
309 cmp dword u64PrevNanoTS_Hi, 0
310 jne .DeltaPrevNotZero
311 jmp .Update
312
313.DeltaPrevNotZero:
314 ; else
315 ; {
316 ; /* Something has gone bust, if negative offset it's real bad. */
317 ; rtTimeNanoTSInternalBitch(pVM,
318 ; }
319
320 ; call C function that does the bitching.
321 mov u64RetNanoTS, eax
322 mov u64RetNanoTS_Hi, edx
323
324 mov edi, u64PrevNanoTS_Hi
325 mov esi, u64PrevNanoTS
326 push edi
327 push esi ; 4 - u64PrevNanoTS
328 push ecx
329 push ebx ; 3 - u64DeltaPrev
330 push edx
331 push eax ; 2 - u64RetNanoTS
332 mov eax, pData
333 push eax ; 1 - pData
334 call dword [eax + RTTIMENANOTSDATA.pfnBad]
335 add esp, 4*7
336
337 mov eax, u64RetNanoTS
338 mov edx, u64RetNanoTS_Hi
339 jmp .Update
340
341
342 ;;
343 ;; Attempt updating the previous value, provided we're still ahead of it.
344 ;;
345 ;; There is no point in recalculating u64NanoTS because we got preempted or if
346 ;; we raced somebody while the GIP was updated, since these are events
347 ;; that might occur at any point in the return path as well.
348 ;;
349 ;; eax:edx = *pData->u64Prev
350 ;; ebx:ecx = u64RetNanoTS
351 ;;
352 ALIGNCODE(16)
353.UpdateFailed:
354 mov edi, pData
355 lock inc dword [edi + RTTIMENANOTSDATA.cUpdateRaces]
356 ; for (i = 0; i < 10; i++)
357 mov edi, 10
358.UpdateLoop:
359 ; if (u64PrevNanoTS >= u64NanoTS)
360 ; break;
361 cmp edx, ecx
362 jg .Updated
363 jne .UpdateLoopLess
364 cmp eax, ebx
365 jae .Updated
366.UpdateLoopLess:
367 ; retry
368 lock cmpxchg8b [esi]
369 jz .Updated
370 dec edi
371 jnz .UpdateLoop
372 jmp .Updated
373
374
375 ;;
376 ;; The GIP is seemingly invalid, redo the discovery.
377 ;;
378.Rediscover:
379 mov eax, pData
380 push eax
381 call [eax + RTTIMENANOTSDATA.pfnRediscover]
382 add esp, 4h
383 jmp .Done
384
385 ;
386 ; Cleanup variables
387 ;
388%undef pData
389%undef u64Delta_Hi
390%undef u64Delta
391%undef u32UpdateIntervalNS
392%undef u32UpdateIntervalTSC
393%undef u64TSC_Hi
394%undef u64TSC
395%undef u64NanoTS_Hi
396%undef u64NanoTS
397%undef u64PrevNanoTS_Hi
398%undef u64PrevNanoTS
399%undef u32TransactionId
400%undef u8ApicId
401
402%else ; AMD64
403
404;;
405; The AMD64 assembly implementation of the assembly routines.
406;
407; @returns Nanosecond timestamp.
408; @param pData gcc:rdi msc:rcx Pointer to the nanosecond timestamp data.
409;
410BEGINPROC rtTimeNanoTSInternalAsm
411 ;
412 ; Define variables and stack frame.
413 ;
414%define SavedRBX [rbp - 08h]
415%define SavedR12 [rbp - 10h]
416%define SavedR13 [rbp - 18h]
417%define SavedRDI [rbp - 20h]
418%define SavedRSI [rbp - 28h]
419%define TmpVar [rbp - 30h]
420%define TmpVar2 [rbp - 38h]
421%ifdef NEED_TRANSACTION_ID
422 %ifdef ASYNC_GIP
423 %define SavedR14 [rbp - 40h]
424 %define SavedR15 [rbp - 48h]
425 %endif
426%endif
427
428%define pData rdi
429
430%define u64TSC rsi
431%define pGip rsi
432%define pGipCPU r8
433%define u32TransactionId r9d
434%define u64CurNanoTS r10
435%define u64PrevNanoTS r11 ; not parameter register
436%define u32UpdateIntervalTSC r12d
437%define u32UpdateIntervalTSC_64 r12
438%define u32UpdateIntervalNS r13d
439%define u32UpdateIntervalNS_64 r13
440%undef u64SavedRetNanoTS
441%undef u32ApicIdPlus
442%ifdef NEED_TRANSACTION_ID
443 %ifdef ASYNC_GIP
444 %define u64SavedRetNanoTS r14
445 %define u32ApicIdPlus r15d
446 %endif
447%endif
448
449 ;
450 ; The prolog.
451 ;
452 push rbp
453 mov rbp, rsp
454%ifdef ASM_CALL64_MSC
455 sub rsp, 50h+20h
456%else
457 sub rsp, 50h
458%endif
459 mov SavedRBX, rbx
460 mov SavedR12, r12
461 mov SavedR13, r13
462%ifdef ASM_CALL64_MSC
463 mov SavedRDI, rdi
464 mov SavedRSI, rsi
465 mov pData, rcx
466%else
467 ;mov pData, rdi - already in rdi.
468%endif
469%ifdef SavedR14
470 mov SavedR14, r14
471%endif
472%ifdef SavedR15
473 mov SavedR15, r15
474%endif
475
476
477 ;;
478 ;; Data fetch loop.
479 ;; We take great pain ensuring that data consistency here.
480 ;;
481.ReadGip:
482
483 ;
484 ; Load pGip and calc pGipCPU, setting u32ApicIdPlus if necessary.
485 ; Finding the GIP is fun...
486 ;
487%ifdef RT_OS_WINDOWS
488 %ifdef IMPORTED_SUPLIB
489 %ifdef IN_RING0
490 mov rax, qword IMP(g_SUPGlobalInfoPage)
491 mov pGip, rax
492 %else
493 mov pGip, [IMP(g_pSUPGlobalInfoPage) wrt rip]
494 mov pGip, [pGip]
495 %endif
496 %else
497 mov pGip, [NAME(g_pSUPGlobalInfoPage) wrt rip]
498 %endif
499%else
500 %ifdef IN_RING0
501 mov rax, qword NAME(g_SUPGlobalInfoPage)
502 mov pGip, rax
503 %else
504 mov pGip, [rel NAME(g_pSUPGlobalInfoPage) wrt ..gotpcrel]
505 mov pGip, [pGip]
506 %endif
507%endif
508 or pGip, pGip
509 jz .Rediscover
510 cmp dword [pGip + SUPGLOBALINFOPAGE.u32Magic], SUPGLOBALINFOPAGE_MAGIC
511 jne .Rediscover
512
513%ifdef ASYNC_GIP
514 ; u8ApicId = ASMGetApicId();
515 mov eax, 1
516 cpuid ; expensive
517 %ifdef NEED_TRANSACTION_ID
518 mov u32ApicIdPlus, ebx
519 %endif
520 ; pGipCpu = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]];
521 shr ebx, 24
522 movzx eax, word [pGip + rbx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId]
523 imul eax, SUPGIPCPU_size
524 lea pGipCPU, [pGip + rax + SUPGLOBALINFOPAGE.aCPUs]
525%else
526 lea pGipCPU, [pGip + SUPGLOBALINFOPAGE.aCPUs]
527%endif
528
529%ifdef NEED_TRANSACTION_ID
530 ;
531 ; Serialized loading of u32TransactionId.
532 ;
533 mov u32TransactionId, [pGipCPU + SUPGIPCPU.u32TransactionId]
534 %ifdef USE_LFENCE
535 lfence
536 %else
537 lock xor dword TmpVar, 0
538 %endif
539%endif
540
541 ;
542 ; Load the data and TSC.
543 ;
544 mov u32UpdateIntervalNS, [pGip + SUPGLOBALINFOPAGE.u32UpdateIntervalNS] ; before u64TSC
545 mov u32UpdateIntervalTSC, [pGipCPU + SUPGIPCPU.u32UpdateIntervalTSC]
546 rdtsc
547 SUPTscDeltaApply pGipCPU
548 mov u64PrevNanoTS, [pData + RTTIMENANOTSDATA.pu64Prev]
549 mov u64PrevNanoTS, [u64PrevNanoTS]
550 shl rdx, 32
551 %ifdef u64SavedRetNanoTS ; doing this here saves a tick or so.
552 mov u64SavedRetNanoTS, rax
553 or u64SavedRetNanoTS, rdx
554 %else
555 or rax, rdx ; rax is u64RetNanoTS.
556 %endif
557 mov u64CurNanoTS, [pGipCPU + SUPGIPCPU.u64NanoTS]
558 mov u64TSC, [pGipCPU + SUPGIPCPU.u64TSC]
559
560%ifdef NEED_TRANSACTION_ID
561 ;
562 ; Check that the GIP and CPU didn't change.
563 ;
564 ; It is crucial that the rdtsc instruction has completed before
565 ; we check the transaction id. The LOCK prefixed instruction with
566 ; dependency on the RDTSC result should do the trick, I think.
567 ; CPUID is serializing, so the async path is safe by default.
568 ;
569 %ifdef ASYNC_GIP
570 mov eax, 1
571 cpuid
572 cmp u32ApicIdPlus, ebx
573 jne .ReadGip
574 %else
575 lock xor qword TmpVar, rax
576 %endif
577 cmp u32TransactionId, [pGipCPU + SUPGIPCPU.u32TransactionId]
578 jne .ReadGip
579 test u32TransactionId, 1
580 jnz .ReadGip
581 %ifdef u64SavedRetNanoTS
582 mov rax, u64SavedRetNanoTS ; rax is u64RetNanoTS.
583 %endif
584%endif ; NEED_TRANSACTION_ID
585
586
587 ;;
588 ;; Calc the timestamp.
589 ;;
590 ; u64RetNanoTS -= u64TSC;
591 sub rax, u64TSC
592 xor edx, edx
593
594 ; if (u64RetNanoTS > u32UpdateIntervalTSC) -> jump
595 cmp rax, u32UpdateIntervalTSC_64
596 ja .OverFlow
597.ContinueCalcs: ; edx = 0; eax <= u32UpdateIntervalTSC
598 mul u32UpdateIntervalNS
599 div u32UpdateIntervalTSC
600
601 ; u64RetNanoTS += u64CurNanoTS;
602 add rax, u64CurNanoTS
603
604
605 ;;
606 ;; Compare it with the previous one.
607 ;;
608 ; if (RT_LIKELY( u64RetNanoTS > u64PrevNanoTS
609 ; && u64RetNanoTS < u64PrevNanoTS + UINT64_C(86000000000000) /* 24h */))
610 ; /* Frequent - less than 24h since last call. */;
611 cmp rax, u64PrevNanoTS
612 jbe .DeltaPrevTooBig
613 mov ecx, 5
614 shl rcx, 44 ; close enough
615 add rcx, u64PrevNanoTS
616 cmp rax, rcx
617 jae .DeltaPrevTooBig
618
619
620 ;;
621 ;; Update the previous value.
622 ;;
623.Update:
624 ; if (RT_LIKELY(ASMAtomicCmpXchgU64(&pData->u64Prev, u64RetNanoTS, u64PrevNanoTS)))
625 mov rbx, [pData + RTTIMENANOTSDATA.pu64Prev]
626 mov rcx, rax
627 mov rax, u64PrevNanoTS
628 lock cmpxchg [rbx], rcx
629 jnz .UpdateFailed
630
631.Updated:
632 mov rax, rcx
633
634.Done:
635 mov rbx, SavedRBX
636 mov r12, SavedR12
637 mov r13, SavedR13
638%ifdef SavedR14
639 mov r14, SavedR14
640%endif
641%ifdef SavedR15
642 mov r15, SavedR15
643%endif
644%ifdef ASM_CALL64_MSC
645 mov rdi, SavedRDI
646 mov rsi, SavedRSI
647%endif
648 leave
649 ret
650
651
652 ;;
653 ;; We've expired the interval, cap it. If we're here for the 2nd
654 ;; time without any GIP update in-between, the checks against
655 ;; pData->u64Prev below will force 1ns stepping.
656 ;;
657ALIGNCODE(16)
658.OverFlow:
659 ; u64RetNanoTS = u32UpdateIntervalTSC;
660 inc dword [pData + RTTIMENANOTSDATA.cExpired]
661 mov eax, u32UpdateIntervalTSC
662 jmp .ContinueCalcs
663
664
665 ;;
666 ;; u64DeltaPrev >= 24h
667 ;;
668 ;; rax = u64RetNanoTS (to be adjusted)
669 ;;
670ALIGNCODE(16)
671.DeltaPrevTooBig:
672 ; uint64_t u64DeltaPrev = u64RetNanoTS - u64PrevNanoTS;
673 mov rbx, rax
674 sub rbx, u64PrevNanoTS
675
676 ; else if ( (int64_t)u64DeltaPrev <= 0
677 ; && (int64_t)u64DeltaPrev + u32UpdateIntervalNS * 2 >= 0)
678 ; {
679 ; /* Occasional - u64NanoTS is in the recent 'past' relative the previous call. */
680 ; pData->c1nsSteps++;
681 ; u64RetNanoTS = u64PrevNanoTS + 1;
682 ; }
683 test rbx, rbx
684 jg .DeltaPrevNotInRecentPast
685
686 lea rdx, [u32UpdateIntervalNS_64 + u32UpdateIntervalNS_64]
687 add rdx, rbx
688 js .DeltaPrevNotInRecentPast
689
690 ; body
691 inc dword [pData + RTTIMENANOTSDATA.c1nsSteps]
692 lea rax, [u64PrevNanoTS + 1]
693 jmp .Update
694
695 ; else if (!u64PrevNanoTS) /* We're resuming (see TMVirtualResume) / first call. */
696 ; /* do nothing */;
697.DeltaPrevNotInRecentPast:
698 or u64PrevNanoTS, u64PrevNanoTS
699 jz .Update
700
701 ; else
702 ; {
703 ; /* Something has gone bust, if negative offset it's real bad. */
704 ; rtTimeNanoTSInternalBitch(pVM,
705 ; }
706
707 ; call C function that does the bitching.
708 mov TmpVar, rax
709 mov TmpVar2, pData
710
711%ifdef ASM_CALL64_MSC
712 mov rcx, pData ; param 1 - pData
713 mov rdx, rax ; param 2 - u64RetNanoTS
714 mov r8, rbx ; param 3 - u64DeltaPrev
715 mov r9, u64PrevNanoTS ; param 4 - u64PrevNanoTS
716%else
717 ;mov rdi, pData - already in rdi; param 1 - pData
718 mov rsi, rax ; param 2 - u64RetNanoTS
719 mov rdx, rbx ; param 3 - u64DeltaPrev
720 mov rcx, u64PrevNanoTS ; param 4 - u64PrevNanoTS
721%endif
722 call qword [pData + RTTIMENANOTSDATA.pfnBad]
723
724 mov rax, TmpVar
725 mov pData, TmpVar2
726 jmp .Update
727
728
729 ;;
730 ;; Attempt updating the previous value, provided we're still ahead of it.
731 ;;
732 ;; There is no point in recalculating u64NanoTS because we got preempted or if
733 ;; we raced somebody while the GIP was updated, since these are events
734 ;; that might occur at any point in the return path as well.
735 ;;
736 ;; rax = *pData->u64Prev;
737 ;; rcx = u64RetNanoTS
738 ;;
739ALIGNCODE(16)
740.UpdateFailed:
741 lock inc dword [pData + RTTIMENANOTSDATA.cUpdateRaces]
742 ; for (i = 0; i < 10; i++)
743 mov edx, 10
744.UpdateLoop:
745 ; if (u64PrevNanoTS >= u64RetNanoTS)
746 ; break;
747 cmp rax, rcx
748 jge .Updated
749.UpdateLoopLess:
750 ; retry
751 lock cmpxchg [rbx], rcx
752 jz .Updated
753 dec edx
754 jnz .UpdateLoop
755 jmp .Updated
756
757
758 ;;
759 ;; The GIP is seemingly invalid, redo the discovery.
760 ;;
761.Rediscover:
762%ifdef ASM_CALL64_MSC
763 mov rcx, pData
764%else
765 ; mov rdi, pData - already in rdi
766%endif
767 call [pData + RTTIMENANOTSDATA.pfnRediscover]
768 jmp .Done
769
770
771 ;
772 ; Cleanup variables
773 ;
774%undef SavedRBX
775%undef SavedR12
776%undef SavedR13
777%undef SavedR14
778%undef SavedR15
779%undef SavedRDI
780%undef SavedRSI
781%undef pData
782%undef TmpVar
783%undef u64TSC
784%undef pGip
785%undef pGipCPU
786%undef u32TransactionId
787%undef u64CurNanoTS
788%undef u64PrevNanoTS
789%undef u32UpdateIntervalTSC
790%undef u32UpdateIntervalTSC_64
791%undef u32UpdateIntervalNS
792%undef u64SavedRetNanoTS
793%undef u32ApicIdPlus
794
795%endif ; AMD64
796ENDPROC rtTimeNanoTSInternalAsm
797
798
799
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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