41c64c31741f70e00de94130927dd5d85ed360a0vboxsync; $Id$
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync;; @file
9ae4ea547111829e80548cfee4c972e62c0da811vboxsync; IPRT - Time using SUPLib, the Assembly Code Template.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync;
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync;
c0e374304cebe77219b2abc0b6796e72e452c4ddvboxsync; Copyright (C) 2006-2014 Oracle Corporation
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync;
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync; available from http://www.virtualbox.org. This file is free software;
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync; you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; terms and conditions of either the GPL or the CDDL or both.
41c64c31741f70e00de94130927dd5d85ed360a0vboxsync;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef RT_ARCH_X86
1e40f57c72c881067b0314f898e1004211bb7650vboxsync;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync; The x86 assembly implementation of the assembly routines.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync; @returns Nanosecond timestamp.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync; @param pData Pointer to the nanosecond timestamp data.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync;
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncBEGINPROC rtTimeNanoTSInternalAsm
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Variable definitions.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define pData [ebp + 08h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64RetNanoTS_Hi [ebp - 04h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64RetNanoTS [ebp - 08h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32UpdateIntervalNS [ebp - 0ch]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32UpdateIntervalTSC [ebp - 10h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64TSC_Hi [ebp - 14h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64TSC [ebp - 18h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64CurNanoTS_Hi [ebp - 1ch]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64CurNanoTS [ebp - 20h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64PrevNanoTS_Hi [ebp - 24h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64PrevNanoTS [ebp - 28h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32TransactionId [ebp - 2ch]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32ApicIdPlus [ebp - 30h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define TmpVar [ebp - 34h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedEBX [ebp - 38h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedEDI [ebp - 3ch]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedESI [ebp - 40h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Prolog.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push ebp
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebp, esp
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub esp, 40h
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedEBX, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedEDI, edi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedESI, esi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Read the GIP data and the previous value.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.ReadGip:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; Load pGip.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
a4a232fa546df3af50f9389873b521028eed4cdevboxsync%ifdef IMPORTED_SUPLIB
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync %ifdef IN_RING0
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync mov esi, IMP(g_SUPGlobalInfoPage)
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync %else
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov esi, IMP(g_pSUPGlobalInfoPage)
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov esi, [esi]
6bc1d32c5bf2ae1e9d714d09a7c116e5b75e1eb5vboxsync %endif
a4a232fa546df3af50f9389873b521028eed4cdevboxsync%else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, [NAME(g_pSUPGlobalInfoPage)]
a4a232fa546df3af50f9389873b521028eed4cdevboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync or esi, esi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jz .Rediscover
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp dword [esi + SUPGLOBALINFOPAGE.u32Magic], SUPGLOBALINFOPAGE_MAGIC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .Rediscover
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; Calc pGipCPU, setting u32ApicIdPlus if necessary.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef NEED_APIC_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u8ApicId = ASMGetApicId();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cpuid ; expensive
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %ifdef NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u32ApicIdPlus, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; pGipCpu/pGipCpuDelta = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]];
1e40f57c72c881067b0314f898e1004211bb7650vboxsync shr ebx, 24
cd7a8c034836a94a0c4f0adf9764f9ed661cdd01vboxsync movzx ebx, word [esi + ebx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, SUPGIPCPU_size
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mul ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lea edi, [esi + eax + SUPGLOBALINFOPAGE.aCPUs] ; edi == &pGip->aCPU[u8ApicId];
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Serialized loading of u32TransactionId.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, [edi + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ebx, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u32TransactionId, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %ifdef USE_LFENCE
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lfence
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lock xor dword TmpVar, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; Load the data and TSC with delta applied.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, [esi + SUPGLOBALINFOPAGE.u32UpdateIntervalNS]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u32UpdateIntervalNS, eax
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP ; esi is now free.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edx, [edi + SUPGIPCPU.u32UpdateIntervalTSC]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov edx, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u32UpdateIntervalTSC]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u32UpdateIntervalTSC, edx
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync rdtsc
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef WITH_TSC_DELTA
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync cmp dword [edi + SUPGIPCPU.i64TSCDelta], 0xffffffff
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync je .TscDeltaPossiblyInvalid
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync.TscDeltaValid:
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync sub eax, dword [edi + SUPGIPCPU.i64TSCDelta]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync sbb edx, dword [edi + SUPGIPCPU.i64TSCDelta + 4]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync.TscDeltaNotValid: ; edi is now free.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, [edi + SUPGIPCPU.u64NanoTS]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, [edi + SUPGIPCPU.u64NanoTS + 4]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ecx, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u64NanoTS]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ebx, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u64NanoTS + 4]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64CurNanoTS, ecx
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64CurNanoTS_Hi, ebx
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ecx, [edi + SUPGIPCPU.u64TSC]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ebx, [edi + SUPGIPCPU.u64TSC + 4]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ecx, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u64TSC]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov ebx, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u64TSC + 4]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64TSC, ecx
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64TSC_Hi, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64PrevNanoTS = ASMAtomicReadU64(pu64Prev);
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; This serializes load/save. And with the dependency on the
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; RDTSC result, we try to make sure it has completed as well.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, pData
b92634cd549ff80a3b9136227345237116ccd4favboxsync mov esi, [esi + RTTIMENANOTSDATA.pu64Prev]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov edi, pData
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov edi, [esi + RTTIMENANOTSDATA.pu64Prev]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, eax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, edx
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
b92634cd549ff80a3b9136227345237116ccd4favboxsync lock cmpxchg8b [esi]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync lock cmpxchg8b [edi]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64PrevNanoTS, eax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64PrevNanoTS_Hi, edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SAVED_u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Check that the GIP and CPU didn't change.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; We've already serialized all the loads and stores at this point.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef NEED_APIC_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64RetNanoTS, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64RetNanoTS_Hi, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %define SAVED_u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cpuid
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp u32ApicIdPlus, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .ReadGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, [edi + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov esi, [esi + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp esi, u32TransactionId
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .ReadGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync test esi, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .ReadGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif ; NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef SAVED_u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, u64RetNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Calc the timestamp.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS -= u64TSC;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub ebx, u64TSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sbb ecx, u64TSC_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (u64RetNanoTS > u32UpdateIntervalTSC) -> jump
1e40f57c72c881067b0314f898e1004211bb7650vboxsync or ecx, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .OverFlow
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp ebx, u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ja .OverFlow
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.ContinueCalcs: ; eax <= u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mul dword u32UpdateIntervalNS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync div dword u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync xor edx, edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS += u64CurNanoTS;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add eax, u64CurNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync adc edx, u64CurNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Compare it with the previous one.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (RT_LIKELY( u64RetNanoTS > u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; && u64RetNanoTS < u64PrevNanoTS + UINT64_C(86000000000000) /* 24h */))
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; @todo optimize this compare (/me too tired).
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, u64PrevNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp edx, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ja .Compare2
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jb .DeltaPrevTooBig
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp eax, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jbe .DeltaPrevTooBig
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Compare2:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add ebx, 0x6F736000
1e40f57c72c881067b0314f898e1004211bb7650vboxsync adc ecx, 0x00004E37
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp edx, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jb .CompareDone
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ja .DeltaPrevTooBig
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp eax, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jae .DeltaPrevTooBig
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.CompareDone:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Update the previous value with the u64RetNanoTS value.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Update:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (RT_LIKELY(ASMAtomicCmpXchgU64(&pData->u64Prev, u64RetNanoTS, u64PrevNanoTS)))
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, eax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, pData
b92634cd549ff80a3b9136227345237116ccd4favboxsync mov esi, [esi + RTTIMENANOTSDATA.pu64Prev]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edx, u64PrevNanoTS_Hi
b92634cd549ff80a3b9136227345237116ccd4favboxsync lock cmpxchg8b [esi]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .UpdateFailed
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Updated:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edx, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Done:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, SavedESI
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edi, SavedEDI
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, SavedEBX
1e40f57c72c881067b0314f898e1004211bb7650vboxsync leave
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ret
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; We've expired the interval, cap it. If we're here for the 2nd
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; time without any GIP update in-between, the checks against
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; pData->u64Prev below will force 1ns stepping.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.OverFlow:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64Delta = u32UpdateIntervalTSC;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync inc dword [esi + RTTIMENANOTSDATA.cExpired]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .ContinueCalcs
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; u64DeltaPrev >= 24h
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; eax:edx = u64RetNanoTS (to be adjusted)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.DeltaPrevTooBig:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; uint64_t u64DeltaPrev = u64RetNanoTS - u64PrevNanoTS;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ebx, eax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub ebx, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sbb ecx, u64PrevNanoTS_Hi ; ebx:ecx = u64DeltaPrev
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; else if ( (int64_t)u64DeltaPrev <= 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; && (int64_t)u64DeltaPrev + u32UpdateIntervalNS * 2 >= 0)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* Occasional - u64RetNanoTS is in the recent 'past' relative the previous call. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; pData->c1nsSteps++;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS = u64PrevNanoTS + 1;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, u32UpdateIntervalNS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp ecx, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jl .PrevNotZero2ndTest
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jg .DeltaPrevNotInRecentPast
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp ebx, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ja .DeltaPrevNotInRecentPast
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.PrevNotZero2ndTest:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add esi, esi ; ASSUMES: u32UpdateIntervalNS * 2 <= 32-bit.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync xor edi, edi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add esi, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync adc edi, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync test edi, edi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync js .DeltaPrevNotInRecentPast
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.DeltaPrevInRecentPast:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync inc dword [esi + RTTIMENANOTSDATA.c1nsSteps]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edx, u64PrevNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add eax, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync adc edx, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Update
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.DeltaPrevNotInRecentPast:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; else if (!u64PrevNanoTS) /* We're resuming (see TMVirtualResume). */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* do nothing */;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp dword u64PrevNanoTS, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .DeltaPrevNotZero
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp dword u64PrevNanoTS_Hi, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .DeltaPrevNotZero
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Update
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.DeltaPrevNotZero:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* Something has gone bust, if negative offset it's real bad. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; rtTimeNanoTSInternalBitch(pVM,
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; call C function that does the bitching.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64RetNanoTS, eax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64RetNanoTS_Hi, edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edi, u64PrevNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov esi, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push edi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push esi ; 4 - u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push ebx ; 3 - u64DeltaPrev
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push eax ; 2 - u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push eax ; 1 - pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync call dword [eax + RTTIMENANOTSDATA.pfnBad]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add esp, 4*7
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edx, u64RetNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Update
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Attempt updating the previous value, provided we're still ahead of it.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; There is no point in recalculating u64NanoTS because we got preempted or if
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; we raced somebody while the GIP was updated, since these are events
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; that might occur at any point in the return path as well.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; eax:edx = *pData->u64Prev
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; ebx:ecx = u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ALIGNCODE(16)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.UpdateFailed:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edi, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lock inc dword [edi + RTTIMENANOTSDATA.cUpdateRaces]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; for (i = 0; i < 10; i++)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov edi, 10
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.UpdateLoop:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (u64PrevNanoTS >= u64NanoTS)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; break;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp edx, ecx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jg .Updated
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .UpdateLoopLess
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp eax, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jae .Updated
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.UpdateLoopLess:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; retry
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lock cmpxchg8b [esi]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jz .Updated
1e40f57c72c881067b0314f898e1004211bb7650vboxsync dec edi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .UpdateLoop
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Updated
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; The GIP is seemingly invalid, redo the discovery.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Rediscover:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push eax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync call [eax + RTTIMENANOTSDATA.pfnRediscover]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add esp, 4h
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Done
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef WITH_TSC_DELTA
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;; Unlikely branch for when we think the TSC delta might be invalid.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync.TscDeltaPossiblyInvalid:
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync cmp dword [edi + SUPGIPCPU.i64TSCDelta + 4], 0x7fffffff
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync jne .TscDeltaValid
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync jmp .TscDeltaNotValid
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Cleanup variables
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64Delta_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64Delta
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32UpdateIntervalNS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64TSC_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64TSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64NanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64NanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64PrevNanoTS_Hi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32TransactionId
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u8ApicId
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%else ; AMD64
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync; The AMD64 assembly implementation of the assembly routines.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync; @returns Nanosecond timestamp.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync; @param pData gcc:rdi msc:rcx Pointer to the nanosecond timestamp data.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync;
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncBEGINPROC rtTimeNanoTSInternalAsm
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Define variables and stack frame.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedRBX [rbp - 08h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedR12 [rbp - 10h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedR13 [rbp - 18h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedRDI [rbp - 20h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define SavedRSI [rbp - 28h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define TmpVar [rbp - 30h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define TmpVar2 [rbp - 38h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef NEED_TRANSACTION_ID
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef NEED_APIC_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %define SavedR14 [rbp - 40h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %define SavedR15 [rbp - 48h]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define pData rdi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %define u64TSC rsi
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %define pGip rsi
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef NEED_APIC_ID
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %define pGipCPU r8
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %define u64TSC r8
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %define pGip rsi
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef NEED_APIC_ID
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %define pGipCPU r8
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32TransactionId r9d
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64CurNanoTS r10
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u64PrevNanoTS r11 ; not parameter register
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32UpdateIntervalTSC r12d
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32UpdateIntervalTSC_64 r12
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32UpdateIntervalNS r13d
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%define u32UpdateIntervalNS_64 r13
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64SavedRetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32ApicIdPlus
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef NEED_TRANSACTION_ID
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef NEED_APIC_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %define u64SavedRetNanoTS r14
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %define u32ApicIdPlus r15d
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; The prolog.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync push rbp
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rbp, rsp
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef ASM_CALL64_MSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub rsp, 50h+20h
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub rsp, 50h
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedRBX, rbx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedR12, r12
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedR13, r13
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef ASM_CALL64_MSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedRDI, rdi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedRSI, rsi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov pData, rcx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;mov pData, rdi - already in rdi.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef SavedR14
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedR14, r14
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef SavedR15
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov SavedR15, r15
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Data fetch loop.
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; We take great pain ensuring that data consistency here.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.ReadGip:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; Load pGip - finding the GIP is fun...
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
a4a232fa546df3af50f9389873b521028eed4cdevboxsync%ifdef RT_OS_WINDOWS
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %ifdef IMPORTED_SUPLIB
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %ifdef IN_RING0
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov rax, qword IMP(g_SUPGlobalInfoPage)
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, rax
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %else
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, [IMP(g_pSUPGlobalInfoPage) wrt rip]
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, [pGip]
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %endif
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %else
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, [NAME(g_pSUPGlobalInfoPage) wrt rip]
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %endif
a4a232fa546df3af50f9389873b521028eed4cdevboxsync%else
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %ifdef IN_RING0
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov rax, qword NAME(g_SUPGlobalInfoPage)
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, rax
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %else
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, [rel NAME(g_pSUPGlobalInfoPage) wrt ..gotpcrel]
a4a232fa546df3af50f9389873b521028eed4cdevboxsync mov pGip, [pGip]
a4a232fa546df3af50f9389873b521028eed4cdevboxsync %endif
a4a232fa546df3af50f9389873b521028eed4cdevboxsync%endif
a4a232fa546df3af50f9389873b521028eed4cdevboxsync or pGip, pGip
a4a232fa546df3af50f9389873b521028eed4cdevboxsync jz .Rediscover
a4a232fa546df3af50f9389873b521028eed4cdevboxsync cmp dword [pGip + SUPGLOBALINFOPAGE.u32Magic], SUPGLOBALINFOPAGE_MAGIC
a4a232fa546df3af50f9389873b521028eed4cdevboxsync jne .Rediscover
a4a232fa546df3af50f9389873b521028eed4cdevboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; pGipCPU, setting u32ApicIdPlus if necessary.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef NEED_APIC_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u8ApicId = ASMGetApicId();
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cpuid ; expensive
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %ifdef NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u32ApicIdPlus, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync ; pGipCPU = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]];
1e40f57c72c881067b0314f898e1004211bb7650vboxsync shr ebx, 24
cd7a8c034836a94a0c4f0adf9764f9ed661cdd01vboxsync movzx eax, word [pGip + rbx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId]
dd8f19fe611a226bfffca18f5b2e40510d11a2edvboxsync imul eax, SUPGIPCPU_size
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lea pGipCPU, [pGip + rax + SUPGLOBALINFOPAGE.aCPUs]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Serialized loading of u32TransactionId.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u32TransactionId, [pGipCPU + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u32TransactionId, [pGip + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %ifdef USE_LFENCE
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lfence
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lock xor dword TmpVar, 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Load the data and TSC.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u32UpdateIntervalNS, [pGip + SUPGLOBALINFOPAGE.u32UpdateIntervalNS]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u32UpdateIntervalTSC, [pGipCPU + SUPGIPCPU.u32UpdateIntervalTSC]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u32UpdateIntervalTSC, [pGip + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u32UpdateIntervalTSC]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync rdtsc
b92634cd549ff80a3b9136227345237116ccd4favboxsync mov u64PrevNanoTS, [pData + RTTIMENANOTSDATA.pu64Prev]
b92634cd549ff80a3b9136227345237116ccd4favboxsync mov u64PrevNanoTS, [u64PrevNanoTS]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync shl rdx, 32
1e40f57c72c881067b0314f898e1004211bb7650vboxsync or rax, rdx ; rax is u64RetNanoTS.
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef WITH_TSC_DELTA
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov rdx, [pGipCPU + SUPGIPCPU.i64TSCDelta]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64CurNanoTS, 0x7fffffffffffffff ; INT64_MAX - temporarily borrowing u64CurNanoTS
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync cmp rdx, u64CurNanoTS
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync je .TscDeltaNotValid
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync sub rax, rdx
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync.TscDeltaNotValid:
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef u64SavedRetNanoTS ; doing this here may save a tick or so?
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64SavedRetNanoTS, rax
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov u64CurNanoTS, [pGipCPU + SUPGIPCPU.u64NanoTS]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64TSC, [pGipCPU + SUPGIPCPU.u64TSC] ; transhes pGIP!
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64CurNanoTS, [pGip + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u64NanoTS]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync mov u64TSC, [pGip + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u64TSC] ; trashes pGipCPU!
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync%endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Check that the GIP and CPU didn't change.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; It is crucial that the rdtsc instruction has completed before
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; we check the transaction id. The LOCK prefixed instruction with
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; dependency on the RDTSC result should do the trick, I think.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; CPUID is serializing, so the async path is safe by default.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef NEED_APIC_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cpuid
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp u32ApicIdPlus, ebx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .ReadGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lock xor qword TmpVar, rax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %ifdef ASYNC_GIP
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp u32TransactionId, [pGipCPU + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %else
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync cmp u32TransactionId, [pGip + SUPGLOBALINFOPAGE.aCPUs + SUPGIPCPU.u32TransactionId]
443b47b0e450919f5012681d9ec4cdccc1ebab08vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jne .ReadGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync test u32TransactionId, 1
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .ReadGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %ifdef u64SavedRetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rax, u64SavedRetNanoTS ; rax is u64RetNanoTS.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync %endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif ; NEED_TRANSACTION_ID
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Calc the timestamp.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS -= u64TSC;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub rax, u64TSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync xor edx, edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (u64RetNanoTS > u32UpdateIntervalTSC) -> jump
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp rax, u32UpdateIntervalTSC_64
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ja .OverFlow
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.ContinueCalcs: ; edx = 0; eax <= u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mul u32UpdateIntervalNS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync div u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS += u64CurNanoTS;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add rax, u64CurNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Compare it with the previous one.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (RT_LIKELY( u64RetNanoTS > u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; && u64RetNanoTS < u64PrevNanoTS + UINT64_C(86000000000000) /* 24h */))
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* Frequent - less than 24h since last call. */;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp rax, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jbe .DeltaPrevTooBig
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov ecx, 5
1e40f57c72c881067b0314f898e1004211bb7650vboxsync shl rcx, 44 ; close enough
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add rcx, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp rax, rcx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jae .DeltaPrevTooBig
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Update the previous value.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Update:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (RT_LIKELY(ASMAtomicCmpXchgU64(&pData->u64Prev, u64RetNanoTS, u64PrevNanoTS)))
b92634cd549ff80a3b9136227345237116ccd4favboxsync mov rbx, [pData + RTTIMENANOTSDATA.pu64Prev]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rcx, rax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rax, u64PrevNanoTS
b92634cd549ff80a3b9136227345237116ccd4favboxsync lock cmpxchg [rbx], rcx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .UpdateFailed
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Updated:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rax, rcx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Done:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rbx, SavedRBX
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov r12, SavedR12
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov r13, SavedR13
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef SavedR14
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov r14, SavedR14
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef SavedR15
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov r15, SavedR15
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef ASM_CALL64_MSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rdi, SavedRDI
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rsi, SavedRSI
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync leave
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ret
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; We've expired the interval, cap it. If we're here for the 2nd
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; time without any GIP update in-between, the checks against
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; pData->u64Prev below will force 1ns stepping.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncALIGNCODE(16)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.OverFlow:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS = u32UpdateIntervalTSC;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync inc dword [pData + RTTIMENANOTSDATA.cExpired]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov eax, u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .ContinueCalcs
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; u64DeltaPrev >= 24h
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; rax = u64RetNanoTS (to be adjusted)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncALIGNCODE(16)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.DeltaPrevTooBig:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; uint64_t u64DeltaPrev = u64RetNanoTS - u64PrevNanoTS;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rbx, rax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync sub rbx, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; else if ( (int64_t)u64DeltaPrev <= 0
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; && (int64_t)u64DeltaPrev + u32UpdateIntervalNS * 2 >= 0)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* Occasional - u64NanoTS is in the recent 'past' relative the previous call. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; pData->c1nsSteps++;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; u64RetNanoTS = u64PrevNanoTS + 1;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync test rbx, rbx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jg .DeltaPrevNotInRecentPast
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lea rdx, [u32UpdateIntervalNS_64 + u32UpdateIntervalNS_64]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync add rdx, rbx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync js .DeltaPrevNotInRecentPast
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; body
1e40f57c72c881067b0314f898e1004211bb7650vboxsync inc dword [pData + RTTIMENANOTSDATA.c1nsSteps]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lea rax, [u64PrevNanoTS + 1]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Update
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; else if (!u64PrevNanoTS) /* We're resuming (see TMVirtualResume) / first call. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* do nothing */;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.DeltaPrevNotInRecentPast:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync or u64PrevNanoTS, u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jz .Update
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; {
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; /* Something has gone bust, if negative offset it's real bad. */
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; rtTimeNanoTSInternalBitch(pVM,
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; }
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; call C function that does the bitching.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov TmpVar, rax
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov TmpVar2, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef ASM_CALL64_MSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rcx, pData ; param 1 - pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rdx, rax ; param 2 - u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov r8, rbx ; param 3 - u64DeltaPrev
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov r9, u64PrevNanoTS ; param 4 - u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;mov rdi, pData - already in rdi; param 1 - pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rsi, rax ; param 2 - u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rdx, rbx ; param 3 - u64DeltaPrev
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rcx, u64PrevNanoTS ; param 4 - u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync call qword [pData + RTTIMENANOTSDATA.pfnBad]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rax, TmpVar
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov pData, TmpVar2
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Update
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; Attempt updating the previous value, provided we're still ahead of it.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; There is no point in recalculating u64NanoTS because we got preempted or if
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; we raced somebody while the GIP was updated, since these are events
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync ;; that might occur at any point in the return path as well.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; rax = *pData->u64Prev;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; rcx = u64RetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncALIGNCODE(16)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.UpdateFailed:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync lock inc dword [pData + RTTIMENANOTSDATA.cUpdateRaces]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; for (i = 0; i < 10; i++)
b92634cd549ff80a3b9136227345237116ccd4favboxsync mov edx, 10
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.UpdateLoop:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; if (u64PrevNanoTS >= u64RetNanoTS)
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; break;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync cmp rax, rcx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jge .Updated
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.UpdateLoopLess:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; retry
b92634cd549ff80a3b9136227345237116ccd4favboxsync lock cmpxchg [rbx], rcx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jz .Updated
b92634cd549ff80a3b9136227345237116ccd4favboxsync dec edx
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jnz .UpdateLoop
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Updated
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;; The GIP is seemingly invalid, redo the discovery.
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync.Rediscover:
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%ifdef ASM_CALL64_MSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync mov rcx, pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%else
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; mov rdi, pData - already in rdi
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif
1e40f57c72c881067b0314f898e1004211bb7650vboxsync call [pData + RTTIMENANOTSDATA.pfnRediscover]
1e40f57c72c881067b0314f898e1004211bb7650vboxsync jmp .Done
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ; Cleanup variables
1e40f57c72c881067b0314f898e1004211bb7650vboxsync ;
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedRBX
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedR12
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedR13
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedR14
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedR15
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedRDI
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef SavedRSI
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef pData
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef TmpVar
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64TSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef pGip
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef pGipCPU
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32TransactionId
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64CurNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64PrevNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32UpdateIntervalTSC
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32UpdateIntervalTSC_64
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32UpdateIntervalNS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u64SavedRetNanoTS
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%undef u32ApicIdPlus
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync%endif ; AMD64
1e40f57c72c881067b0314f898e1004211bb7650vboxsyncENDPROC rtTimeNanoTSInternalAsm
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync
1e40f57c72c881067b0314f898e1004211bb7650vboxsync