From: Duke Zhai <duke.z...@amd.com>

BZ #:4640

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     |  32 +++

 .../Library/TscTimerLib/BaseTscTimerLib.inf   |  55 ++++

 .../Library/TscTimerLib/DxeTscTimerLib.c      |  89 ++++++

 .../Library/TscTimerLib/DxeTscTimerLib.inf    |  62 ++++

 .../Library/TscTimerLib/PeiTscTimerLib.c      |  62 ++++

 .../Library/TscTimerLib/PeiTscTimerLib.inf    |  56 ++++

 .../Library/TscTimerLib/TscTimerLibInternal.h |  62 ++++

 .../Library/TscTimerLib/TscTimerLibShare.c    | 264 ++++++++++++++++++

 8 files changed, 682 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..a4e37da22e

--- /dev/null

+++ 
b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c

@@ -0,0 +1,32 @@

+/** @file

+  Implements AMD BaseTscTimerLib.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  ACPI Timer implements one instance of Timer Library.

+

+  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..7dc29cef40

--- /dev/null

+++ 
b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf

@@ -0,0 +1,55 @@

+## @file

+# BaseTscTimerLib

+#

+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+# This file includes code originally published under the following license.

+## @file

+#  Base 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                      = 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..e0616565fc

--- /dev/null

+++ 
b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c

@@ -0,0 +1,89 @@

+/** @file

+  Implements AMD DxeTscTimerLib.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  ACPI Timer implements one instance of Timer Library.

+

+  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..d2a562197a

--- /dev/null

+++ 
b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c

@@ -0,0 +1,62 @@

+/** @file

+  Implements AMD PeiTscTimerLib.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  ACPI Timer implements one instance of Timer Library.

+

+  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..68d0949cbd

--- /dev/null

+++ 
b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h

@@ -0,0 +1,62 @@

+/** @file

+  Implements AMD TscTimerLibInternal.h

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  Header file internal to ACPI TimerLib.

+

+Copyright (c) Microsoft Corporation.

+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..39eff36abc

--- /dev/null

+++ 
b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c

@@ -0,0 +1,264 @@

+/** @file

+  Implements AMD TscTimerLibShare.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  ACPI Timer implements one instance of Timer Library.

+

+  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 (#114065): https://edk2.groups.io/g/devel/message/114065
Mute This Topic: https://groups.io/mt/103831177/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to