From: Duke Zhai <duke.z...@amd.com> BZ #:4640 In V2: Improve coding style. 1.Remove the leading underscore and use double underscore at trailing in C header files. 2.Remove old tianocore licenses and redundant license description. 3.Improve coding style. For example: remove space between @param.
In V1: Provides basic TSC timer calibration based on the ACPI timer hardware. The performance counter features are provided by the processors time stamp counter. Signed-off-by: Ken Yao <ken....@amd.com> Cc: Eric Xing <eric.x...@amd.com> Cc: Duke Zhai <duke.z...@amd.com> Cc: Igniculus Fu <igniculus...@amd.com> Cc: Abner Chang <abner.ch...@amd.com> --- .../Library/TscTimerLib/BaseTscTimerLib.c | 23 ++ .../Library/TscTimerLib/BaseTscTimerLib.inf | 43 +++ .../Library/TscTimerLib/DxeTscTimerLib.c | 80 ++++++ .../Library/TscTimerLib/DxeTscTimerLib.inf | 62 +++++ .../Library/TscTimerLib/PeiTscTimerLib.c | 53 ++++ .../Library/TscTimerLib/PeiTscTimerLib.inf | 56 ++++ .../Library/TscTimerLib/TscTimerLibInternal.h | 53 ++++ .../Library/TscTimerLib/TscTimerLibShare.c | 255 ++++++++++++++++++ 8 files changed, 625 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c new file mode 100644 index 0000000000..7dfef490e9 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c @@ -0,0 +1,23 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "TscTimerLibInternal.h" + +/** Get TSC frequency. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ) +{ + return InternalCalculateTscFrequency (); +} diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf new file mode 100644 index 0000000000..d6c4e2e1d6 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf @@ -0,0 +1,43 @@ +## @file +# BaseTscTimerLib +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseTscTimerLib + FILE_GUID = D29338B9-50FE-4e4f-B7D4-A150A2C1F4FB + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLibShare.c + BaseTscTimerLib.c + TscTimerLibInternal.h + + +[Packages] + MdePkg/MdePkg.dec + AgesaPublic/AgesaPublic.dec + + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + +[Pcd.common] + gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c new file mode 100644 index 0000000000..5a374665c3 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c @@ -0,0 +1,80 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/DebugLib.h> +#include "TscTimerLibInternal.h" + +UINT64 mTscFrequency; + +/** The constructor function determines the actual TSC frequency. + + First, Get TSC frequency from system configuration table with TSC frequency GUID, + if the table is not found, install it. + This function will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeTscTimerLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT64 *TscFrequency; + + TscFrequency = NULL; + // + // Get TSC frequency from system configuration table with TSC frequency GUID. + // + Status = EfiGetSystemConfigurationTable (&gAmdCommonPkgTscFrequencyGuid, (VOID **)&TscFrequency); + if (Status == EFI_SUCCESS) { + ASSERT (TscFrequency != NULL); + mTscFrequency = *TscFrequency; + return EFI_SUCCESS; + } + + // + // TSC frequency GUID system configuration table is not found, install it. + // + + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (UINT64), (VOID **)&TscFrequency); + ASSERT_EFI_ERROR (Status); + + *TscFrequency = InternalCalculateTscFrequency (); + // + // TscFrequency now points to the number of TSC counts per second, install system configuration table for it. + // + gBS->InstallConfigurationTable (&gAmdCommonPkgTscFrequencyGuid, TscFrequency); + + mTscFrequency = *TscFrequency; + return EFI_SUCCESS; +} + +/** Get TSC frequency. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ) +{ + return mTscFrequency; +} diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf new file mode 100644 index 0000000000..c1a5d39ab1 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf @@ -0,0 +1,62 @@ +## @file +# DxeTscTimerLib +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +## @file +# DXE ACPI Timer Library +# +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Note: The implementation uses the lower 24-bits of the ACPI timer and +# is compatible with both 24-bit and 32-bit ACPI timers. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeTscTimerLib + FILE_GUID = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = DxeTscTimerLibConstructor + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLibShare.c + DxeTscTimerLib.c + TscTimerLibInternal.h + + +[Packages] + MdePkg/MdePkg.dec + VanGoghCommonPkg/AmdCommonPkg.dec + AgesaPublic/AgesaPublic.dec + +[LibraryClasses] + UefiBootServicesTableLib + PcdLib + PciLib + IoLib + BaseLib + UefiLib + DebugLib + +[Guids] + gAmdCommonPkgTscFrequencyGuid ## CONSUMES ## System Configuration Table + +[Pcd.common] + gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c new file mode 100644 index 0000000000..338821b5d7 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c @@ -0,0 +1,53 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> +#include <Library/HobLib.h> +#include "TscTimerLibInternal.h" + +/** Get TSC frequency from TSC frequency GUID HOB, if the HOB is not found, build it. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + VOID *DataInHob; + UINT64 TscFrequency; + + // + // Get TSC frequency from TSC frequency GUID HOB. + // + GuidHob = GetFirstGuidHob (&gAmdCommonPkgTscFrequencyGuid); + if (GuidHob != NULL) { + DataInHob = GET_GUID_HOB_DATA (GuidHob); + TscFrequency = *(UINT64 *)DataInHob; + return TscFrequency; + } + + // + // TSC frequency GUID HOB is not found, build it. + // + + TscFrequency = InternalCalculateTscFrequency (); + // + // TscFrequency is now equal to the number of TSC counts per second, build GUID HOB for it. + // + BuildGuidDataHob ( + &gAmdCommonPkgTscFrequencyGuid, + &TscFrequency, + sizeof (UINT64) + ); + + return TscFrequency; +} diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf new file mode 100644 index 0000000000..e1c3bb695c --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf @@ -0,0 +1,56 @@ +## @file +# PeiTscTimerLib +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +## @file +# PEI ACPI Timer Library +# +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Note: The implementation uses the lower 24-bits of the ACPI timer and +# is compatible with both 24-bit and 32-bit ACPI timers. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiTscTimerLib + FILE_GUID = 342C36C0-15DF-43b4-9EC9-FBF748BFB3D1 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|PEIM PEI_CORE + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLibShare.c + PeiTscTimerLib.c + TscTimerLibInternal.h + +[Packages] + MdePkg/MdePkg.dec + AgesaPublic/AgesaPublic.dec + VanGoghCommonPkg/AmdCommonPkg.dec + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + HobLib + +[Guids] + gAmdCommonPkgTscFrequencyGuid ## PRODUCES ## HOB + +[Pcd.common] + gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h new file mode 100644 index 0000000000..cd4fc9db14 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h @@ -0,0 +1,53 @@ +/** @file + Header file internal to ACPI TimerLib. + +Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> +Copyright (c) Microsoft Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef TSC_TIMER_LIB_INTERNAL_H__ +#define TSC_TIMER_LIB_INTERNAL_H__ + +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> +#include <Library/IoLib.h> +#include <Library/PciLib.h> +#include <Library/PcdLib.h> + +#include <Library/IoLib.h> +#define ACPI_MMIO_BASE 0xFED80000ul +#define PMIO_BASE 0x300 // DWORD +#define FCH_PMIOA_REG64 0x64 // AcpiPmTmrBlk + +/** Get TSC frequency. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ); + +/** Calculate TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 1ms period as determined by the ACPI timer. The ACPI timer is + used because it counts at a known frequency. + If ACPI I/O space not enabled, this function will enable it. Then the + TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms. + The TSC is then sampled again. The difference multiplied by 1000 is the TSC + frequency. There will be a small error because of the overhead of reading + the ACPI timer. An attempt is made to determine and compensate for this error. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ); + +#endif diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c new file mode 100644 index 0000000000..a49a2db2b3 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c @@ -0,0 +1,255 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "TscTimerLibInternal.h" + +/** Calculate TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 1ms period as determined by the ACPI timer. The ACPI timer is + used because it counts at a known frequency. + If ACPI I/O space not enabled, this function will enable it. Then the + TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms. + The TSC is then sampled again. The difference multiplied by 1000 is the TSC + frequency. There will be a small error because of the overhead of reading + the ACPI timer. An attempt is made to determine and compensate for this error. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ) +{ + UINT64 StartTSC; + UINT64 EndTSC; + UINT16 TimerAddr; + UINT32 Ticks; + UINT64 TscFrequency; + + TimerAddr = MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG64); + if (TimerAddr == 0) { + TimerAddr = PcdGet16 (PcdAmdFchCfgAcpiPmTmrBlkAddr); + MmioWrite16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG64, TimerAddr); + } + + // + // ACPI I/O space should be enabled now, locate the ACPI Timer. + // ACPI I/O base address maybe have be initialized by other driver with different value, + // So get it from PCI space directly. + // + Ticks = IoRead32 (TimerAddr) + (3579); // Set Ticks to 1ms in the future + StartTSC = AsmReadTsc (); // Get base value for the TSC + // + // Wait until the ACPI timer has counted 1ms. + // Timer wrap-arounds are handled correctly by this function. + // When the current ACPI timer value is greater than 'Ticks', the while loop will exit. + // + while (((Ticks - IoRead32 (TimerAddr)) & BIT23) == 0) { + CpuPause (); + } + + EndTSC = AsmReadTsc (); // TSC value 1ms later + + TscFrequency = MultU64x32 ( + (EndTSC - StartTSC), // Number of TSC counts in 1ms + 1000 // Number of ms in a second + ); + + return TscFrequency; +} + +/** Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param[in] Delay A period of time to delay in ticks. + +**/ +VOID +InternalX86Delay ( + IN UINT64 Delay + ) +{ + UINT64 Ticks; + + // + // The target timer count is calculated here + // + Ticks = AsmReadTsc () + Delay; + + // + // Wait until time out + // Timer wrap-arounds are NOT handled correctly by this function. + // Thus, this function must be called within 10 years of reset since + // Intel ensures a minimum of 10 years before the TSC wraps. + // + while (AsmReadTsc () <= Ticks) { + CpuPause (); + } +} + +/** Stalls the CPU for at least the specified number of MicroSeconds. + + @param[in] MicroSeconds The minimum number of microseconds to delay. + + @return The value of MicroSeconds input. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + InternalX86Delay ( + DivU64x32 ( + MultU64x64 ( + InternalGetTscFrequency (), + MicroSeconds + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** Stalls the CPU for at least the specified number of NanoSeconds. + + @param[in] NanoSeconds The minimum number of nanoseconds to delay. + + @return The value of NanoSeconds input. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + InternalX86Delay ( + DivU64x32 ( + MultU64x32 ( + InternalGetTscFrequency (), + (UINT32)NanoSeconds + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** Retrieves the current value of the 64-bit free running Time-Stamp counter. + + The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M, + Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and + later processors) is a 64-bit counter that is set to 0 following a RESET of + the processor. Following a RESET, the counter increments even when the + processor is halted by the HLT instruction or the external STPCLK# pin. Note + that the assertion of the external DPSLP# pin may cause the time-stamp + counter to stop. + + The properties of the counter can be retrieved by the + GetPerformanceCounterProperties() function. + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return AsmReadTsc (); +} + +/** Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with, 0x0, is returned in StartValue. If EndValue is not NULL, then the value + that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in + EndValue. + + The 64-bit frequency of the performance counter, in Hz, is always returned. + To determine average processor clock frequency, Intel recommends the use of + EMON logic to count processor core clocks over the period of time for which + the average is required. + + + @param[out] StartValue Pointer to where the performance counter's starting value is saved, or NULL. + @param[out] EndValue Pointer to where the performance counter's ending value is saved, or NULL. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + *StartValue = 0; + } + + if (EndValue != NULL) { + *EndValue = 0xFFFFFFFFFFFFFFFFull; + } + + return InternalGetTscFrequency (); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency = GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, + // i.e. highest bit set in Remainder should <= 33. + // + Shift = MAX (0, HighBitSet64 (Remainder) - 33); + Remainder = RShiftU64 (Remainder, (UINTN)Shift); + Frequency = RShiftU64 (Frequency, (UINTN)Shift); + NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); + + return NanoSeconds; +} -- 2.31.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114509): https://edk2.groups.io/g/devel/message/114509 Mute This Topic: https://groups.io/mt/103971406/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-