From: Duke Zhai <Duke.Zhai@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.yao@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@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/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.