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]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to