public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-12  5:14 Donald Kuo
  0 siblings, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-12  5:14 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  17 ++
 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 290 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   4 +-
 6 files changed, 393 insertions(+), 1 deletion(-)
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c

diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..ccb92a95d3
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,40 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..c31dacd57a
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
\ No newline at end of file
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..5ed01146cf
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,290 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX Eax;
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Display CPU FAMILY / MODEL / STEPPING ID Info
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+  DEBUG ((DEBUG_INFO, "CPUID = %X\n", (Eax.Uint32 & 0x0FFF0FFF)));
+  
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+  DEBUG ((DEBUG_INFO, "Denominator of the TSC ratio = %d\n", RegEax));
+  DEBUG ((DEBUG_INFO, "Numerator of the TSC ratio = %d\n", RegEbx));
+  DEBUG ((DEBUG_INFO, "Nominal frequency (hertz) = %d\n", RegEcx));
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  if (RegEbx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    ASSERT (RegEbx != 0);
+  }
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+    DEBUG ((DEBUG_INFO, "CoreXtalFrequency (hertz) from PCD = %d\n", CoreXtalFrequency));
+    //ASSERT (RegEcx != 0);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "MicroSecDelay = %d\n", MicroSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "NanoSecDelay = %d\n", NanoSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..2d4eb931e1 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -42,7 +42,7 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+#  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
@@ -56,6 +56,7 @@
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+  TimerLib|UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [LibraryClasses.common.SEC]
   PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -143,6 +144,7 @@
       SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   }
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-12  5:24 Donald Kuo
  0 siblings, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-12  5:24 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  17 ++
 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 290 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   4 +-
 6 files changed, 393 insertions(+), 1 deletion(-)
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c

diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..ccb92a95d3
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,40 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..c31dacd57a
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
\ No newline at end of file
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..5ed01146cf
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,290 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX Eax;
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Display CPU FAMILY / MODEL / STEPPING ID Info
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+  DEBUG ((DEBUG_INFO, "CPUID = %X\n", (Eax.Uint32 & 0x0FFF0FFF)));
+  
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+  DEBUG ((DEBUG_INFO, "Denominator of the TSC ratio = %d\n", RegEax));
+  DEBUG ((DEBUG_INFO, "Numerator of the TSC ratio = %d\n", RegEbx));
+  DEBUG ((DEBUG_INFO, "Nominal frequency (hertz) = %d\n", RegEcx));
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  if (RegEbx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    ASSERT (RegEbx != 0);
+  }
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+    DEBUG ((DEBUG_INFO, "CoreXtalFrequency (hertz) from PCD = %d\n", CoreXtalFrequency));
+    //ASSERT (RegEcx != 0);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "MicroSecDelay = %d\n", MicroSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "NanoSecDelay = %d\n", NanoSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..2d4eb931e1 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -42,7 +42,7 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+#  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
@@ -56,6 +56,7 @@
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+  TimerLib|UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [LibraryClasses.common.SEC]
   PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -143,6 +144,7 @@
       SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   }
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-12  5:42 Donald Kuo
  0 siblings, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-12  5:42 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  17 ++
 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 290 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   4 +-
 6 files changed, 393 insertions(+), 1 deletion(-)
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c

diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..ccb92a95d3
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,40 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..c31dacd57a
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
\ No newline at end of file
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..5ed01146cf
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,290 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX Eax;
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Display CPU FAMILY / MODEL / STEPPING ID Info
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+  DEBUG ((DEBUG_INFO, "CPUID = %X\n", (Eax.Uint32 & 0x0FFF0FFF)));
+  
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+  DEBUG ((DEBUG_INFO, "Denominator of the TSC ratio = %d\n", RegEax));
+  DEBUG ((DEBUG_INFO, "Numerator of the TSC ratio = %d\n", RegEbx));
+  DEBUG ((DEBUG_INFO, "Nominal frequency (hertz) = %d\n", RegEcx));
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  if (RegEbx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    ASSERT (RegEbx != 0);
+  }
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+    DEBUG ((DEBUG_INFO, "CoreXtalFrequency (hertz) from PCD = %d\n", CoreXtalFrequency));
+    //ASSERT (RegEcx != 0);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "MicroSecDelay = %d\n", MicroSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "NanoSecDelay = %d\n", NanoSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..2d4eb931e1 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -42,7 +42,7 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+#  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
@@ -56,6 +56,7 @@
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+  TimerLib|UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [LibraryClasses.common.SEC]
   PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -143,6 +144,7 @@
       SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   }
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-12  5:56 Donald Kuo
  2019-08-12 10:26 ` Zeng, Star
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-12  5:56 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  17 ++
 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 290 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   4 +-
 6 files changed, 393 insertions(+), 1 deletion(-)
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c

diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..ccb92a95d3
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,40 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..c31dacd57a
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
\ No newline at end of file
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..5ed01146cf
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,290 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX Eax;
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Display CPU FAMILY / MODEL / STEPPING ID Info
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+  DEBUG ((DEBUG_INFO, "CPUID = %X\n", (Eax.Uint32 & 0x0FFF0FFF)));
+  
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+  DEBUG ((DEBUG_INFO, "Denominator of the TSC ratio = %d\n", RegEax));
+  DEBUG ((DEBUG_INFO, "Numerator of the TSC ratio = %d\n", RegEbx));
+  DEBUG ((DEBUG_INFO, "Nominal frequency (hertz) = %d\n", RegEcx));
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  if (RegEbx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    ASSERT (RegEbx != 0);
+  }
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock Frequency !!\n"));
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+    DEBUG ((DEBUG_INFO, "CoreXtalFrequency (hertz) from PCD = %d\n", CoreXtalFrequency));
+    //ASSERT (RegEcx != 0);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "MicroSecDelay = %d\n", MicroSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+  DEBUG ((DEBUG_INFO, "NanoSecDelay = %d\n", NanoSeconds));
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..2d4eb931e1 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -42,7 +42,7 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+#  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
@@ -56,6 +56,7 @@
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+  TimerLib|UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [LibraryClasses.common.SEC]
   PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -143,6 +144,7 @@
       SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   }
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-12  5:56 Donald Kuo
@ 2019-08-12 10:26 ` Zeng, Star
  0 siblings, 0 replies; 27+ messages in thread
From: Zeng, Star @ 2019-08-12 10:26 UTC (permalink / raw)
  To: Kuo, Donald, devel@edk2.groups.io; +Cc: Ni, Ray, Dong, Eric, Zeng, Star

Some comments below.

> -----Original Message-----
> From: Kuo, Donald
> Sent: Monday, August 12, 2019 1:57 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Dong, Eric
> <eric.dong@intel.com>
> Subject: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15)
> TSC leaf
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> 
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> ---
>  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
>  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
>  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  17 ++
>  UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 290
> +++++++++++++++++++++
>  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
>  UefiCpuPkg/UefiCpuPkg.dsc                          |   4 +-
>  6 files changed, 393 insertions(+), 1 deletion(-)  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
>  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
>  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> 


[Trimmed]


> +
> diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> new file mode 100644
> index 0000000000..5ed01146cf
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> @@ -0,0 +1,290 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DebugLib.h>
> +#include <Register/Cpuid.h>
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  );
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  )
> +{
> +  CPUID_VERSION_INFO_EAX Eax;
> +  UINT64                 TscFrequency;
> +  UINT64                 CoreXtalFrequency;
> +  UINT32                 RegEax;
> +  UINT32                 RegEbx;
> +  UINT32                 RegEcx;
> +
> +  //
> +  // Display CPU FAMILY / MODEL / STEPPING ID Info  //  AsmCpuid
> + (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);  DEBUG
> + ((DEBUG_INFO, "CPUID = %X\n", (Eax.Uint32 & 0x0FFF0FFF)));

Suggest removing this debugging code block.

> +
> +  //
> +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> + Clock Information  // EBX returns 0 if not supported. ECX, if non zero,
> provides Core Xtal Frequency in hertz.
> +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> +  //
> +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx,
> NULL);
> + DEBUG ((DEBUG_INFO, "Denominator of the TSC ratio = %d\n", RegEax));
> + DEBUG ((DEBUG_INFO, "Numerator of the TSC ratio = %d\n", RegEbx));
> + DEBUG ((DEBUG_INFO, "Nominal frequency (hertz) = %d\n", RegEcx));

Suggest removing this debug message codes as the timerlib may be used by AP.

> +
> +  //
> +  // If EBX returns 0, the XTAL ratio is not enumerated.
> +  //
> +  if (RegEbx == 0) {
> +    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock
> Frequency !!\n"));

Suggest removing this debug message codes as the timerlib may be used by AP.
Then the if condition can be also removed.

> +    ASSERT (RegEbx != 0);
> +  }
> +  //
> +  // If ECX returns 0, the XTAL frequency is not enumerated.
> +  //
> +  if (RegEcx == 0) {
> +    DEBUG ((DEBUG_ERROR, "The CPU is not capble for Core Crystal Clock
> Frequency !!\n"));

Suggest removing this debug message codes as the timerlib may be used by AP.

> +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> +    DEBUG ((DEBUG_INFO, "CoreXtalFrequency (hertz) from PCD = %d\n",
> CoreXtalFrequency));

Suggest removing this debug message codes as the timerlib may be used by AP.

> +    //ASSERT (RegEcx != 0);

Suggest removing this line

> +  } else {
> +    CoreXtalFrequency = (UINT64) RegEcx;  }
> +
> +  //
> +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX  //
> + TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) +
> + (UINT64)(RegEax >> 1), RegEax);
> +
> +  return TscFrequency;
> +}
> +

[Trimmed]

> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -42,7 +42,7 @@
>    PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
>    PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
> 
> PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanc
> eLibNull.inf
> -
> TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTem
> plate.inf
> +#
> +TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTe
> mpla
> +te.inf

Suggest removing this line.

Thanks,
Star

> 
> DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLi
> bNull.inf
> 
> LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.in
> f
> 
> ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseR
> eportStatusCodeLibNull.inf
> @@ -56,6 +56,7 @@
> 
> PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/Base
> PeCoffGetEntryPointLib.inf
> 
> PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BaseP
> eCoffExtraActionLibNull.inf
> 
> TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/Tp
> mMeasurementLibNull.inf
> +  TimerLib|UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> 
>  [LibraryClasses.common.SEC]
> 
> PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.i
> nf
> @@ -143,6 +144,7 @@
> 
> SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFea
> turesLibStm.inf
>    }
>    UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
> +  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> 
>  [BuildOptions]
>    *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
> --
> 2.14.2.windows.3


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-12 11:03 Donald Kuo
  0 siblings, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-12 11:03 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong, Amy Chan, Rangasai V Chaganty

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Amy Chan <amy.chan@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  16 ++
 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 274 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   1 +
 6 files changed, 374 insertions(+)
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c

diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..ccb92a95d3
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,40 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..7e27a55c90
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..6e5c3ef70e
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..965e206d7d
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,274 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX Eax;
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  if (RegEbx == 0) {
+    ASSERT (RegEbx != 0);
+  }
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..e1337c741b 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -143,6 +143,7 @@
       SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   }
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-12 11:23 Donald Kuo
  2019-08-13  2:26 ` Dong, Eric
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-12 11:23 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong, Amy Chan, Rangasai V Chaganty

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Amy Chan <amy.chan@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
 .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  16 ++
 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 272 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   1 +
 6 files changed, 372 insertions(+)
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c

diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..ccb92a95d3
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,40 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..7e27a55c90
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..6e5c3ef70e
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..39492acd8e
--- /dev/null
+++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,272 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX Eax;
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  ASSERT (RegEbx != 0);
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        CpuidCoreClockCalculateTscFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..e1337c741b 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -143,6 +143,7 @@
       SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
   }
   UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-12 11:23 Donald Kuo
@ 2019-08-13  2:26 ` Dong, Eric
  2019-08-13  3:26   ` Donald Kuo
  0 siblings, 1 reply; 27+ messages in thread
From: Dong, Eric @ 2019-08-13  2:26 UTC (permalink / raw)
  To: Kuo, Donald, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V

Hi Donald,

Do you think it's necessary to check the TIME_STAMP_COUNTER capability before using it? I see SDM has CPUID(0x01) which return the capability of TIME_STAMP_COUNTER.

Thanks,
Eric 

> -----Original Message-----
> From: Kuo, Donald
> Sent: Monday, August 12, 2019 7:23 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>; Chaganty,
> Rangasai V <rangasai.v.chaganty@intel.com>
> Subject: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15)
> TSC leaf
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> 
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Amy Chan <amy.chan@intel.com>
> Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> ---
>  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
>  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
>  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  16 ++
>  UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 272
> +++++++++++++++++++++
>  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
>  UefiCpuPkg/UefiCpuPkg.dsc                          |   1 +
>  6 files changed, 372 insertions(+)
>  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
>  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
>  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> 
> diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> new file mode 100644
> index 0000000000..ccb92a95d3
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> @@ -0,0 +1,40 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  return CpuidCoreClockCalculateTscFrequency (); }
> diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> new file mode 100644
> index 0000000000..7e27a55c90
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +#  Base CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = BaseCpuTimerLib
> +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = TimerLib
> +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  BaseCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> new file mode 100644
> index 0000000000..6e5c3ef70e
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> @@ -0,0 +1,16 @@
> +// /** @file
> +// Base CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> new file mode 100644
> index 0000000000..39492acd8e
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> @@ -0,0 +1,272 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DebugLib.h>
> +#include <Register/Cpuid.h>
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  );
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  )
> +{
> +  CPUID_VERSION_INFO_EAX Eax;
> +  UINT64                 TscFrequency;
> +  UINT64                 CoreXtalFrequency;
> +  UINT32                 RegEax;
> +  UINT32                 RegEbx;
> +  UINT32                 RegEcx;
> +
> +  //
> +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> + Clock Information  // EBX returns 0 if not supported. ECX, if non zero,
> provides Core Xtal Frequency in hertz.
> +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> +  //
> +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx,
> NULL);
> +
> +  //
> +  // If EBX returns 0, the XTAL ratio is not enumerated.
> +  //
> +  ASSERT (RegEbx != 0);
> +  //
> +  // If ECX returns 0, the XTAL frequency is not enumerated.
> +  //
> +  if (RegEcx == 0) {
> +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> +  } else {
> +    CoreXtalFrequency = (UINT64) RegEcx;  }
> +
> +  //
> +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX  //
> + TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) +
> + (UINT64)(RegEax >> 1), RegEax);
> +
> +  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  Delay     A period of time to delay in ticks.
> +
> +**/
> +VOID
> +InternalCpuDelay (
> +  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 guarantees a minimum of 10 years before the TSC wraps.
> +  //
> +  while (AsmReadTsc() <= Ticks) {
> +    CpuPause();
> +  }
> +}
> +
> +/**
> +  Stalls the CPU for at least the given number of microseconds.
> +
> +  Stalls the CPU for the number of microseconds specified by MicroSeconds.
> +
> +  @param[in]  MicroSeconds  The minimum number of microseconds to
> delay.
> +
> +  @return MicroSeconds
> +
> +**/
> +UINTN
> +EFIAPI
> +MicroSecondDelay (
> +  IN UINTN  MicroSeconds
> +  )
> +{
> +
> +  InternalCpuDelay (
> +    DivU64x32 (
> +      MultU64x64 (
> +        MicroSeconds,
> +        CpuidCoreClockCalculateTscFrequency ()
> +        ),
> +      1000000u
> +    )
> +  );
> +
> +  return MicroSeconds;
> +}
> +
> +/**
> +  Stalls the CPU for at least the given number of nanoseconds.
> +
> +  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
> +
> +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> +
> +  @return NanoSeconds
> +
> +**/
> +UINTN
> +EFIAPI
> +NanoSecondDelay (
> +  IN UINTN  NanoSeconds
> +  )
> +{
> +
> +  InternalCpuDelay (
> +    DivU64x32 (
> +      MultU64x64 (
> +        NanoSeconds,
> +        CpuidCoreClockCalculateTscFrequency ()
> +        ),
> +      1000000000u
> +    )
> +  );
> +
> +  return NanoSeconds;
> +}
> +
> +/**
> +  Retrieves the current value of a 64-bit free running performance counter.
> +
> +  Retrieves the current value of a 64-bit free running performance
> + counter. The  counter can either count up by 1 or count down by 1. If
> + the physical  performance counter counts by a larger increment, then
> + the counter values  must be translated. The properties of the counter
> + can be retrieved from  GetPerformanceCounterProperties().
> +
> +  @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 immediately after is it rolls over is returned in
> + StartValue. If  EndValue is not NULL, then the value that the
> + performance counter end with  immediately before it rolls over is
> + returned in EndValue. The 64-bit  frequency of the performance counter
> + in Hz is always returned. If StartValue  is less than EndValue, then
> + the performance counter counts up. If StartValue  is greater than
> + EndValue, then the performance counter counts down. For  example, a
> + 64-bit free running counter that counts up would have a StartValue  of
> + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
> that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
> +
> +  @param  StartValue  The value the performance counter starts with when
> it
> +                      rolls over.
> +  @param  EndValue    The value that the performance counter ends with
> before
> +                      it rolls over.
> +
> +  @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 InternalGetPerformanceCounterFrequency (); }
> +
> +/**
> +  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;
> +}
> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> index 14ddaa8633..a94bd2ea30 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dec
> +++ b/UefiCpuPkg/UefiCpuPkg.dec
> @@ -211,6 +211,14 @@
>    # @Prompt If CPU features will be initialized during S3 resume.
> 
> gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> LEAN|0x0000001D
> 
> +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core
> Crystal Clock Frequency.
> +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> 25000000 (25MHz)
> +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> Processor Family = 24000000 (24MHz)
> +  #   Intel Atom processors based on Goldmont Microarchitecture with
> CPUID signature 06_5CH = 19200000 (19.2MHz)
> +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
> +
> +
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> UIN
> + T64|0x32132113
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
>    ## Specifies max supported number of Logical Processors.
>    # @Prompt Configure max supported number of Logical Processors diff --git
> a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> bf690d3978..e1337c741b 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -143,6 +143,7 @@
> 
> SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFea
> turesLibStm.inf
>    }
>    UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
> +  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> 
>  [BuildOptions]
>    *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
> --
> 2.14.2.windows.3


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-13  2:26 ` Dong, Eric
@ 2019-08-13  3:26   ` Donald Kuo
  2019-08-13  5:45     ` Dong, Eric
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-13  3:26 UTC (permalink / raw)
  To: Dong, Eric, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V

Hi Eric,

The CPUID Leaf 0x1:EDX.TSC[bit 4] is to check capability for IA32_TIME_STAMP_COUNTER MSR and RDTSC instruction which defined in IA32 SDM chapter 17.17

And what we implement is based on IA32 SDM Chapter 18.7 for CPU core XTAL clock frequency which is from CPUID Leaf 0x15 and new TSC frequency = (ECX, Core XTAL Frequency) * EBX/EAX

So no need to check CPUID(0x01).

Thanks,
Donald

> -----Original Message-----
> From: Dong, Eric
> Sent: Tuesday, August 13, 2019 10:27 AM
> To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>
> Subject: RE: [PATCH] UefiCpuPkg: Adding a new TSC library by using
> CPUID(0x15) TSC leaf
> 
> Hi Donald,
> 
> Do you think it's necessary to check the TIME_STAMP_COUNTER capability
> before using it? I see SDM has CPUID(0x01) which return the capability of
> TIME_STAMP_COUNTER.
> 
> Thanks,
> Eric
> 
> > -----Original Message-----
> > From: Kuo, Donald
> > Sent: Monday, August 12, 2019 7:23 PM
> > To: devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > Dong, Eric <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
> > Subject: [PATCH] UefiCpuPkg: Adding a new TSC library by using
> > CPUID(0x15) TSC leaf
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> >
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Amy Chan <amy.chan@intel.com>
> > Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> > Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> > ---
> >  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
> >  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
> >  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  16 ++
> >  UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 272
> > +++++++++++++++++++++
> >  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
> >  UefiCpuPkg/UefiCpuPkg.dsc                          |   1 +
> >  6 files changed, 372 insertions(+)
> >  create mode 100644
> > UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> >  create mode 100644
> > UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> >  create mode 100644
> > UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> >  create mode 100644 UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> >
> > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > new file mode 100644
> > index 0000000000..ccb92a95d3
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > @@ -0,0 +1,40 @@
> > +/** @file
> > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer
> Library.
> > +
> > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Base.h>
> > +#include <Library/TimerLib.h>
> > +#include <Library/BaseLib.h>
> > +
> > +/**
> > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > +
> > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > + or 0 if
> > not supported.
> > +  @return The number of TSC counts per second.
> > +
> > +**/
> > +UINT64
> > +CpuidCoreClockCalculateTscFrequency (
> > +  VOID
> > +  );
> > +
> > +/**
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  @return The frequency in Hz.
> > +
> > +**/
> > +UINT64
> > +InternalGetPerformanceCounterFrequency (
> > +  VOID
> > +  )
> > +{
> > +  return CpuidCoreClockCalculateTscFrequency (); }
> > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > new file mode 100644
> > index 0000000000..7e27a55c90
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > @@ -0,0 +1,35 @@
> > +## @file
> > +#  Base CPU Timer Library
> > +#
> > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance #  counter features are provided by the processors
> > +time
> > stamp counter.
> > +#
> > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = BaseCpuTimerLib
> > +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = TimerLib
> > +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> > +
> > +[Sources]
> > +  CpuTimerLib.c
> > +  BaseCpuTimerLib.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  UefiCpuPkg/UefiCpuPkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  PcdLib
> > +  DebugLib
> > +
> > +[Pcd]
> > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > +CONSUMES
> > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > new file mode 100644
> > index 0000000000..6e5c3ef70e
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > @@ -0,0 +1,16 @@
> > +// /** @file
> > +// Base CPU Timer Library
> > +//
> > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance // counter features are provided by the processors
> > +time
> > stamp counter.
> > +//
> > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > Library"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> basic
> > timer support using CPUID Leaf 0x15 XTAL frequency."
> > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > new file mode 100644
> > index 0000000000..39492acd8e
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > @@ -0,0 +1,272 @@
> > +/** @file
> > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer
> Library.
> > +
> > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Base.h>
> > +#include <Library/TimerLib.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Register/Cpuid.h>
> > +
> > +/**
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  @return The frequency in Hz.
> > +
> > +**/
> > +UINT64
> > +InternalGetPerformanceCounterFrequency (
> > +  VOID
> > +  );
> > +
> > +/**
> > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > +
> > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > + or 0 if
> > not supported.
> > +  @return The number of TSC counts per second.
> > +
> > +**/
> > +UINT64
> > +CpuidCoreClockCalculateTscFrequency (
> > +  VOID
> > +  )
> > +{
> > +  CPUID_VERSION_INFO_EAX Eax;
> > +  UINT64                 TscFrequency;
> > +  UINT64                 CoreXtalFrequency;
> > +  UINT32                 RegEax;
> > +  UINT32                 RegEbx;
> > +  UINT32                 RegEcx;
> > +
> > +  //
> > +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> > + Clock Information  // EBX returns 0 if not supported. ECX, if non
> > + zero,
> > provides Core Xtal Frequency in hertz.
> > +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> > +  //
> > +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx,
> &RegEcx,
> > NULL);
> > +
> > +  //
> > +  // If EBX returns 0, the XTAL ratio is not enumerated.
> > +  //
> > +  ASSERT (RegEbx != 0);
> > +  //
> > +  // If ECX returns 0, the XTAL frequency is not enumerated.
> > +  //
> > +  if (RegEcx == 0) {
> > +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> > +  } else {
> > +    CoreXtalFrequency = (UINT64) RegEcx;  }
> > +
> > +  //
> > +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
> > + // TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx)
> > + + (UINT64)(RegEax >> 1), RegEax);
> > +
> > +  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  Delay     A period of time to delay in ticks.
> > +
> > +**/
> > +VOID
> > +InternalCpuDelay (
> > +  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 guarantees a minimum of 10 years before the TSC wraps.
> > +  //
> > +  while (AsmReadTsc() <= Ticks) {
> > +    CpuPause();
> > +  }
> > +}
> > +
> > +/**
> > +  Stalls the CPU for at least the given number of microseconds.
> > +
> > +  Stalls the CPU for the number of microseconds specified by
> MicroSeconds.
> > +
> > +  @param[in]  MicroSeconds  The minimum number of microseconds to
> > delay.
> > +
> > +  @return MicroSeconds
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +MicroSecondDelay (
> > +  IN UINTN  MicroSeconds
> > +  )
> > +{
> > +
> > +  InternalCpuDelay (
> > +    DivU64x32 (
> > +      MultU64x64 (
> > +        MicroSeconds,
> > +        CpuidCoreClockCalculateTscFrequency ()
> > +        ),
> > +      1000000u
> > +    )
> > +  );
> > +
> > +  return MicroSeconds;
> > +}
> > +
> > +/**
> > +  Stalls the CPU for at least the given number of nanoseconds.
> > +
> > +  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
> > +
> > +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> > +
> > +  @return NanoSeconds
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +NanoSecondDelay (
> > +  IN UINTN  NanoSeconds
> > +  )
> > +{
> > +
> > +  InternalCpuDelay (
> > +    DivU64x32 (
> > +      MultU64x64 (
> > +        NanoSeconds,
> > +        CpuidCoreClockCalculateTscFrequency ()
> > +        ),
> > +      1000000000u
> > +    )
> > +  );
> > +
> > +  return NanoSeconds;
> > +}
> > +
> > +/**
> > +  Retrieves the current value of a 64-bit free running performance counter.
> > +
> > +  Retrieves the current value of a 64-bit free running performance
> > + counter. The  counter can either count up by 1 or count down by 1.
> > + If the physical  performance counter counts by a larger increment,
> > + then the counter values  must be translated. The properties of the
> > + counter can be retrieved from  GetPerformanceCounterProperties().
> > +
> > +  @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 immediately after is it rolls over is returned
> > + in StartValue. If  EndValue is not NULL, then the value that the
> > + performance counter end with  immediately before it rolls over is
> > + returned in EndValue. The 64-bit  frequency of the performance
> > + counter in Hz is always returned. If StartValue  is less than
> > + EndValue, then the performance counter counts up. If StartValue  is
> > + greater than EndValue, then the performance counter counts down. For
> > + example, a 64-bit free running counter that counts up would have a
> > + StartValue  of
> > + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running
> > + counter
> > that counts down would have a StartValue of 0xFFFFFF and an EndValue of
> 0.
> > +
> > +  @param  StartValue  The value the performance counter starts with
> > + when
> > it
> > +                      rolls over.
> > +  @param  EndValue    The value that the performance counter ends with
> > before
> > +                      it rolls over.
> > +
> > +  @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
> > + InternalGetPerformanceCounterFrequency (); }
> > +
> > +/**
> > +  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;
> > +}
> > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> > index 14ddaa8633..a94bd2ea30 100644
> > --- a/UefiCpuPkg/UefiCpuPkg.dec
> > +++ b/UefiCpuPkg/UefiCpuPkg.dec
> > @@ -211,6 +211,14 @@
> >    # @Prompt If CPU features will be initialized during S3 resume.
> >
> > gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> > LEAN|0x0000001D
> >
> > +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core
> > Crystal Clock Frequency.
> > +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> > +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> > 25000000 (25MHz)
> > +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> > Processor Family = 24000000 (24MHz)
> > +  #   Intel Atom processors based on Goldmont Microarchitecture with
> > CPUID signature 06_5CH = 19200000 (19.2MHz)
> > +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
> > +
> > +
> >
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> > UIN
> > + T64|0x32132113
> > +
> >  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
> >    ## Specifies max supported number of Logical Processors.
> >    # @Prompt Configure max supported number of Logical Processors diff
> > --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> > bf690d3978..e1337c741b 100644
> > --- a/UefiCpuPkg/UefiCpuPkg.dsc
> > +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> > @@ -143,6 +143,7 @@
> >
> > SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFea
> > turesLibStm.inf
> >    }
> >    UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
> > +  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> >
> >  [BuildOptions]
> >    *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
> > --
> > 2.14.2.windows.3


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-13  3:26   ` Donald Kuo
@ 2019-08-13  5:45     ` Dong, Eric
  0 siblings, 0 replies; 27+ messages in thread
From: Dong, Eric @ 2019-08-13  5:45 UTC (permalink / raw)
  To: Kuo, Donald, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V

Hi Donald,

Thanks for your explanation.  In this case, Reviewed-by: Eric Dong <eric.dong@intel.com>

Thanks,
Eric
> -----Original Message-----
> From: Kuo, Donald
> Sent: Tuesday, August 13, 2019 11:26 AM
> To: Dong, Eric <eric.dong@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>
> Subject: RE: [PATCH] UefiCpuPkg: Adding a new TSC library by using
> CPUID(0x15) TSC leaf
> 
> Hi Eric,
> 
> The CPUID Leaf 0x1:EDX.TSC[bit 4] is to check capability for
> IA32_TIME_STAMP_COUNTER MSR and RDTSC instruction which defined in
> IA32 SDM chapter 17.17
> 
> And what we implement is based on IA32 SDM Chapter 18.7 for CPU core
> XTAL clock frequency which is from CPUID Leaf 0x15 and new TSC frequency
> = (ECX, Core XTAL Frequency) * EBX/EAX
> 
> So no need to check CPUID(0x01).
> 
> Thanks,
> Donald
> 
> > -----Original Message-----
> > From: Dong, Eric
> > Sent: Tuesday, August 13, 2019 10:27 AM
> > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>
> > Subject: RE: [PATCH] UefiCpuPkg: Adding a new TSC library by using
> > CPUID(0x15) TSC leaf
> >
> > Hi Donald,
> >
> > Do you think it's necessary to check the TIME_STAMP_COUNTER capability
> > before using it? I see SDM has CPUID(0x01) which return the capability
> > of TIME_STAMP_COUNTER.
> >
> > Thanks,
> > Eric
> >
> > > -----Original Message-----
> > > From: Kuo, Donald
> > > Sent: Monday, August 12, 2019 7:23 PM
> > > To: devel@edk2.groups.io
> > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > Dong, Eric <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > > Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
> > > Subject: [PATCH] UefiCpuPkg: Adding a new TSC library by using
> > > CPUID(0x15) TSC leaf
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > >
> > > Cc: Ray Ni <ray.ni@intel.com>
> > > Cc: Star Zeng <star.zeng@intel.com>
> > > Cc: Eric Dong <eric.dong@intel.com>
> > > Cc: Amy Chan <amy.chan@intel.com>
> > > Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> > > Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> > > ---
> > >  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.c      |  40 +++
> > >  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.inf    |  35 +++
> > >  .../Library/BaseCpuTimerLib/BaseCpuTimerLib.uni    |  16 ++
> > >  UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c   | 272
> > > +++++++++++++++++++++
> > >  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
> > >  UefiCpuPkg/UefiCpuPkg.dsc                          |   1 +
> > >  6 files changed, 372 insertions(+)
> > >  create mode 100644
> > > UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > >  create mode 100644
> > > UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > >  create mode 100644
> > > UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > >  create mode 100644
> UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > >
> > > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > > b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > > new file mode 100644
> > > index 0000000000..ccb92a95d3
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.c
> > > @@ -0,0 +1,40 @@
> > > +/** @file
> > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of
> > > +Timer
> > Library.
> > > +
> > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Base.h>
> > > +#include <Library/TimerLib.h>
> > > +#include <Library/BaseLib.h>
> > > +
> > > +/**
> > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > +
> > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > +  In newer flavors of the CPU, core xtal frequency is returned in
> > > + ECX or 0 if
> > > not supported.
> > > +  @return The number of TSC counts per second.
> > > +
> > > +**/
> > > +UINT64
> > > +CpuidCoreClockCalculateTscFrequency (
> > > +  VOID
> > > +  );
> > > +
> > > +/**
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  @return The frequency in Hz.
> > > +
> > > +**/
> > > +UINT64
> > > +InternalGetPerformanceCounterFrequency (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return CpuidCoreClockCalculateTscFrequency (); }
> > > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > > b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > > new file mode 100644
> > > index 0000000000..7e27a55c90
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > > @@ -0,0 +1,35 @@
> > > +## @file
> > > +#  Base CPU Timer Library
> > > +#
> > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance #  counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +#
> > > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > +#
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x00010005
> > > +  BASE_NAME                      = BaseCpuTimerLib
> > > +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> > > +  MODULE_TYPE                    = BASE
> > > +  VERSION_STRING                 = 1.0
> > > +  LIBRARY_CLASS                  = TimerLib
> > > +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> > > +
> > > +[Sources]
> > > +  CpuTimerLib.c
> > > +  BaseCpuTimerLib.c
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > +
> > > +[LibraryClasses]
> > > +  BaseLib
> > > +  PcdLib
> > > +  DebugLib
> > > +
> > > +[Pcd]
> > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > +CONSUMES
> > > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > > b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > > new file mode 100644
> > > index 0000000000..6e5c3ef70e
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.uni
> > > @@ -0,0 +1,16 @@
> > > +// /** @file
> > > +// Base CPU Timer Library
> > > +//
> > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance // counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +//
> > > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > +// // SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > +
> > > +
> > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > Library"
> > > +
> > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > basic
> > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > diff --git a/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > > b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > > new file mode 100644
> > > index 0000000000..39492acd8e
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/BaseCpuTimerLib/CpuTimerLib.c
> > > @@ -0,0 +1,272 @@
> > > +/** @file
> > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of
> > > +Timer
> > Library.
> > > +
> > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Base.h>
> > > +#include <Library/TimerLib.h>
> > > +#include <Library/BaseLib.h>
> > > +#include <Library/PcdLib.h>
> > > +#include <Library/DebugLib.h>
> > > +#include <Register/Cpuid.h>
> > > +
> > > +/**
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  @return The frequency in Hz.
> > > +
> > > +**/
> > > +UINT64
> > > +InternalGetPerformanceCounterFrequency (
> > > +  VOID
> > > +  );
> > > +
> > > +/**
> > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > +
> > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > +  In newer flavors of the CPU, core xtal frequency is returned in
> > > + ECX or 0 if
> > > not supported.
> > > +  @return The number of TSC counts per second.
> > > +
> > > +**/
> > > +UINT64
> > > +CpuidCoreClockCalculateTscFrequency (
> > > +  VOID
> > > +  )
> > > +{
> > > +  CPUID_VERSION_INFO_EAX Eax;
> > > +  UINT64                 TscFrequency;
> > > +  UINT64                 CoreXtalFrequency;
> > > +  UINT32                 RegEax;
> > > +  UINT32                 RegEbx;
> > > +  UINT32                 RegEcx;
> > > +
> > > +  //
> > > +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core
> > > + Crystal Clock Information  // EBX returns 0 if not supported. ECX,
> > > + if non zero,
> > > provides Core Xtal Frequency in hertz.
> > > +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> > > +  //
> > > +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx,
> > &RegEcx,
> > > NULL);
> > > +
> > > +  //
> > > +  // If EBX returns 0, the XTAL ratio is not enumerated.
> > > +  //
> > > +  ASSERT (RegEbx != 0);
> > > +  //
> > > +  // If ECX returns 0, the XTAL frequency is not enumerated.
> > > +  //
> > > +  if (RegEcx == 0) {
> > > +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> > > +  } else {
> > > +    CoreXtalFrequency = (UINT64) RegEcx;  }
> > > +
> > > +  //
> > > +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
> > > + // TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency,
> > > + RegEbx)
> > > + + (UINT64)(RegEax >> 1), RegEax);
> > > +
> > > +  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  Delay     A period of time to delay in ticks.
> > > +
> > > +**/
> > > +VOID
> > > +InternalCpuDelay (
> > > +  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 guarantees a minimum of 10 years before the TSC wraps.
> > > +  //
> > > +  while (AsmReadTsc() <= Ticks) {
> > > +    CpuPause();
> > > +  }
> > > +}
> > > +
> > > +/**
> > > +  Stalls the CPU for at least the given number of microseconds.
> > > +
> > > +  Stalls the CPU for the number of microseconds specified by
> > MicroSeconds.
> > > +
> > > +  @param[in]  MicroSeconds  The minimum number of microseconds to
> > > delay.
> > > +
> > > +  @return MicroSeconds
> > > +
> > > +**/
> > > +UINTN
> > > +EFIAPI
> > > +MicroSecondDelay (
> > > +  IN UINTN  MicroSeconds
> > > +  )
> > > +{
> > > +
> > > +  InternalCpuDelay (
> > > +    DivU64x32 (
> > > +      MultU64x64 (
> > > +        MicroSeconds,
> > > +        CpuidCoreClockCalculateTscFrequency ()
> > > +        ),
> > > +      1000000u
> > > +    )
> > > +  );
> > > +
> > > +  return MicroSeconds;
> > > +}
> > > +
> > > +/**
> > > +  Stalls the CPU for at least the given number of nanoseconds.
> > > +
> > > +  Stalls the CPU for the number of nanoseconds specified by
> NanoSeconds.
> > > +
> > > +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> > > +
> > > +  @return NanoSeconds
> > > +
> > > +**/
> > > +UINTN
> > > +EFIAPI
> > > +NanoSecondDelay (
> > > +  IN UINTN  NanoSeconds
> > > +  )
> > > +{
> > > +
> > > +  InternalCpuDelay (
> > > +    DivU64x32 (
> > > +      MultU64x64 (
> > > +        NanoSeconds,
> > > +        CpuidCoreClockCalculateTscFrequency ()
> > > +        ),
> > > +      1000000000u
> > > +    )
> > > +  );
> > > +
> > > +  return NanoSeconds;
> > > +}
> > > +
> > > +/**
> > > +  Retrieves the current value of a 64-bit free running performance
> counter.
> > > +
> > > +  Retrieves the current value of a 64-bit free running performance
> > > + counter. The  counter can either count up by 1 or count down by 1.
> > > + If the physical  performance counter counts by a larger increment,
> > > + then the counter values  must be translated. The properties of the
> > > + counter can be retrieved from  GetPerformanceCounterProperties().
> > > +
> > > +  @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 immediately after is it rolls over is
> > > + returned in StartValue. If  EndValue is not NULL, then the value
> > > + that the performance counter end with  immediately before it rolls
> > > + over is returned in EndValue. The 64-bit  frequency of the
> > > + performance counter in Hz is always returned. If StartValue  is
> > > + less than EndValue, then the performance counter counts up. If
> > > + StartValue  is greater than EndValue, then the performance counter
> > > + counts down. For example, a 64-bit free running counter that
> > > + counts up would have a StartValue  of
> > > + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running
> > > + counter
> > > that counts down would have a StartValue of 0xFFFFFF and an EndValue
> > > of
> > 0.
> > > +
> > > +  @param  StartValue  The value the performance counter starts with
> > > + when
> > > it
> > > +                      rolls over.
> > > +  @param  EndValue    The value that the performance counter ends
> with
> > > before
> > > +                      it rolls over.
> > > +
> > > +  @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
> > > + InternalGetPerformanceCounterFrequency (); }
> > > +
> > > +/**
> > > +  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;
> > > +}
> > > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> > > index 14ddaa8633..a94bd2ea30 100644
> > > --- a/UefiCpuPkg/UefiCpuPkg.dec
> > > +++ b/UefiCpuPkg/UefiCpuPkg.dec
> > > @@ -211,6 +211,14 @@
> > >    # @Prompt If CPU features will be initialized during S3 resume.
> > >
> > >
> gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> > > LEAN|0x0000001D
> > >
> > > +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core
> > > Crystal Clock Frequency.
> > > +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> > > +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> > > 25000000 (25MHz)
> > > +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> > > Processor Family = 24000000 (24MHz)
> > > +  #   Intel Atom processors based on Goldmont Microarchitecture with
> > > CPUID signature 06_5CH = 19200000 (19.2MHz)
> > > +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
> > > +
> > > +
> > >
> >
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> > > UIN
> > > + T64|0x32132113
> > > +
> > >  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic,
> PcdsDynamicEx]
> > >    ## Specifies max supported number of Logical Processors.
> > >    # @Prompt Configure max supported number of Logical Processors
> > > diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
> > > index bf690d3978..e1337c741b 100644
> > > --- a/UefiCpuPkg/UefiCpuPkg.dsc
> > > +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> > > @@ -143,6 +143,7 @@
> > >
> > >
> SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFea
> > > turesLibStm.inf
> > >    }
> > >    UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
> > > +  UefiCpuPkg/Library/BaseCpuTimerLib/BaseCpuTimerLib.inf
> > >
> > >  [BuildOptions]
> > >    *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
> > > --
> > > 2.14.2.windows.3


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-13 10:53 Donald Kuo
  2019-08-15  2:45 ` [edk2-devel] " Dong, Eric
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-13 10:53 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong, Amy Chan, Rangasai V Chaganty

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Amy Chan <amy.chan@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274 +++++++++++++++++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
 12 files changed, 624 insertions(+)
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni

diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..6ddf917bad
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,41 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..fd93adc5f1
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..0b9e9384f5
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,274 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, { 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  ASSERT (RegEbx != 0);
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
new file mode 100644
index 0000000000..2d0ef6ab07
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
@@ -0,0 +1,81 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+//
+// Cached CPU Crystal counter frequency
+//
+UINT64  mCpuCrystalCounterFrequency = 0;
+
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return mCpuCrystalCounterFrequency;
+}
+
+/**
+  The constructor function is to initialize CpuCrystalCounterFrequency.
+
+  @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 RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeCpuTimerLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  //
+  // Initialize CpuCrystalCounterFrequency
+  //
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob != NULL) {
+    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
new file mode 100644
index 0000000000..6c83549c87
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
@@ -0,0 +1,37 @@
+## @file
+#  DXE CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeCpuTimerLib
+  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
+  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                    = DxeCpuTimerLibConstructor
+  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  DxeCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
new file mode 100644
index 0000000000..f55b92abac
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// DXE CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
new file mode 100644
index 0000000000..91a7212056
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
@@ -0,0 +1,58 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  UINT64              *CpuCrystalCounterFrequency;
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  CpuCrystalCounterFrequency = NULL;
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob == NULL) {
+    CpuCrystalCounterFrequency  = (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof (*CpuCrystalCounterFrequency));
+    ASSERT (CpuCrystalCounterFrequency != NULL);
+    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  } else {
+    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  }
+
+  return  *CpuCrystalCounterFrequency;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
new file mode 100644
index 0000000000..7af0fc44a6
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  PEI CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiCpuTimerLib
+  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
+  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  PeiCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
new file mode 100644
index 0000000000..49beb44908
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// PEI CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..a94bd2ea30 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..e7dfe30eda 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -101,6 +101,9 @@
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf
   UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
   UefiCpuPkg/Application/Cpuid/Cpuid.inf
+  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 
 [Components.IA32, Components.X64]
   UefiCpuPkg/CpuDxe/CpuDxe.inf
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-13 10:53 [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf Donald Kuo
@ 2019-08-15  2:45 ` Dong, Eric
  2019-08-15  3:02   ` Donald Kuo
  0 siblings, 1 reply; 27+ messages in thread
From: Dong, Eric @ 2019-08-15  2:45 UTC (permalink / raw)
  To: devel@edk2.groups.io, Kuo, Donald
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V

Reviewed-by: Eric Dong <eric.dong@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Donald Kuo
> Sent: Tuesday, August 13, 2019 6:53 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>; Chaganty,
> Rangasai V <rangasai.v.chaganty@intel.com>
> Subject: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using
> CPUID(0x15) TSC leaf
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> 
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Amy Chan <amy.chan@intel.com>
> Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> ---
>  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
>  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
> UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
>  UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274
> +++++++++++++++++++++
>  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
>  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
> UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
>  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
>  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
> UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
>  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
>  UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
>  12 files changed, 624 insertions(+)
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> 
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> new file mode 100644
> index 0000000000..6ddf917bad
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> @@ -0,0 +1,41 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer
> Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  return CpuidCoreClockCalculateTscFrequency (); }
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> new file mode 100644
> index 0000000000..fd93adc5f1
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +#  Base CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = BaseCpuTimerLib
> +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
> +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  BaseCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> new file mode 100644
> index 0000000000..fcf2b0fbcb
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> @@ -0,0 +1,17 @@
> +// /** @file
> +// Base CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> new file mode 100644
> index 0000000000..0b9e9384f5
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> @@ -0,0 +1,274 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DebugLib.h>
> +#include <Register/Cpuid.h>
> +
> +GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, {
> +0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  );
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  )
> +{
> +  UINT64                 TscFrequency;
> +  UINT64                 CoreXtalFrequency;
> +  UINT32                 RegEax;
> +  UINT32                 RegEbx;
> +  UINT32                 RegEcx;
> +
> +  //
> +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> + Clock Information  // EBX returns 0 if not supported. ECX, if non zero,
> provides Core Xtal Frequency in hertz.
> +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> +  //
> +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx,
> NULL);
> +
> +  //
> +  // If EBX returns 0, the XTAL ratio is not enumerated.
> +  //
> +  ASSERT (RegEbx != 0);
> +  //
> +  // If ECX returns 0, the XTAL frequency is not enumerated.
> +  //
> +  if (RegEcx == 0) {
> +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> +  } else {
> +    CoreXtalFrequency = (UINT64) RegEcx;  }
> +
> +  //
> +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX  //
> + TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) +
> + (UINT64)(RegEax >> 1), RegEax);
> +
> +  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  Delay     A period of time to delay in ticks.
> +
> +**/
> +VOID
> +InternalCpuDelay (
> +  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 guarantees a minimum of 10 years before the TSC wraps.
> +  //
> +  while (AsmReadTsc() <= Ticks) {
> +    CpuPause();
> +  }
> +}
> +
> +/**
> +  Stalls the CPU for at least the given number of microseconds.
> +
> +  Stalls the CPU for the number of microseconds specified by MicroSeconds.
> +
> +  @param[in]  MicroSeconds  The minimum number of microseconds to
> delay.
> +
> +  @return MicroSeconds
> +
> +**/
> +UINTN
> +EFIAPI
> +MicroSecondDelay (
> +  IN UINTN  MicroSeconds
> +  )
> +{
> +
> +  InternalCpuDelay (
> +    DivU64x32 (
> +      MultU64x64 (
> +        MicroSeconds,
> +        InternalGetPerformanceCounterFrequency ()
> +        ),
> +      1000000u
> +    )
> +  );
> +
> +  return MicroSeconds;
> +}
> +
> +/**
> +  Stalls the CPU for at least the given number of nanoseconds.
> +
> +  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
> +
> +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> +
> +  @return NanoSeconds
> +
> +**/
> +UINTN
> +EFIAPI
> +NanoSecondDelay (
> +  IN UINTN  NanoSeconds
> +  )
> +{
> +
> +  InternalCpuDelay (
> +    DivU64x32 (
> +      MultU64x64 (
> +        NanoSeconds,
> +        InternalGetPerformanceCounterFrequency ()
> +        ),
> +      1000000000u
> +    )
> +  );
> +
> +  return NanoSeconds;
> +}
> +
> +/**
> +  Retrieves the current value of a 64-bit free running performance counter.
> +
> +  Retrieves the current value of a 64-bit free running performance
> + counter. The  counter can either count up by 1 or count down by 1. If
> + the physical  performance counter counts by a larger increment, then
> + the counter values  must be translated. The properties of the counter
> + can be retrieved from  GetPerformanceCounterProperties().
> +
> +  @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 immediately after is it rolls over is returned in
> + StartValue. If  EndValue is not NULL, then the value that the
> + performance counter end with  immediately before it rolls over is
> + returned in EndValue. The 64-bit  frequency of the performance counter
> + in Hz is always returned. If StartValue  is less than EndValue, then
> + the performance counter counts up. If StartValue  is greater than
> + EndValue, then the performance counter counts down. For  example, a
> + 64-bit free running counter that counts up would have a StartValue  of
> + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
> that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
> +
> +  @param  StartValue  The value the performance counter starts with when
> it
> +                      rolls over.
> +  @param  EndValue    The value that the performance counter ends with
> before
> +                      it rolls over.
> +
> +  @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 InternalGetPerformanceCounterFrequency (); }
> +
> +/**
> +  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;
> +}
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> new file mode 100644
> index 0000000000..2d0ef6ab07
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> @@ -0,0 +1,81 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/HobLib.h>
> +
> +extern GUID mCpuCrystalFrequencyHobGuid;
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +//
> +// Cached CPU Crystal counter frequency //
> +UINT64  mCpuCrystalCounterFrequency = 0;
> +
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  return mCpuCrystalCounterFrequency;
> +}
> +
> +/**
> +  The constructor function is to initialize CpuCrystalCounterFrequency.
> +
> +  @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 RETURN_SUCCESS.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DxeCpuTimerLibConstructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_HOB_GUID_TYPE   *GuidHob;
> +
> +  //
> +  // Initialize CpuCrystalCounterFrequency  //  GuidHob =
> + GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if (GuidHob != NULL)
> + {
> +    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA
> + (GuidHob);  } else {
> +    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency
> + ();  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> new file mode 100644
> index 0000000000..6c83549c87
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +#  DXE CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = DxeCpuTimerLib
> +  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
> +  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                    = DxeCpuTimerLibConstructor
> +  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  DxeCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +  HobLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> new file mode 100644
> index 0000000000..f55b92abac
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> @@ -0,0 +1,17 @@
> +// /** @file
> +// DXE CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> new file mode 100644
> index 0000000000..91a7212056
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> @@ -0,0 +1,58 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer
> Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiPei.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/DebugLib.h>
> +
> +extern GUID mCpuCrystalFrequencyHobGuid;
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if
> not supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  UINT64              *CpuCrystalCounterFrequency;
> +  EFI_HOB_GUID_TYPE   *GuidHob;
> +
> +  CpuCrystalCounterFrequency = NULL;
> +  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if
> + (GuidHob == NULL) {
> +    CpuCrystalCounterFrequency  =
> (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof
> (*CpuCrystalCounterFrequency));
> +    ASSERT (CpuCrystalCounterFrequency != NULL);
> +    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency
> + ();  } else {
> +    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA
> (GuidHob);
> + }
> +
> +  return  *CpuCrystalCounterFrequency;
> +}
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> new file mode 100644
> index 0000000000..7af0fc44a6
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> @@ -0,0 +1,36 @@
> +## @file
> +#  PEI CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PeiCpuTimerLib
> +  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
> +  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  PeiCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +  HobLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> new file mode 100644
> index 0000000000..49beb44908
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> @@ -0,0 +1,17 @@
> +// /** @file
> +// PEI CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> +
> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> index 14ddaa8633..a94bd2ea30 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dec
> +++ b/UefiCpuPkg/UefiCpuPkg.dec
> @@ -211,6 +211,14 @@
>    # @Prompt If CPU features will be initialized during S3 resume.
> 
> gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> LEAN|0x0000001D
> 
> +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core
> Crystal Clock Frequency.
> +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> 25000000 (25MHz)
> +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> Processor Family = 24000000 (24MHz)
> +  #   Intel Atom processors based on Goldmont Microarchitecture with
> CPUID signature 06_5CH = 19200000 (19.2MHz)
> +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
> +
> +
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> UIN
> + T64|0x32132113
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
>    ## Specifies max supported number of Logical Processors.
>    # @Prompt Configure max supported number of Logical Processors diff --git
> a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> bf690d3978..e7dfe30eda 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -101,6 +101,9 @@
>    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
> 
> UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.i
> nf
>    UefiCpuPkg/Application/Cpuid/Cpuid.inf
> +  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> +  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> +  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> 
>  [Components.IA32, Components.X64]
>    UefiCpuPkg/CpuDxe/CpuDxe.inf
> --
> 2.14.2.windows.3
> 
> 
> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-15  2:45 ` [edk2-devel] " Dong, Eric
@ 2019-08-15  3:02   ` Donald Kuo
  2019-08-15  4:02     ` Liming Gao
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-15  3:02 UTC (permalink / raw)
  To: Dong, Eric, devel@edk2.groups.io, Gao, Liming
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y

Hi Liming,

As we plan to add new TimerLib to use CPUID Leaf 0x15 (CPU XTAL clock frequency) to calculate TSC to resolve performance value unreliable concern.

As the code review had got approved and planning into 201908 stable tag. Please help to review whether any concern for 201908 stable tag.

Thanks,
Donald

> -----Original Message-----
> From: Dong, Eric
> Sent: Thursday, August 15, 2019 10:46 AM
> To: devel@edk2.groups.io; Kuo, Donald <donald.kuo@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> using CPUID(0x15) TSC leaf
> 
> Reviewed-by: Eric Dong <eric.dong@intel.com>
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > Donald Kuo
> > Sent: Tuesday, August 13, 2019 6:53 PM
> > To: devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > Dong, Eric <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
> > Subject: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> > using
> > CPUID(0x15) TSC leaf
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> >
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Amy Chan <amy.chan@intel.com>
> > Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> > Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> > ---
> >  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
> >  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
> > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
> >  UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274
> > +++++++++++++++++++++
> >  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
> >  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
> > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
> >  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
> >  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
> > UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
> >  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
> >  UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
> >  12 files changed, 624 insertions(+)
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> >  create mode 100644
> UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> >  create mode 100644
> UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> >  create mode 100644
> UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> >
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > new file mode 100644
> > index 0000000000..6ddf917bad
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > @@ -0,0 +1,41 @@
> > +/** @file
> > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base
> > +Timer
> > Library.
> > +
> > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Base.h>
> > +#include <Library/TimerLib.h>
> > +#include <Library/BaseLib.h>
> > +
> > +/**
> > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > +
> > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > + or 0 if
> > not supported.
> > +  @return The number of TSC counts per second.
> > +
> > +**/
> > +UINT64
> > +CpuidCoreClockCalculateTscFrequency (
> > +  VOID
> > +  );
> > +
> > +/**
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  @return The frequency in Hz.
> > +
> > +**/
> > +UINT64
> > +InternalGetPerformanceCounterFrequency (
> > +  VOID
> > +  )
> > +{
> > +  return CpuidCoreClockCalculateTscFrequency (); }
> > +
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > new file mode 100644
> > index 0000000000..fd93adc5f1
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > @@ -0,0 +1,35 @@
> > +## @file
> > +#  Base CPU Timer Library
> > +#
> > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance #  counter features are provided by the processors
> > +time
> > stamp counter.
> > +#
> > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = BaseCpuTimerLib
> > +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
> > +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> > +
> > +[Sources]
> > +  CpuTimerLib.c
> > +  BaseCpuTimerLib.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  UefiCpuPkg/UefiCpuPkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  PcdLib
> > +  DebugLib
> > +
> > +[Pcd]
> > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > +CONSUMES
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > new file mode 100644
> > index 0000000000..fcf2b0fbcb
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > @@ -0,0 +1,17 @@
> > +// /** @file
> > +// Base CPU Timer Library
> > +//
> > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance // counter features are provided by the processors
> > +time
> > stamp counter.
> > +//
> > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > Library"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> basic
> > timer support using CPUID Leaf 0x15 XTAL frequency."
> > +
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > new file mode 100644
> > index 0000000000..0b9e9384f5
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > @@ -0,0 +1,274 @@
> > +/** @file
> > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer
> Library.
> > +
> > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Base.h>
> > +#include <Library/TimerLib.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Register/Cpuid.h>
> > +
> > +GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, {
> > +0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
> > +
> > +/**
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  @return The frequency in Hz.
> > +
> > +**/
> > +UINT64
> > +InternalGetPerformanceCounterFrequency (
> > +  VOID
> > +  );
> > +
> > +/**
> > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > +
> > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > + or 0 if
> > not supported.
> > +  @return The number of TSC counts per second.
> > +
> > +**/
> > +UINT64
> > +CpuidCoreClockCalculateTscFrequency (
> > +  VOID
> > +  )
> > +{
> > +  UINT64                 TscFrequency;
> > +  UINT64                 CoreXtalFrequency;
> > +  UINT32                 RegEax;
> > +  UINT32                 RegEbx;
> > +  UINT32                 RegEcx;
> > +
> > +  //
> > +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> > + Clock Information  // EBX returns 0 if not supported. ECX, if non
> > + zero,
> > provides Core Xtal Frequency in hertz.
> > +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> > +  //
> > +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx,
> &RegEcx,
> > NULL);
> > +
> > +  //
> > +  // If EBX returns 0, the XTAL ratio is not enumerated.
> > +  //
> > +  ASSERT (RegEbx != 0);
> > +  //
> > +  // If ECX returns 0, the XTAL frequency is not enumerated.
> > +  //
> > +  if (RegEcx == 0) {
> > +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> > +  } else {
> > +    CoreXtalFrequency = (UINT64) RegEcx;  }
> > +
> > +  //
> > +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
> > + // TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx)
> > + + (UINT64)(RegEax >> 1), RegEax);
> > +
> > +  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  Delay     A period of time to delay in ticks.
> > +
> > +**/
> > +VOID
> > +InternalCpuDelay (
> > +  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 guarantees a minimum of 10 years before the TSC wraps.
> > +  //
> > +  while (AsmReadTsc() <= Ticks) {
> > +    CpuPause();
> > +  }
> > +}
> > +
> > +/**
> > +  Stalls the CPU for at least the given number of microseconds.
> > +
> > +  Stalls the CPU for the number of microseconds specified by
> MicroSeconds.
> > +
> > +  @param[in]  MicroSeconds  The minimum number of microseconds to
> > delay.
> > +
> > +  @return MicroSeconds
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +MicroSecondDelay (
> > +  IN UINTN  MicroSeconds
> > +  )
> > +{
> > +
> > +  InternalCpuDelay (
> > +    DivU64x32 (
> > +      MultU64x64 (
> > +        MicroSeconds,
> > +        InternalGetPerformanceCounterFrequency ()
> > +        ),
> > +      1000000u
> > +    )
> > +  );
> > +
> > +  return MicroSeconds;
> > +}
> > +
> > +/**
> > +  Stalls the CPU for at least the given number of nanoseconds.
> > +
> > +  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
> > +
> > +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> > +
> > +  @return NanoSeconds
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +NanoSecondDelay (
> > +  IN UINTN  NanoSeconds
> > +  )
> > +{
> > +
> > +  InternalCpuDelay (
> > +    DivU64x32 (
> > +      MultU64x64 (
> > +        NanoSeconds,
> > +        InternalGetPerformanceCounterFrequency ()
> > +        ),
> > +      1000000000u
> > +    )
> > +  );
> > +
> > +  return NanoSeconds;
> > +}
> > +
> > +/**
> > +  Retrieves the current value of a 64-bit free running performance counter.
> > +
> > +  Retrieves the current value of a 64-bit free running performance
> > + counter. The  counter can either count up by 1 or count down by 1.
> > + If the physical  performance counter counts by a larger increment,
> > + then the counter values  must be translated. The properties of the
> > + counter can be retrieved from  GetPerformanceCounterProperties().
> > +
> > +  @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 immediately after is it rolls over is returned
> > + in StartValue. If  EndValue is not NULL, then the value that the
> > + performance counter end with  immediately before it rolls over is
> > + returned in EndValue. The 64-bit  frequency of the performance
> > + counter in Hz is always returned. If StartValue  is less than
> > + EndValue, then the performance counter counts up. If StartValue  is
> > + greater than EndValue, then the performance counter counts down. For
> > + example, a 64-bit free running counter that counts up would have a
> > + StartValue  of
> > + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running
> > + counter
> > that counts down would have a StartValue of 0xFFFFFF and an EndValue of
> 0.
> > +
> > +  @param  StartValue  The value the performance counter starts with
> > + when
> > it
> > +                      rolls over.
> > +  @param  EndValue    The value that the performance counter ends with
> > before
> > +                      it rolls over.
> > +
> > +  @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
> > + InternalGetPerformanceCounterFrequency (); }
> > +
> > +/**
> > +  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;
> > +}
> > +
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > new file mode 100644
> > index 0000000000..2d0ef6ab07
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > @@ -0,0 +1,81 @@
> > +/** @file
> > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer
> Library.
> > +
> > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <PiDxe.h>
> > +#include <Library/TimerLib.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/HobLib.h>
> > +
> > +extern GUID mCpuCrystalFrequencyHobGuid;
> > +
> > +/**
> > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > +
> > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > + or 0 if
> > not supported.
> > +  @return The number of TSC counts per second.
> > +
> > +**/
> > +UINT64
> > +CpuidCoreClockCalculateTscFrequency (
> > +  VOID
> > +  );
> > +
> > +//
> > +// Cached CPU Crystal counter frequency //
> > +UINT64  mCpuCrystalCounterFrequency = 0;
> > +
> > +
> > +/**
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  @return The frequency in Hz.
> > +
> > +**/
> > +UINT64
> > +InternalGetPerformanceCounterFrequency (
> > +  VOID
> > +  )
> > +{
> > +  return mCpuCrystalCounterFrequency; }
> > +
> > +/**
> > +  The constructor function is to initialize CpuCrystalCounterFrequency.
> > +
> > +  @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
> RETURN_SUCCESS.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +DxeCpuTimerLibConstructor (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  EFI_HOB_GUID_TYPE   *GuidHob;
> > +
> > +  //
> > +  // Initialize CpuCrystalCounterFrequency  //  GuidHob =
> > + GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if (GuidHob !=
> > + NULL) {
> > +    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA
> > + (GuidHob);  } else {
> > +    mCpuCrystalCounterFrequency =
> CpuidCoreClockCalculateTscFrequency
> > + ();  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > new file mode 100644
> > index 0000000000..6c83549c87
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > @@ -0,0 +1,37 @@
> > +## @file
> > +#  DXE CPU Timer Library
> > +#
> > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance #  counter features are provided by the processors
> > +time
> > stamp counter.
> > +#
> > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = DxeCpuTimerLib
> > +  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
> > +  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                    = DxeCpuTimerLibConstructor
> > +  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
> > +
> > +[Sources]
> > +  CpuTimerLib.c
> > +  DxeCpuTimerLib.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  UefiCpuPkg/UefiCpuPkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  PcdLib
> > +  DebugLib
> > +  HobLib
> > +
> > +[Pcd]
> > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > +CONSUMES
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > new file mode 100644
> > index 0000000000..f55b92abac
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > @@ -0,0 +1,17 @@
> > +// /** @file
> > +// DXE CPU Timer Library
> > +//
> > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance // counter features are provided by the processors
> > +time
> > stamp counter.
> > +//
> > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > Library"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> basic
> > timer support using CPUID Leaf 0x15 XTAL frequency."
> > +
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > new file mode 100644
> > index 0000000000..91a7212056
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > @@ -0,0 +1,58 @@
> > +/** @file
> > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI
> > +Timer
> > Library.
> > +
> > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <PiPei.h>
> > +#include <Library/TimerLib.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/HobLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +extern GUID mCpuCrystalFrequencyHobGuid;
> > +
> > +/**
> > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > +
> > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > + or 0 if
> > not supported.
> > +  @return The number of TSC counts per second.
> > +
> > +**/
> > +UINT64
> > +CpuidCoreClockCalculateTscFrequency (
> > +  VOID
> > +  );
> > +
> > +/**
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  Internal function to retrieves the 64-bit frequency in Hz.
> > +
> > +  @return The frequency in Hz.
> > +
> > +**/
> > +UINT64
> > +InternalGetPerformanceCounterFrequency (
> > +  VOID
> > +  )
> > +{
> > +  UINT64              *CpuCrystalCounterFrequency;
> > +  EFI_HOB_GUID_TYPE   *GuidHob;
> > +
> > +  CpuCrystalCounterFrequency = NULL;
> > +  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if
> > + (GuidHob == NULL) {
> > +    CpuCrystalCounterFrequency  =
> > (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof
> > (*CpuCrystalCounterFrequency));
> > +    ASSERT (CpuCrystalCounterFrequency != NULL);
> > +    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency
> > + ();  } else {
> > +    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA
> > (GuidHob);
> > + }
> > +
> > +  return  *CpuCrystalCounterFrequency; }
> > +
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > new file mode 100644
> > index 0000000000..7af0fc44a6
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > @@ -0,0 +1,36 @@
> > +## @file
> > +#  PEI CPU Timer Library
> > +#
> > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance #  counter features are provided by the processors
> > +time
> > stamp counter.
> > +#
> > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = PeiCpuTimerLib
> > +  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
> > +  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
> > +
> > +[Sources]
> > +  CpuTimerLib.c
> > +  PeiCpuTimerLib.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  UefiCpuPkg/UefiCpuPkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  PcdLib
> > +  DebugLib
> > +  HobLib
> > +
> > +[Pcd]
> > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > +CONSUMES
> > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > new file mode 100644
> > index 0000000000..49beb44908
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > @@ -0,0 +1,17 @@
> > +// /** @file
> > +// PEI CPU Timer Library
> > +//
> > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > +The performance // counter features are provided by the processors
> > +time
> > stamp counter.
> > +//
> > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > Library"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> basic
> > timer support using CPUID Leaf 0x15 XTAL frequency."
> > +
> > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> > index 14ddaa8633..a94bd2ea30 100644
> > --- a/UefiCpuPkg/UefiCpuPkg.dec
> > +++ b/UefiCpuPkg/UefiCpuPkg.dec
> > @@ -211,6 +211,14 @@
> >    # @Prompt If CPU features will be initialized during S3 resume.
> >
> > gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> > LEAN|0x0000001D
> >
> > +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core
> > Crystal Clock Frequency.
> > +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> > +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> > 25000000 (25MHz)
> > +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> > Processor Family = 24000000 (24MHz)
> > +  #   Intel Atom processors based on Goldmont Microarchitecture with
> > CPUID signature 06_5CH = 19200000 (19.2MHz)
> > +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
> > +
> > +
> >
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> > UIN
> > + T64|0x32132113
> > +
> >  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
> >    ## Specifies max supported number of Logical Processors.
> >    # @Prompt Configure max supported number of Logical Processors diff
> > --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> > bf690d3978..e7dfe30eda 100644
> > --- a/UefiCpuPkg/UefiCpuPkg.dsc
> > +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> > @@ -101,6 +101,9 @@
> >    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
> >
> >
> UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.i
> > nf
> >    UefiCpuPkg/Application/Cpuid/Cpuid.inf
> > +  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > +  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > +  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> >
> >  [Components.IA32, Components.X64]
> >    UefiCpuPkg/CpuDxe/CpuDxe.inf
> > --
> > 2.14.2.windows.3
> >
> >
> > 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-15  3:02   ` Donald Kuo
@ 2019-08-15  4:02     ` Liming Gao
  2019-08-15  4:40       ` Donald Kuo
  2019-08-16 16:16       ` Laszlo Ersek
  0 siblings, 2 replies; 27+ messages in thread
From: Liming Gao @ 2019-08-15  4:02 UTC (permalink / raw)
  To: Kuo, Donald, Dong, Eric, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, Laszlo Ersek (lersek@redhat.com),
	leif.lindholm@linaro.org, afish@apple.com, Kinney, Michael D

Donald:
  This change is a new feature. Now, it is not in edk2 feature planning list. If you want to catch it into 201908 stable tag, please get approve from Stewards first. I have cc this mail to all Stewards. 

  For this patch, I have one minor comment. You add one PCD in UefiCpuPkg DEC. Please also add this PCD into UefiCpuPkg.uni. 

Thanks
Liming
> -----Original Message-----
> From: Kuo, Donald
> Sent: Thursday, August 15, 2019 11:02 AM
> To: Dong, Eric <eric.dong@intel.com>; devel@edk2.groups.io; Gao, Liming <liming.gao@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
> 
> Hi Liming,
> 
> As we plan to add new TimerLib to use CPUID Leaf 0x15 (CPU XTAL clock frequency) to calculate TSC to resolve performance value
> unreliable concern.
> 
> As the code review had got approved and planning into 201908 stable tag. Please help to review whether any concern for 201908 stable
> tag.
> 
> Thanks,
> Donald
> 
> > -----Original Message-----
> > From: Dong, Eric
> > Sent: Thursday, August 15, 2019 10:46 AM
> > To: devel@edk2.groups.io; Kuo, Donald <donald.kuo@intel.com>
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> > Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>
> > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> > using CPUID(0x15) TSC leaf
> >
> > Reviewed-by: Eric Dong <eric.dong@intel.com>
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > > Donald Kuo
> > > Sent: Tuesday, August 13, 2019 6:53 PM
> > > To: devel@edk2.groups.io
> > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > Dong, Eric <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > > Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
> > > Subject: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> > > using
> > > CPUID(0x15) TSC leaf
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > >
> > > Cc: Ray Ni <ray.ni@intel.com>
> > > Cc: Star Zeng <star.zeng@intel.com>
> > > Cc: Eric Dong <eric.dong@intel.com>
> > > Cc: Amy Chan <amy.chan@intel.com>
> > > Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> > > Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> > > ---
> > >  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
> > >  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
> > > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
> > >  UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274
> > > +++++++++++++++++++++
> > >  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
> > >  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
> > > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
> > >  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
> > >  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
> > > UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
> > >  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
> > >  UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
> > >  12 files changed, 624 insertions(+)
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > >  create mode 100644
> > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > >  create mode 100644
> > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > >  create mode 100644
> > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > >
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > new file mode 100644
> > > index 0000000000..6ddf917bad
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > @@ -0,0 +1,41 @@
> > > +/** @file
> > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base
> > > +Timer
> > > Library.
> > > +
> > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Base.h>
> > > +#include <Library/TimerLib.h>
> > > +#include <Library/BaseLib.h>
> > > +
> > > +/**
> > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > +
> > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > > + or 0 if
> > > not supported.
> > > +  @return The number of TSC counts per second.
> > > +
> > > +**/
> > > +UINT64
> > > +CpuidCoreClockCalculateTscFrequency (
> > > +  VOID
> > > +  );
> > > +
> > > +/**
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  @return The frequency in Hz.
> > > +
> > > +**/
> > > +UINT64
> > > +InternalGetPerformanceCounterFrequency (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return CpuidCoreClockCalculateTscFrequency (); }
> > > +
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > new file mode 100644
> > > index 0000000000..fd93adc5f1
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > @@ -0,0 +1,35 @@
> > > +## @file
> > > +#  Base CPU Timer Library
> > > +#
> > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance #  counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +#
> > > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x00010005
> > > +  BASE_NAME                      = BaseCpuTimerLib
> > > +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> > > +  MODULE_TYPE                    = BASE
> > > +  VERSION_STRING                 = 1.0
> > > +  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
> > > +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> > > +
> > > +[Sources]
> > > +  CpuTimerLib.c
> > > +  BaseCpuTimerLib.c
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > +
> > > +[LibraryClasses]
> > > +  BaseLib
> > > +  PcdLib
> > > +  DebugLib
> > > +
> > > +[Pcd]
> > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > +CONSUMES
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > new file mode 100644
> > > index 0000000000..fcf2b0fbcb
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > @@ -0,0 +1,17 @@
> > > +// /** @file
> > > +// Base CPU Timer Library
> > > +//
> > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance // counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +//
> > > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > +
> > > +
> > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > Library"
> > > +
> > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > basic
> > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > +
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > new file mode 100644
> > > index 0000000000..0b9e9384f5
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > @@ -0,0 +1,274 @@
> > > +/** @file
> > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer
> > Library.
> > > +
> > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Base.h>
> > > +#include <Library/TimerLib.h>
> > > +#include <Library/BaseLib.h>
> > > +#include <Library/PcdLib.h>
> > > +#include <Library/DebugLib.h>
> > > +#include <Register/Cpuid.h>
> > > +
> > > +GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, {
> > > +0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
> > > +
> > > +/**
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  @return The frequency in Hz.
> > > +
> > > +**/
> > > +UINT64
> > > +InternalGetPerformanceCounterFrequency (
> > > +  VOID
> > > +  );
> > > +
> > > +/**
> > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > +
> > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > > + or 0 if
> > > not supported.
> > > +  @return The number of TSC counts per second.
> > > +
> > > +**/
> > > +UINT64
> > > +CpuidCoreClockCalculateTscFrequency (
> > > +  VOID
> > > +  )
> > > +{
> > > +  UINT64                 TscFrequency;
> > > +  UINT64                 CoreXtalFrequency;
> > > +  UINT32                 RegEax;
> > > +  UINT32                 RegEbx;
> > > +  UINT32                 RegEcx;
> > > +
> > > +  //
> > > +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> > > + Clock Information  // EBX returns 0 if not supported. ECX, if non
> > > + zero,
> > > provides Core Xtal Frequency in hertz.
> > > +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> > > +  //
> > > +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx,
> > &RegEcx,
> > > NULL);
> > > +
> > > +  //
> > > +  // If EBX returns 0, the XTAL ratio is not enumerated.
> > > +  //
> > > +  ASSERT (RegEbx != 0);
> > > +  //
> > > +  // If ECX returns 0, the XTAL frequency is not enumerated.
> > > +  //
> > > +  if (RegEcx == 0) {
> > > +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> > > +  } else {
> > > +    CoreXtalFrequency = (UINT64) RegEcx;  }
> > > +
> > > +  //
> > > +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
> > > + // TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx)
> > > + + (UINT64)(RegEax >> 1), RegEax);
> > > +
> > > +  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  Delay     A period of time to delay in ticks.
> > > +
> > > +**/
> > > +VOID
> > > +InternalCpuDelay (
> > > +  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 guarantees a minimum of 10 years before the TSC wraps.
> > > +  //
> > > +  while (AsmReadTsc() <= Ticks) {
> > > +    CpuPause();
> > > +  }
> > > +}
> > > +
> > > +/**
> > > +  Stalls the CPU for at least the given number of microseconds.
> > > +
> > > +  Stalls the CPU for the number of microseconds specified by
> > MicroSeconds.
> > > +
> > > +  @param[in]  MicroSeconds  The minimum number of microseconds to
> > > delay.
> > > +
> > > +  @return MicroSeconds
> > > +
> > > +**/
> > > +UINTN
> > > +EFIAPI
> > > +MicroSecondDelay (
> > > +  IN UINTN  MicroSeconds
> > > +  )
> > > +{
> > > +
> > > +  InternalCpuDelay (
> > > +    DivU64x32 (
> > > +      MultU64x64 (
> > > +        MicroSeconds,
> > > +        InternalGetPerformanceCounterFrequency ()
> > > +        ),
> > > +      1000000u
> > > +    )
> > > +  );
> > > +
> > > +  return MicroSeconds;
> > > +}
> > > +
> > > +/**
> > > +  Stalls the CPU for at least the given number of nanoseconds.
> > > +
> > > +  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
> > > +
> > > +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> > > +
> > > +  @return NanoSeconds
> > > +
> > > +**/
> > > +UINTN
> > > +EFIAPI
> > > +NanoSecondDelay (
> > > +  IN UINTN  NanoSeconds
> > > +  )
> > > +{
> > > +
> > > +  InternalCpuDelay (
> > > +    DivU64x32 (
> > > +      MultU64x64 (
> > > +        NanoSeconds,
> > > +        InternalGetPerformanceCounterFrequency ()
> > > +        ),
> > > +      1000000000u
> > > +    )
> > > +  );
> > > +
> > > +  return NanoSeconds;
> > > +}
> > > +
> > > +/**
> > > +  Retrieves the current value of a 64-bit free running performance counter.
> > > +
> > > +  Retrieves the current value of a 64-bit free running performance
> > > + counter. The  counter can either count up by 1 or count down by 1.
> > > + If the physical  performance counter counts by a larger increment,
> > > + then the counter values  must be translated. The properties of the
> > > + counter can be retrieved from  GetPerformanceCounterProperties().
> > > +
> > > +  @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 immediately after is it rolls over is returned
> > > + in StartValue. If  EndValue is not NULL, then the value that the
> > > + performance counter end with  immediately before it rolls over is
> > > + returned in EndValue. The 64-bit  frequency of the performance
> > > + counter in Hz is always returned. If StartValue  is less than
> > > + EndValue, then the performance counter counts up. If StartValue  is
> > > + greater than EndValue, then the performance counter counts down. For
> > > + example, a 64-bit free running counter that counts up would have a
> > > + StartValue  of
> > > + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running
> > > + counter
> > > that counts down would have a StartValue of 0xFFFFFF and an EndValue of
> > 0.
> > > +
> > > +  @param  StartValue  The value the performance counter starts with
> > > + when
> > > it
> > > +                      rolls over.
> > > +  @param  EndValue    The value that the performance counter ends with
> > > before
> > > +                      it rolls over.
> > > +
> > > +  @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
> > > + InternalGetPerformanceCounterFrequency (); }
> > > +
> > > +/**
> > > +  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;
> > > +}
> > > +
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > new file mode 100644
> > > index 0000000000..2d0ef6ab07
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > @@ -0,0 +1,81 @@
> > > +/** @file
> > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer
> > Library.
> > > +
> > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <PiDxe.h>
> > > +#include <Library/TimerLib.h>
> > > +#include <Library/BaseLib.h>
> > > +#include <Library/HobLib.h>
> > > +
> > > +extern GUID mCpuCrystalFrequencyHobGuid;
> > > +
> > > +/**
> > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > +
> > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > > + or 0 if
> > > not supported.
> > > +  @return The number of TSC counts per second.
> > > +
> > > +**/
> > > +UINT64
> > > +CpuidCoreClockCalculateTscFrequency (
> > > +  VOID
> > > +  );
> > > +
> > > +//
> > > +// Cached CPU Crystal counter frequency //
> > > +UINT64  mCpuCrystalCounterFrequency = 0;
> > > +
> > > +
> > > +/**
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  @return The frequency in Hz.
> > > +
> > > +**/
> > > +UINT64
> > > +InternalGetPerformanceCounterFrequency (
> > > +  VOID
> > > +  )
> > > +{
> > > +  return mCpuCrystalCounterFrequency; }
> > > +
> > > +/**
> > > +  The constructor function is to initialize CpuCrystalCounterFrequency.
> > > +
> > > +  @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
> > RETURN_SUCCESS.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +DxeCpuTimerLibConstructor (
> > > +  IN EFI_HANDLE        ImageHandle,
> > > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > > +  )
> > > +{
> > > +  EFI_HOB_GUID_TYPE   *GuidHob;
> > > +
> > > +  //
> > > +  // Initialize CpuCrystalCounterFrequency  //  GuidHob =
> > > + GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if (GuidHob !=
> > > + NULL) {
> > > +    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA
> > > + (GuidHob);  } else {
> > > +    mCpuCrystalCounterFrequency =
> > CpuidCoreClockCalculateTscFrequency
> > > + ();  }
> > > +
> > > +  return EFI_SUCCESS;
> > > +}
> > > +
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > new file mode 100644
> > > index 0000000000..6c83549c87
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > @@ -0,0 +1,37 @@
> > > +## @file
> > > +#  DXE CPU Timer Library
> > > +#
> > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance #  counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +#
> > > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x00010005
> > > +  BASE_NAME                      = DxeCpuTimerLib
> > > +  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
> > > +  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                    = DxeCpuTimerLibConstructor
> > > +  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
> > > +
> > > +[Sources]
> > > +  CpuTimerLib.c
> > > +  DxeCpuTimerLib.c
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > +
> > > +[LibraryClasses]
> > > +  BaseLib
> > > +  PcdLib
> > > +  DebugLib
> > > +  HobLib
> > > +
> > > +[Pcd]
> > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > +CONSUMES
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > new file mode 100644
> > > index 0000000000..f55b92abac
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > @@ -0,0 +1,17 @@
> > > +// /** @file
> > > +// DXE CPU Timer Library
> > > +//
> > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance // counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +//
> > > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > +
> > > +
> > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > Library"
> > > +
> > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > basic
> > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > +
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > new file mode 100644
> > > index 0000000000..91a7212056
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > @@ -0,0 +1,58 @@
> > > +/** @file
> > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI
> > > +Timer
> > > Library.
> > > +
> > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <PiPei.h>
> > > +#include <Library/TimerLib.h>
> > > +#include <Library/BaseLib.h>
> > > +#include <Library/HobLib.h>
> > > +#include <Library/DebugLib.h>
> > > +
> > > +extern GUID mCpuCrystalFrequencyHobGuid;
> > > +
> > > +/**
> > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > +
> > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > +  In newer flavors of the CPU, core xtal frequency is returned in ECX
> > > + or 0 if
> > > not supported.
> > > +  @return The number of TSC counts per second.
> > > +
> > > +**/
> > > +UINT64
> > > +CpuidCoreClockCalculateTscFrequency (
> > > +  VOID
> > > +  );
> > > +
> > > +/**
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > +
> > > +  @return The frequency in Hz.
> > > +
> > > +**/
> > > +UINT64
> > > +InternalGetPerformanceCounterFrequency (
> > > +  VOID
> > > +  )
> > > +{
> > > +  UINT64              *CpuCrystalCounterFrequency;
> > > +  EFI_HOB_GUID_TYPE   *GuidHob;
> > > +
> > > +  CpuCrystalCounterFrequency = NULL;
> > > +  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if
> > > + (GuidHob == NULL) {
> > > +    CpuCrystalCounterFrequency  =
> > > (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof
> > > (*CpuCrystalCounterFrequency));
> > > +    ASSERT (CpuCrystalCounterFrequency != NULL);
> > > +    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency
> > > + ();  } else {
> > > +    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA
> > > (GuidHob);
> > > + }
> > > +
> > > +  return  *CpuCrystalCounterFrequency; }
> > > +
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > new file mode 100644
> > > index 0000000000..7af0fc44a6
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > @@ -0,0 +1,36 @@
> > > +## @file
> > > +#  PEI CPU Timer Library
> > > +#
> > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance #  counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +#
> > > +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x00010005
> > > +  BASE_NAME                      = PeiCpuTimerLib
> > > +  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
> > > +  MODULE_TYPE                    = BASE
> > > +  VERSION_STRING                 = 1.0
> > > +  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
> > > +  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
> > > +
> > > +[Sources]
> > > +  CpuTimerLib.c
> > > +  PeiCpuTimerLib.c
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > +
> > > +[LibraryClasses]
> > > +  BaseLib
> > > +  PcdLib
> > > +  DebugLib
> > > +  HobLib
> > > +
> > > +[Pcd]
> > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > +CONSUMES
> > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > new file mode 100644
> > > index 0000000000..49beb44908
> > > --- /dev/null
> > > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > @@ -0,0 +1,17 @@
> > > +// /** @file
> > > +// PEI CPU Timer Library
> > > +//
> > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > +The performance // counter features are provided by the processors
> > > +time
> > > stamp counter.
> > > +//
> > > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > +
> > > +
> > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > Library"
> > > +
> > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > basic
> > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > +
> > > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> > > index 14ddaa8633..a94bd2ea30 100644
> > > --- a/UefiCpuPkg/UefiCpuPkg.dec
> > > +++ b/UefiCpuPkg/UefiCpuPkg.dec
> > > @@ -211,6 +211,14 @@
> > >    # @Prompt If CPU features will be initialized during S3 resume.
> > >
> > > gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> > > LEAN|0x0000001D
> > >
> > > +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core
> > > Crystal Clock Frequency.
> > > +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> > > +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> > > 25000000 (25MHz)
> > > +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> > > Processor Family = 24000000 (24MHz)
> > > +  #   Intel Atom processors based on Goldmont Microarchitecture with
> > > CPUID signature 06_5CH = 19200000 (19.2MHz)
> > > +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf 0x15.ECX
> > > +
> > > +
> > >
> > gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> > > UIN
> > > + T64|0x32132113
> > > +
> > >  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
> > >    ## Specifies max supported number of Logical Processors.
> > >    # @Prompt Configure max supported number of Logical Processors diff
> > > --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> > > bf690d3978..e7dfe30eda 100644
> > > --- a/UefiCpuPkg/UefiCpuPkg.dsc
> > > +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> > > @@ -101,6 +101,9 @@
> > >    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
> > >
> > >
> > UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.i
> > > nf
> > >    UefiCpuPkg/Application/Cpuid/Cpuid.inf
> > > +  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > +  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > +  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > >
> > >  [Components.IA32, Components.X64]
> > >    UefiCpuPkg/CpuDxe/CpuDxe.inf
> > > --
> > > 2.14.2.windows.3
> > >
> > >
> > > 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-15  4:37 Donald Kuo
  0 siblings, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-15  4:37 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong, Amy Chan, Rangasai V Chaganty

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Amy Chan <amy.chan@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274 +++++++++++++++++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
 UefiCpuPkg/UefiCpuPkg.uni                          |  10 +
 13 files changed, 634 insertions(+)
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni

diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..6ddf917bad
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,41 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..fd93adc5f1
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..0b9e9384f5
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,274 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, { 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  ASSERT (RegEbx != 0);
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
new file mode 100644
index 0000000000..2d0ef6ab07
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
@@ -0,0 +1,81 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+//
+// Cached CPU Crystal counter frequency
+//
+UINT64  mCpuCrystalCounterFrequency = 0;
+
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return mCpuCrystalCounterFrequency;
+}
+
+/**
+  The constructor function is to initialize CpuCrystalCounterFrequency.
+
+  @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 RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeCpuTimerLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  //
+  // Initialize CpuCrystalCounterFrequency
+  //
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob != NULL) {
+    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
new file mode 100644
index 0000000000..6c83549c87
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
@@ -0,0 +1,37 @@
+## @file
+#  DXE CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeCpuTimerLib
+  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
+  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                    = DxeCpuTimerLibConstructor
+  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  DxeCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
new file mode 100644
index 0000000000..f55b92abac
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// DXE CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
new file mode 100644
index 0000000000..91a7212056
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
@@ -0,0 +1,58 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  UINT64              *CpuCrystalCounterFrequency;
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  CpuCrystalCounterFrequency = NULL;
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob == NULL) {
+    CpuCrystalCounterFrequency  = (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof (*CpuCrystalCounterFrequency));
+    ASSERT (CpuCrystalCounterFrequency != NULL);
+    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  } else {
+    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  }
+
+  return  *CpuCrystalCounterFrequency;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
new file mode 100644
index 0000000000..7af0fc44a6
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  PEI CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiCpuTimerLib
+  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
+  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  PeiCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
new file mode 100644
index 0000000000..49beb44908
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// PEI CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..86ad61f64b 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..e7dfe30eda 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -101,6 +101,9 @@
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf
   UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
   UefiCpuPkg/Application/Cpuid/Cpuid.inf
+  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 
 [Components.IA32, Components.X64]
   UefiCpuPkg/CpuDxe/CpuDxe.inf
diff --git a/UefiCpuPkg/UefiCpuPkg.uni b/UefiCpuPkg/UefiCpuPkg.uni
index 80af4fc1d2..fbf7680726 100644
--- a/UefiCpuPkg/UefiCpuPkg.uni
+++ b/UefiCpuPkg/UefiCpuPkg.uni
@@ -242,3 +242,13 @@
 #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuKnownGoodStackSize_HELP  #language en-US "Size of good stack for an exception.\n"
                                                                                      "This PCD will only take into effect if PcdCpuStackGuard is enabled.\n"
 
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_PROMPT  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency."
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_HELP  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.<BR><BR>\n"
+                                                                                            "TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.<BR><BR>\n"
+                                                                                            "This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX.<BR><BR>\n"
+                                                                                            "Default value is 24000000 for 6th and 7th generation Intel Core processors and Intel Xeon W Processor Family.<BR>\n"
+                                                                                            "25000000  -  Intel Xeon Processor Scalable Family with CPUID signature 06_55H(25MHz).<BR>\n"
+                                                                                            "24000000  -  6th and 7th generation Intel Core processors and Intel Xeon W Processor Family(24MHz).<BR>\n"
+                                                                                            "19200000  -  Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH(19.2MHz).<BR>\n"
+
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-15  4:02     ` Liming Gao
@ 2019-08-15  4:40       ` Donald Kuo
  2019-08-16 16:16       ` Laszlo Ersek
  1 sibling, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-15  4:40 UTC (permalink / raw)
  To: Gao, Liming, Dong, Eric, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, Laszlo Ersek (lersek@redhat.com),
	leif.lindholm@linaro.org, afish@apple.com, Kinney, Michael D

[-- Attachment #1: Type: text/plain, Size: 33310 bytes --]

Thanks Liming for review.

Update UefiCpuPkg.uni for review again.

Thanks,
Donald

> -----Original Message-----
> From: Gao, Liming
> Sent: Thursday, August 15, 2019 12:03 PM
> To: Kuo, Donald <donald.kuo@intel.com>; Dong, Eric
> <eric.dong@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin
> Y <kevin.y.li@intel.com>; Laszlo Ersek (lersek@redhat.com)
> <lersek@redhat.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> using CPUID(0x15) TSC leaf
> 
> Donald:
>   This change is a new feature. Now, it is not in edk2 feature planning list. If
> you want to catch it into 201908 stable tag, please get approve from
> Stewards first. I have cc this mail to all Stewards.
> 
>   For this patch, I have one minor comment. You add one PCD in UefiCpuPkg
> DEC. Please also add this PCD into UefiCpuPkg.uni.
> 
> Thanks
> Liming
> > -----Original Message-----
> > From: Kuo, Donald
> > Sent: Thursday, August 15, 2019 11:02 AM
> > To: Dong, Eric <eric.dong@intel.com>; devel@edk2.groups.io; Gao,
> > Liming <liming.gao@intel.com>
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > Kevin Y <kevin.y.li@intel.com>
> > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> > by using CPUID(0x15) TSC leaf
> >
> > Hi Liming,
> >
> > As we plan to add new TimerLib to use CPUID Leaf 0x15 (CPU XTAL clock
> > frequency) to calculate TSC to resolve performance value unreliable
> concern.
> >
> > As the code review had got approved and planning into 201908 stable
> > tag. Please help to review whether any concern for 201908 stable tag.
> >
> > Thanks,
> > Donald
> >
> > > -----Original Message-----
> > > From: Dong, Eric
> > > Sent: Thursday, August 15, 2019 10:46 AM
> > > To: devel@edk2.groups.io; Kuo, Donald <donald.kuo@intel.com>
> > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > library by using CPUID(0x15) TSC leaf
> > >
> > > Reviewed-by: Eric Dong <eric.dong@intel.com>
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf
> > > > Of Donald Kuo
> > > > Sent: Tuesday, August 13, 2019 6:53 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > > Dong, Eric <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > > > Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
> > > > Subject: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> > > > by using
> > > > CPUID(0x15) TSC leaf
> > > >
> > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > > >
> > > > Cc: Ray Ni <ray.ni@intel.com>
> > > > Cc: Star Zeng <star.zeng@intel.com>
> > > > Cc: Eric Dong <eric.dong@intel.com>
> > > > Cc: Amy Chan <amy.chan@intel.com>
> > > > Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> > > > Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> > > > ---
> > > >  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
> > > >  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
> > > > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
> > > >  UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274
> > > > +++++++++++++++++++++
> > > >  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
> > > >  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
> > > > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
> > > >  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
> > > >  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
> > > > UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
> > > >  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
> > > >  UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
> > > >  12 files changed, 624 insertions(+)  create mode 100644
> > > > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > >  create mode 100644
> > > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > >  create mode 100644
> > > UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > >  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > >  create mode 100644
> > > > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > >  create mode 100644
> > > > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > >  create mode 100644
> > > UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > >  create mode 100644
> > > > UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > >  create mode 100644
> > > > UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > >  create mode 100644
> > > > UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > >
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > > new file mode 100644
> > > > index 0000000000..6ddf917bad
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> > > > @@ -0,0 +1,41 @@
> > > > +/** @file
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as
> > > > +Base Timer
> > > > Library.
> > > > +
> > > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Base.h>
> > > > +#include <Library/TimerLib.h>
> > > > +#include <Library/BaseLib.h>
> > > > +
> > > > +/**
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > > +
> > > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > > +  In newer flavors of the CPU, core xtal frequency is returned in
> > > > + ECX or 0 if
> > > > not supported.
> > > > +  @return The number of TSC counts per second.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +CpuidCoreClockCalculateTscFrequency (
> > > > +  VOID
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  @return The frequency in Hz.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +InternalGetPerformanceCounterFrequency (
> > > > +  VOID
> > > > +  )
> > > > +{
> > > > +  return CpuidCoreClockCalculateTscFrequency (); }
> > > > +
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > > new file mode 100644
> > > > index 0000000000..fd93adc5f1
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > > @@ -0,0 +1,35 @@
> > > > +## @file
> > > > +#  Base CPU Timer Library
> > > > +#
> > > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > > +The performance #  counter features are provided by the
> > > > +processors time
> > > > stamp counter.
> > > > +#
> > > > +#  Copyright (c) 2019, Intel Corporation. All rights
> > > > +reserved.<BR> #
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > > +
> > > > +[Defines]
> > > > +  INF_VERSION                    = 0x00010005
> > > > +  BASE_NAME                      = BaseCpuTimerLib
> > > > +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> > > > +  MODULE_TYPE                    = BASE
> > > > +  VERSION_STRING                 = 1.0
> > > > +  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
> > > > +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> > > > +
> > > > +[Sources]
> > > > +  CpuTimerLib.c
> > > > +  BaseCpuTimerLib.c
> > > > +
> > > > +[Packages]
> > > > +  MdePkg/MdePkg.dec
> > > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > > +
> > > > +[LibraryClasses]
> > > > +  BaseLib
> > > > +  PcdLib
> > > > +  DebugLib
> > > > +
> > > > +[Pcd]
> > > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > > +CONSUMES
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > > b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > > new file mode 100644
> > > > index 0000000000..fcf2b0fbcb
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> > > > @@ -0,0 +1,17 @@
> > > > +// /** @file
> > > > +// Base CPU Timer Library
> > > > +//
> > > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > > +The performance // counter features are provided by the
> > > > +processors time
> > > > stamp counter.
> > > > +//
> > > > +// Copyright (c) 2019, Intel Corporation. All rights
> > > > +reserved.<BR> // // SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +// // **/
> > > > +
> > > > +
> > > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > > Library"
> > > > +
> > > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > > basic
> > > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > > +
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > > b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > > new file mode 100644
> > > > index 0000000000..0b9e9384f5
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> > > > @@ -0,0 +1,274 @@
> > > > +/** @file
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of
> > > > +Timer
> > > Library.
> > > > +
> > > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <Base.h>
> > > > +#include <Library/TimerLib.h>
> > > > +#include <Library/BaseLib.h>
> > > > +#include <Library/PcdLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +#include <Register/Cpuid.h>
> > > > +
> > > > +GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd,
> > > > +{ 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
> > > > +
> > > > +/**
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  @return The frequency in Hz.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +InternalGetPerformanceCounterFrequency (
> > > > +  VOID
> > > > +  );
> > > > +
> > > > +/**
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > > +
> > > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > > +  In newer flavors of the CPU, core xtal frequency is returned in
> > > > + ECX or 0 if
> > > > not supported.
> > > > +  @return The number of TSC counts per second.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +CpuidCoreClockCalculateTscFrequency (
> > > > +  VOID
> > > > +  )
> > > > +{
> > > > +  UINT64                 TscFrequency;
> > > > +  UINT64                 CoreXtalFrequency;
> > > > +  UINT32                 RegEax;
> > > > +  UINT32                 RegEbx;
> > > > +  UINT32                 RegEcx;
> > > > +
> > > > +  //
> > > > +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core
> > > > + Crystal Clock Information  // EBX returns 0 if not supported.
> > > > + ECX, if non zero,
> > > > provides Core Xtal Frequency in hertz.
> > > > +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> > > > +  //
> > > > +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx,
> > > &RegEcx,
> > > > NULL);
> > > > +
> > > > +  //
> > > > +  // If EBX returns 0, the XTAL ratio is not enumerated.
> > > > +  //
> > > > +  ASSERT (RegEbx != 0);
> > > > +  //
> > > > +  // If ECX returns 0, the XTAL frequency is not enumerated.
> > > > +  //
> > > > +  if (RegEcx == 0) {
> > > > +    CoreXtalFrequency = PcdGet64
> > > > + (PcdCpuCoreCrystalClockFrequency);
> > > > +  } else {
> > > > +    CoreXtalFrequency = (UINT64) RegEcx;  }
> > > > +
> > > > +  //
> > > > +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) *
> > > > + EBX/EAX // TscFrequency = DivU64x32 (MultU64x32
> > > > + (CoreXtalFrequency, RegEbx)
> > > > + + (UINT64)(RegEax >> 1), RegEax);
> > > > +
> > > > +  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  Delay     A period of time to delay in ticks.
> > > > +
> > > > +**/
> > > > +VOID
> > > > +InternalCpuDelay (
> > > > +  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 guarantees a minimum of 10 years before the TSC wraps.
> > > > +  //
> > > > +  while (AsmReadTsc() <= Ticks) {
> > > > +    CpuPause();
> > > > +  }
> > > > +}
> > > > +
> > > > +/**
> > > > +  Stalls the CPU for at least the given number of microseconds.
> > > > +
> > > > +  Stalls the CPU for the number of microseconds specified by
> > > MicroSeconds.
> > > > +
> > > > +  @param[in]  MicroSeconds  The minimum number of microseconds
> to
> > > > delay.
> > > > +
> > > > +  @return MicroSeconds
> > > > +
> > > > +**/
> > > > +UINTN
> > > > +EFIAPI
> > > > +MicroSecondDelay (
> > > > +  IN UINTN  MicroSeconds
> > > > +  )
> > > > +{
> > > > +
> > > > +  InternalCpuDelay (
> > > > +    DivU64x32 (
> > > > +      MultU64x64 (
> > > > +        MicroSeconds,
> > > > +        InternalGetPerformanceCounterFrequency ()
> > > > +        ),
> > > > +      1000000u
> > > > +    )
> > > > +  );
> > > > +
> > > > +  return MicroSeconds;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Stalls the CPU for at least the given number of nanoseconds.
> > > > +
> > > > +  Stalls the CPU for the number of nanoseconds specified by
> NanoSeconds.
> > > > +
> > > > +  @param  NanoSeconds The minimum number of nanoseconds to
> delay.
> > > > +
> > > > +  @return NanoSeconds
> > > > +
> > > > +**/
> > > > +UINTN
> > > > +EFIAPI
> > > > +NanoSecondDelay (
> > > > +  IN UINTN  NanoSeconds
> > > > +  )
> > > > +{
> > > > +
> > > > +  InternalCpuDelay (
> > > > +    DivU64x32 (
> > > > +      MultU64x64 (
> > > > +        NanoSeconds,
> > > > +        InternalGetPerformanceCounterFrequency ()
> > > > +        ),
> > > > +      1000000000u
> > > > +    )
> > > > +  );
> > > > +
> > > > +  return NanoSeconds;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Retrieves the current value of a 64-bit free running performance
> counter.
> > > > +
> > > > +  Retrieves the current value of a 64-bit free running
> > > > + performance counter. The  counter can either count up by 1 or count
> down by 1.
> > > > + If the physical  performance counter counts by a larger
> > > > + increment, then the counter values  must be translated. The
> > > > + properties of the counter can be retrieved from
> GetPerformanceCounterProperties().
> > > > +
> > > > +  @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 immediately after is it rolls over is
> > > > + returned in StartValue. If  EndValue is not NULL, then the value
> > > > + that the performance counter end with  immediately before it
> > > > + rolls over is returned in EndValue. The 64-bit  frequency of the
> > > > + performance counter in Hz is always returned. If StartValue  is
> > > > + less than EndValue, then the performance counter counts up. If
> > > > + StartValue  is greater than EndValue, then the performance
> > > > + counter counts down. For example, a 64-bit free running counter
> > > > + that counts up would have a StartValue  of
> > > > + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running
> > > > + counter
> > > > that counts down would have a StartValue of 0xFFFFFF and an
> > > > EndValue of
> > > 0.
> > > > +
> > > > +  @param  StartValue  The value the performance counter starts
> > > > + with when
> > > > it
> > > > +                      rolls over.
> > > > +  @param  EndValue    The value that the performance counter ends
> with
> > > > before
> > > > +                      it rolls over.
> > > > +
> > > > +  @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
> > > > + InternalGetPerformanceCounterFrequency (); }
> > > > +
> > > > +/**
> > > > +  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;
> > > > +}
> > > > +
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > > new file mode 100644
> > > > index 0000000000..2d0ef6ab07
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> > > > @@ -0,0 +1,81 @@
> > > > +/** @file
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of
> > > > +Timer
> > > Library.
> > > > +
> > > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <PiDxe.h>
> > > > +#include <Library/TimerLib.h>
> > > > +#include <Library/BaseLib.h>
> > > > +#include <Library/HobLib.h>
> > > > +
> > > > +extern GUID mCpuCrystalFrequencyHobGuid;
> > > > +
> > > > +/**
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > > +
> > > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > > +  In newer flavors of the CPU, core xtal frequency is returned in
> > > > + ECX or 0 if
> > > > not supported.
> > > > +  @return The number of TSC counts per second.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +CpuidCoreClockCalculateTscFrequency (
> > > > +  VOID
> > > > +  );
> > > > +
> > > > +//
> > > > +// Cached CPU Crystal counter frequency //
> > > > +UINT64  mCpuCrystalCounterFrequency = 0;
> > > > +
> > > > +
> > > > +/**
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  @return The frequency in Hz.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +InternalGetPerformanceCounterFrequency (
> > > > +  VOID
> > > > +  )
> > > > +{
> > > > +  return mCpuCrystalCounterFrequency; }
> > > > +
> > > > +/**
> > > > +  The constructor function is to initialize CpuCrystalCounterFrequency.
> > > > +
> > > > +  @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
> > > RETURN_SUCCESS.
> > > > +
> > > > +**/
> > > > +EFI_STATUS
> > > > +EFIAPI
> > > > +DxeCpuTimerLibConstructor (
> > > > +  IN EFI_HANDLE        ImageHandle,
> > > > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > > > +  )
> > > > +{
> > > > +  EFI_HOB_GUID_TYPE   *GuidHob;
> > > > +
> > > > +  //
> > > > +  // Initialize CpuCrystalCounterFrequency  //  GuidHob =
> > > > + GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if (GuidHob !=
> > > > + NULL) {
> > > > +    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA
> > > > + (GuidHob);  } else {
> > > > +    mCpuCrystalCounterFrequency =
> > > CpuidCoreClockCalculateTscFrequency
> > > > + ();  }
> > > > +
> > > > +  return EFI_SUCCESS;
> > > > +}
> > > > +
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > > new file mode 100644
> > > > index 0000000000..6c83549c87
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > > @@ -0,0 +1,37 @@
> > > > +## @file
> > > > +#  DXE CPU Timer Library
> > > > +#
> > > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > > +The performance #  counter features are provided by the
> > > > +processors time
> > > > stamp counter.
> > > > +#
> > > > +#  Copyright (c) 2019, Intel Corporation. All rights
> > > > +reserved.<BR> #
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > > +
> > > > +[Defines]
> > > > +  INF_VERSION                    = 0x00010005
> > > > +  BASE_NAME                      = DxeCpuTimerLib
> > > > +  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
> > > > +  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                    = DxeCpuTimerLibConstructor
> > > > +  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
> > > > +
> > > > +[Sources]
> > > > +  CpuTimerLib.c
> > > > +  DxeCpuTimerLib.c
> > > > +
> > > > +[Packages]
> > > > +  MdePkg/MdePkg.dec
> > > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > > +
> > > > +[LibraryClasses]
> > > > +  BaseLib
> > > > +  PcdLib
> > > > +  DebugLib
> > > > +  HobLib
> > > > +
> > > > +[Pcd]
> > > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > > +CONSUMES
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > > b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > > new file mode 100644
> > > > index 0000000000..f55b92abac
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> > > > @@ -0,0 +1,17 @@
> > > > +// /** @file
> > > > +// DXE CPU Timer Library
> > > > +//
> > > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > > +The performance // counter features are provided by the
> > > > +processors time
> > > > stamp counter.
> > > > +//
> > > > +// Copyright (c) 2019, Intel Corporation. All rights
> > > > +reserved.<BR> // // SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +// // **/
> > > > +
> > > > +
> > > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > > Library"
> > > > +
> > > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > > basic
> > > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > > +
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > > new file mode 100644
> > > > index 0000000000..91a7212056
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> > > > @@ -0,0 +1,58 @@
> > > > +/** @file
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as
> > > > +PEI Timer
> > > > Library.
> > > > +
> > > > +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +#include <PiPei.h>
> > > > +#include <Library/TimerLib.h>
> > > > +#include <Library/BaseLib.h>
> > > > +#include <Library/HobLib.h>
> > > > +#include <Library/DebugLib.h>
> > > > +
> > > > +extern GUID mCpuCrystalFrequencyHobGuid;
> > > > +
> > > > +/**
> > > > +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> > > > +
> > > > +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> > > > Frequency in MHz = Core XTAL frequency * EBX/EAX.
> > > > +  In newer flavors of the CPU, core xtal frequency is returned in
> > > > + ECX or 0 if
> > > > not supported.
> > > > +  @return The number of TSC counts per second.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +CpuidCoreClockCalculateTscFrequency (
> > > > +  VOID
> > > > +  );
> > > > +
> > > > +/**
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  Internal function to retrieves the 64-bit frequency in Hz.
> > > > +
> > > > +  @return The frequency in Hz.
> > > > +
> > > > +**/
> > > > +UINT64
> > > > +InternalGetPerformanceCounterFrequency (
> > > > +  VOID
> > > > +  )
> > > > +{
> > > > +  UINT64              *CpuCrystalCounterFrequency;
> > > > +  EFI_HOB_GUID_TYPE   *GuidHob;
> > > > +
> > > > +  CpuCrystalCounterFrequency = NULL;  GuidHob = GetFirstGuidHob
> > > > + (&mCpuCrystalFrequencyHobGuid);  if (GuidHob == NULL) {
> > > > +    CpuCrystalCounterFrequency  =
> > > > (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof
> > > > (*CpuCrystalCounterFrequency));
> > > > +    ASSERT (CpuCrystalCounterFrequency != NULL);
> > > > +    *CpuCrystalCounterFrequency =
> > > > + CpuidCoreClockCalculateTscFrequency
> > > > + ();  } else {
> > > > +    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA
> > > > (GuidHob);
> > > > + }
> > > > +
> > > > +  return  *CpuCrystalCounterFrequency; }
> > > > +
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > > new file mode 100644
> > > > index 0000000000..7af0fc44a6
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > > @@ -0,0 +1,36 @@
> > > > +## @file
> > > > +#  PEI CPU Timer Library
> > > > +#
> > > > +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > > +The performance #  counter features are provided by the
> > > > +processors time
> > > > stamp counter.
> > > > +#
> > > > +#  Copyright (c) 2019, Intel Corporation. All rights
> > > > +reserved.<BR> #
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > > +
> > > > +[Defines]
> > > > +  INF_VERSION                    = 0x00010005
> > > > +  BASE_NAME                      = PeiCpuTimerLib
> > > > +  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
> > > > +  MODULE_TYPE                    = BASE
> > > > +  VERSION_STRING                 = 1.0
> > > > +  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
> > > > +  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
> > > > +
> > > > +[Sources]
> > > > +  CpuTimerLib.c
> > > > +  PeiCpuTimerLib.c
> > > > +
> > > > +[Packages]
> > > > +  MdePkg/MdePkg.dec
> > > > +  UefiCpuPkg/UefiCpuPkg.dec
> > > > +
> > > > +[LibraryClasses]
> > > > +  BaseLib
> > > > +  PcdLib
> > > > +  DebugLib
> > > > +  HobLib
> > > > +
> > > > +[Pcd]
> > > > +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> > > > +CONSUMES
> > > > diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > > b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > > new file mode 100644
> > > > index 0000000000..49beb44908
> > > > --- /dev/null
> > > > +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> > > > @@ -0,0 +1,17 @@
> > > > +// /** @file
> > > > +// PEI CPU Timer Library
> > > > +//
> > > > +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> > > > +The performance // counter features are provided by the
> > > > +processors time
> > > > stamp counter.
> > > > +//
> > > > +// Copyright (c) 2019, Intel Corporation. All rights
> > > > +reserved.<BR> // // SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +// // **/
> > > > +
> > > > +
> > > > +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> > > > Library"
> > > > +
> > > > +#string STR_MODULE_DESCRIPTION          #language en-US "Provides
> > > basic
> > > > timer support using CPUID Leaf 0x15 XTAL frequency."
> > > > +
> > > > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> > > > index 14ddaa8633..a94bd2ea30 100644
> > > > --- a/UefiCpuPkg/UefiCpuPkg.dec
> > > > +++ b/UefiCpuPkg/UefiCpuPkg.dec
> > > > @@ -211,6 +211,14 @@
> > > >    # @Prompt If CPU features will be initialized during S3 resume.
> > > >
> > > >
> gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOO
> > > > LEAN|0x0000001D
> > > >
> > > > +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal
> > > > + Core
> > > > Crystal Clock Frequency.
> > > > +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> > > > +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H
> =
> > > > 25000000 (25MHz)
> > > > +  #   6th and 7th generation Intel Core processors and Intel Xeon W
> > > > Processor Family = 24000000 (24MHz)
> > > > +  #   Intel Atom processors based on Goldmont Microarchitecture with
> > > > CPUID signature 06_5CH = 19200000 (19.2MHz)
> > > > +  # @Prompt Core Crystal Clock Frequency is for CPUID Leaf
> > > > + 0x15.ECX
> > > > +
> > > > +
> > > >
> > >
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|
> > > > UIN
> > > > + T64|0x32132113
> > > > +
> > > >  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic,
> PcdsDynamicEx]
> > > >    ## Specifies max supported number of Logical Processors.
> > > >    # @Prompt Configure max supported number of Logical Processors
> > > > diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
> > > > index bf690d3978..e7dfe30eda 100644
> > > > --- a/UefiCpuPkg/UefiCpuPkg.dsc
> > > > +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> > > > @@ -101,6 +101,9 @@
> > > >    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
> > > >
> > > >
> > >
> UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu
> > > .i
> > > > nf
> > > >    UefiCpuPkg/Application/Cpuid/Cpuid.inf
> > > > +  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> > > > +  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> > > > +  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> > > >
> > > >  [Components.IA32, Components.X64]
> > > >    UefiCpuPkg/CpuDxe/CpuDxe.inf
> > > > --
> > > > 2.14.2.windows.3
> > > >
> > > >
> > > > 


[-- Attachment #2: Type: message/rfc822, Size: 27250 bytes --]

From: "Kuo, Donald" <donald.kuo@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Ni, Ray" <ray.ni@intel.com>, "Zeng, Star" <star.zeng@intel.com>, "Dong, Eric" <eric.dong@intel.com>, "Chan, Amy" <amy.chan@intel.com>, "Chaganty, Rangasai V" <rangasai.v.chaganty@intel.com>
Subject: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
Date: Thu, 15 Aug 2019 04:37:48 +0000
Message-ID: <15BAFEB54B2C61CD.23161@groups.io>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Amy Chan <amy.chan@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 274 +++++++++++++++++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  81 ++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
 UefiCpuPkg/UefiCpuPkg.uni                          |  10 +
 13 files changed, 634 insertions(+)
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni

diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..6ddf917bad
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,41 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..fd93adc5f1
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..0b9e9384f5
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,274 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, { 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+
+  //
+  // If EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  ASSERT (RegEbx != 0);
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  //
+  if (RegEcx == 0) {
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
new file mode 100644
index 0000000000..2d0ef6ab07
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
@@ -0,0 +1,81 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+//
+// Cached CPU Crystal counter frequency
+//
+UINT64  mCpuCrystalCounterFrequency = 0;
+
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return mCpuCrystalCounterFrequency;
+}
+
+/**
+  The constructor function is to initialize CpuCrystalCounterFrequency.
+
+  @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 RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeCpuTimerLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  //
+  // Initialize CpuCrystalCounterFrequency
+  //
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob != NULL) {
+    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
new file mode 100644
index 0000000000..6c83549c87
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
@@ -0,0 +1,37 @@
+## @file
+#  DXE CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeCpuTimerLib
+  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
+  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                    = DxeCpuTimerLibConstructor
+  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  DxeCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
new file mode 100644
index 0000000000..f55b92abac
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// DXE CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
new file mode 100644
index 0000000000..91a7212056
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
@@ -0,0 +1,58 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  UINT64              *CpuCrystalCounterFrequency;
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  CpuCrystalCounterFrequency = NULL;
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob == NULL) {
+    CpuCrystalCounterFrequency  = (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof (*CpuCrystalCounterFrequency));
+    ASSERT (CpuCrystalCounterFrequency != NULL);
+    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  } else {
+    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  }
+
+  return  *CpuCrystalCounterFrequency;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
new file mode 100644
index 0000000000..7af0fc44a6
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  PEI CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiCpuTimerLib
+  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
+  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  PeiCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
new file mode 100644
index 0000000000..49beb44908
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// PEI CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..86ad61f64b 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D

+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..e7dfe30eda 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -101,6 +101,9 @@
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf
   UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
   UefiCpuPkg/Application/Cpuid/Cpuid.inf
+  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf

 [Components.IA32, Components.X64]
   UefiCpuPkg/CpuDxe/CpuDxe.inf
diff --git a/UefiCpuPkg/UefiCpuPkg.uni b/UefiCpuPkg/UefiCpuPkg.uni
index 80af4fc1d2..fbf7680726 100644
--- a/UefiCpuPkg/UefiCpuPkg.uni
+++ b/UefiCpuPkg/UefiCpuPkg.uni
@@ -242,3 +242,13 @@
 #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuKnownGoodStackSize_HELP  #language en-US "Size of good stack for an exception.\n"
                                                                                      "This PCD will only take into effect if PcdCpuStackGuard is enabled.\n"

+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_PROMPT  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency."
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_HELP  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.<BR><BR>\n"
+                                                                                            "TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.<BR><BR>\n"
+                                                                                            "This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX.<BR><BR>\n"
+                                                                                            "Default value is 24000000 for 6th and 7th generation Intel Core processors and Intel Xeon W Processor Family.<BR>\n"
+                                                                                            "25000000  -  Intel Xeon Processor Scalable Family with CPUID signature 06_55H(25MHz).<BR>\n"
+                                                                                            "24000000  -  6th and 7th generation Intel Core processors and Intel Xeon W Processor Family(24MHz).<BR>\n"
+                                                                                            "19200000  -  Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH(19.2MHz).<BR>\n"
+
--
2.14.2.windows.3


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#45682): https://edk2.groups.io/g/devel/message/45682
Mute This Topic: https://groups.io/mt/32839184/1887560
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [donald.kuo@intel.com]
-=-=-=-=-=-=-=-=-=-=-=-


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
@ 2019-08-15  9:11 Donald Kuo
  2019-08-16  4:27 ` Dong, Eric
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-15  9:11 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Star Zeng, Eric Dong, Amy Chan, Rangasai V Chaganty

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Amy Chan <amy.chan@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Signed-off-by: Donald Kuo <donald.kuo@intel.com>
---
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 279 +++++++++++++++++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  85 +++++++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
 UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
 UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
 UefiCpuPkg/UefiCpuPkg.uni                          |  10 +
 13 files changed, 643 insertions(+)
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni

diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
new file mode 100644
index 0000000000..6ddf917bad
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
@@ -0,0 +1,41 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return CpuidCoreClockCalculateTscFrequency ();
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644
index 0000000000..fd93adc5f1
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  Base CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseCpuTimerLib
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  BaseCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644
index 0000000000..fcf2b0fbcb
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Base CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
new file mode 100644
index 0000000000..192a401fe6
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
@@ -0,0 +1,279 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Cpuid.h>
+
+GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, { 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  );
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  )
+{
+  UINT64                 TscFrequency;
+  UINT64                 CoreXtalFrequency;
+  UINT32                 RegEax;
+  UINT32                 RegEbx;
+  UINT32                 RegEcx;
+
+  //
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
+  //
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
+
+  //
+  // If EAX or EBX returns 0, the XTAL ratio is not enumerated.
+  //
+  if (RegEax == 0 || RegEbx ==0 ) {
+    ASSERT (RegEax != 0);
+    ASSERT (RegEbx != 0);
+    return 0;
+  }
+  //
+  // If ECX returns 0, the XTAL frequency is not enumerated.
+  // And PcdCpuCoreCrystalClockFrequency defined should base on processor series.
+  //
+  if (RegEcx == 0) {
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
+  } else {
+    CoreXtalFrequency = (UINT64) RegEcx;
+  }
+
+  //
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
+  //
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
+
+  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  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalCpuDelay (
+  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 guarantees a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc() <= Ticks) {
+    CpuPause();
+  }
+}
+
+/**
+  Stalls the CPU for at least the given number of microseconds.
+
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN UINTN  MicroSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        MicroSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000u
+    )
+  );
+
+  return MicroSeconds;
+}
+
+/**
+  Stalls the CPU for at least the given number of nanoseconds.
+
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+  @param  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN UINTN  NanoSeconds
+  )
+{
+
+  InternalCpuDelay (
+    DivU64x32 (
+      MultU64x64 (
+        NanoSeconds,
+        InternalGetPerformanceCounterFrequency ()
+        ),
+      1000000000u
+    )
+  );
+
+  return NanoSeconds;
+}
+
+/**
+  Retrieves the current value of a 64-bit free running performance counter.
+
+  Retrieves the current value of a 64-bit free running performance counter. The
+  counter can either count up by 1 or count down by 1. If the physical
+  performance counter counts by a larger increment, then the counter values
+  must be translated. The properties of the counter can be retrieved from
+  GetPerformanceCounterProperties().
+
+  @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 immediately after is it rolls over is returned in StartValue. If
+  EndValue is not NULL, then the value that the performance counter end with
+  immediately before it rolls over is returned in EndValue. The 64-bit
+  frequency of the performance counter in Hz is always returned. If StartValue
+  is less than EndValue, then the performance counter counts up. If StartValue
+  is greater than EndValue, then the performance counter counts down. For
+  example, a 64-bit free running counter that counts up would have a StartValue
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+  @param  StartValue  The value the performance counter starts with when it
+                      rolls over.
+  @param  EndValue    The value that the performance counter ends with before
+                      it rolls over.
+
+  @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 InternalGetPerformanceCounterFrequency ();
+}
+
+/**
+  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;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
new file mode 100644
index 0000000000..269e5a3e83
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
@@ -0,0 +1,85 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+//
+// Cached CPU Crystal counter frequency
+//
+UINT64  mCpuCrystalCounterFrequency = 0;
+
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  return mCpuCrystalCounterFrequency;
+}
+
+/**
+  The constructor function is to initialize CpuCrystalCounterFrequency.
+
+  @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 RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeCpuTimerLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  //
+  // Initialize CpuCrystalCounterFrequency
+  //
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob != NULL) {
+    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  }
+
+  if (mCpuCrystalCounterFrequency == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
new file mode 100644
index 0000000000..6c83549c87
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
@@ -0,0 +1,37 @@
+## @file
+#  DXE CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeCpuTimerLib
+  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
+  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                    = DxeCpuTimerLibConstructor
+  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  DxeCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
new file mode 100644
index 0000000000..f55b92abac
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// DXE CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
new file mode 100644
index 0000000000..91a7212056
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
@@ -0,0 +1,58 @@
+/** @file
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer Library.
+
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+
+extern GUID mCpuCrystalFrequencyHobGuid;
+
+/**
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
+
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+CpuidCoreClockCalculateTscFrequency (
+  VOID
+  );
+
+/**
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  Internal function to retrieves the 64-bit frequency in Hz.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+  VOID
+  )
+{
+  UINT64              *CpuCrystalCounterFrequency;
+  EFI_HOB_GUID_TYPE   *GuidHob;
+
+  CpuCrystalCounterFrequency = NULL;
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
+  if (GuidHob == NULL) {
+    CpuCrystalCounterFrequency  = (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof (*CpuCrystalCounterFrequency));
+    ASSERT (CpuCrystalCounterFrequency != NULL);
+    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
+  } else {
+    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob);
+  }
+
+  return  *CpuCrystalCounterFrequency;
+}
+
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
new file mode 100644
index 0000000000..7af0fc44a6
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  PEI CPU Timer Library
+#
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiCpuTimerLib
+  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
+  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
+
+[Sources]
+  CpuTimerLib.c
+  PeiCpuTimerLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  DebugLib
+  HobLib
+
+[Pcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
new file mode 100644
index 0000000000..49beb44908
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// PEI CPU Timer Library
+//
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 14ddaa8633..86ad61f64b 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -211,6 +211,14 @@
   # @Prompt If CPU features will be initialized during S3 resume.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
 
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)
+  # @Prompt This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113
+
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## Specifies max supported number of Logical Processors.
   # @Prompt Configure max supported number of Logical Processors
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index bf690d3978..e7dfe30eda 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -101,6 +101,9 @@
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf
   UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
   UefiCpuPkg/Application/Cpuid/Cpuid.inf
+  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
+  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
 
 [Components.IA32, Components.X64]
   UefiCpuPkg/CpuDxe/CpuDxe.inf
diff --git a/UefiCpuPkg/UefiCpuPkg.uni b/UefiCpuPkg/UefiCpuPkg.uni
index 80af4fc1d2..fbf7680726 100644
--- a/UefiCpuPkg/UefiCpuPkg.uni
+++ b/UefiCpuPkg/UefiCpuPkg.uni
@@ -242,3 +242,13 @@
 #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuKnownGoodStackSize_HELP  #language en-US "Size of good stack for an exception.\n"
                                                                                      "This PCD will only take into effect if PcdCpuStackGuard is enabled.\n"
 
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_PROMPT  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency."
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_HELP  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.<BR><BR>\n"
+                                                                                            "TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.<BR><BR>\n"
+                                                                                            "This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX.<BR><BR>\n"
+                                                                                            "Default value is 24000000 for 6th and 7th generation Intel Core processors and Intel Xeon W Processor Family.<BR>\n"
+                                                                                            "25000000  -  Intel Xeon Processor Scalable Family with CPUID signature 06_55H(25MHz).<BR>\n"
+                                                                                            "24000000  -  6th and 7th generation Intel Core processors and Intel Xeon W Processor Family(24MHz).<BR>\n"
+                                                                                            "19200000  -  Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH(19.2MHz).<BR>\n"
+
-- 
2.14.2.windows.3


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-15  9:11 Donald Kuo
@ 2019-08-16  4:27 ` Dong, Eric
  0 siblings, 0 replies; 27+ messages in thread
From: Dong, Eric @ 2019-08-16  4:27 UTC (permalink / raw)
  To: Kuo, Donald, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V

Reviewed-by: Eric Dong <eric.dong@intel.com>

> -----Original Message-----
> From: Kuo, Donald
> Sent: Thursday, August 15, 2019 5:11 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Chan, Amy <amy.chan@intel.com>; Chaganty,
> Rangasai V <rangasai.v.chaganty@intel.com>
> Subject: [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15)
> TSC leaf
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> 
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Amy Chan <amy.chan@intel.com>
> Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> Signed-off-by: Donald Kuo <donald.kuo@intel.com>
> ---
>  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c   |  41 +++
>  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf |  35 +++
> UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni |  17 ++
>  UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c       | 279
> +++++++++++++++++++++
>  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c    |  85 +++++++
>  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf  |  37 +++
> UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni  |  17 ++
>  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c    |  58 +++++
>  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf  |  36 +++
> UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni  |  17 ++
>  UefiCpuPkg/UefiCpuPkg.dec                          |   8 +
>  UefiCpuPkg/UefiCpuPkg.dsc                          |   3 +
>  UefiCpuPkg/UefiCpuPkg.uni                          |  10 +
>  13 files changed, 643 insertions(+)
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> 
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> new file mode 100644
> index 0000000000..6ddf917bad
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
> @@ -0,0 +1,41 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer
> Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not
> supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  return CpuidCoreClockCalculateTscFrequency (); }
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> new file mode 100644
> index 0000000000..fd93adc5f1
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> @@ -0,0 +1,35 @@
> +## @file
> +#  Base CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = BaseCpuTimerLib
> +  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM
> +  MODULE_UNI_FILE                = BaseCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  BaseCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> new file mode 100644
> index 0000000000..fcf2b0fbcb
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
> @@ -0,0 +1,17 @@
> +// /** @file
> +// Base CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> new file mode 100644
> index 0000000000..192a401fe6
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
> @@ -0,0 +1,279 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DebugLib.h>
> +#include <Register/Cpuid.h>
> +
> +GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, {
> +0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  );
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not
> supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  )
> +{
> +  UINT64                 TscFrequency;
> +  UINT64                 CoreXtalFrequency;
> +  UINT32                 RegEax;
> +  UINT32                 RegEbx;
> +  UINT32                 RegEcx;
> +
> +  //
> +  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> + Clock Information  // EBX returns 0 if not supported. ECX, if non zero,
> provides Core Xtal Frequency in hertz.
> +  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
> +  //
> +  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx,
> NULL);
> +
> +  //
> +  // If EAX or EBX returns 0, the XTAL ratio is not enumerated.
> +  //
> +  if (RegEax == 0 || RegEbx ==0 ) {
> +    ASSERT (RegEax != 0);
> +    ASSERT (RegEbx != 0);
> +    return 0;
> +  }
> +  //
> +  // If ECX returns 0, the XTAL frequency is not enumerated.
> +  // And PcdCpuCoreCrystalClockFrequency defined should base on processor
> series.
> +  //
> +  if (RegEcx == 0) {
> +    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
> +  } else {
> +    CoreXtalFrequency = (UINT64) RegEcx;  }
> +
> +  //
> +  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX  //
> + TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) +
> + (UINT64)(RegEax >> 1), RegEax);
> +
> +  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  Delay     A period of time to delay in ticks.
> +
> +**/
> +VOID
> +InternalCpuDelay (
> +  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 guarantees a minimum of 10 years before the TSC wraps.
> +  //
> +  while (AsmReadTsc() <= Ticks) {
> +    CpuPause();
> +  }
> +}
> +
> +/**
> +  Stalls the CPU for at least the given number of microseconds.
> +
> +  Stalls the CPU for the number of microseconds specified by MicroSeconds.
> +
> +  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
> +
> +  @return MicroSeconds
> +
> +**/
> +UINTN
> +EFIAPI
> +MicroSecondDelay (
> +  IN UINTN  MicroSeconds
> +  )
> +{
> +
> +  InternalCpuDelay (
> +    DivU64x32 (
> +      MultU64x64 (
> +        MicroSeconds,
> +        InternalGetPerformanceCounterFrequency ()
> +        ),
> +      1000000u
> +    )
> +  );
> +
> +  return MicroSeconds;
> +}
> +
> +/**
> +  Stalls the CPU for at least the given number of nanoseconds.
> +
> +  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
> +
> +  @param  NanoSeconds The minimum number of nanoseconds to delay.
> +
> +  @return NanoSeconds
> +
> +**/
> +UINTN
> +EFIAPI
> +NanoSecondDelay (
> +  IN UINTN  NanoSeconds
> +  )
> +{
> +
> +  InternalCpuDelay (
> +    DivU64x32 (
> +      MultU64x64 (
> +        NanoSeconds,
> +        InternalGetPerformanceCounterFrequency ()
> +        ),
> +      1000000000u
> +    )
> +  );
> +
> +  return NanoSeconds;
> +}
> +
> +/**
> +  Retrieves the current value of a 64-bit free running performance counter.
> +
> +  Retrieves the current value of a 64-bit free running performance
> + counter. The  counter can either count up by 1 or count down by 1. If
> + the physical  performance counter counts by a larger increment, then
> + the counter values  must be translated. The properties of the counter
> + can be retrieved from  GetPerformanceCounterProperties().
> +
> +  @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 immediately after is it rolls over is returned in
> + StartValue. If  EndValue is not NULL, then the value that the
> + performance counter end with  immediately before it rolls over is
> + returned in EndValue. The 64-bit  frequency of the performance counter
> + in Hz is always returned. If StartValue  is less than EndValue, then
> + the performance counter counts up. If StartValue  is greater than
> + EndValue, then the performance counter counts down. For  example, a
> + 64-bit free running counter that counts up would have a StartValue  of
> + 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter  that
> counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
> +
> +  @param  StartValue  The value the performance counter starts with when it
> +                      rolls over.
> +  @param  EndValue    The value that the performance counter ends with
> before
> +                      it rolls over.
> +
> +  @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 InternalGetPerformanceCounterFrequency (); }
> +
> +/**
> +  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;
> +}
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> new file mode 100644
> index 0000000000..269e5a3e83
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
> @@ -0,0 +1,85 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/HobLib.h>
> +
> +extern GUID mCpuCrystalFrequencyHobGuid;
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not
> supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +//
> +// Cached CPU Crystal counter frequency //
> +UINT64  mCpuCrystalCounterFrequency = 0;
> +
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  return mCpuCrystalCounterFrequency;
> +}
> +
> +/**
> +  The constructor function is to initialize CpuCrystalCounterFrequency.
> +
> +  @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 RETURN_SUCCESS.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DxeCpuTimerLibConstructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_HOB_GUID_TYPE   *GuidHob;
> +
> +  //
> +  // Initialize CpuCrystalCounterFrequency  //  GuidHob =
> + GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if (GuidHob != NULL)
> + {
> +    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA
> + (GuidHob);  } else {
> +    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency
> + ();  }
> +
> +  if (mCpuCrystalCounterFrequency == 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> new file mode 100644
> index 0000000000..6c83549c87
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +#  DXE CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = DxeCpuTimerLib
> +  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
> +  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                    = DxeCpuTimerLibConstructor
> +  MODULE_UNI_FILE                = DxeCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  DxeCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +  HobLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> new file mode 100644
> index 0000000000..f55b92abac
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
> @@ -0,0 +1,17 @@
> +// /** @file
> +// DXE CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> new file mode 100644
> index 0000000000..91a7212056
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
> @@ -0,0 +1,58 @@
> +/** @file
> +  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer
> Library.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiPei.h>
> +#include <Library/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/DebugLib.h>
> +
> +extern GUID mCpuCrystalFrequencyHobGuid;
> +
> +/**
> +  CPUID Leaf 0x15 for Core Crystal Clock Frequency.
> +
> +  The TSC counting frequency is determined by using CPUID leaf 0x15.
> Frequency in MHz = Core XTAL frequency * EBX/EAX.
> +  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not
> supported.
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +CpuidCoreClockCalculateTscFrequency (
> +  VOID
> +  );
> +
> +/**
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  Internal function to retrieves the 64-bit frequency in Hz.
> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT64
> +InternalGetPerformanceCounterFrequency (
> +  VOID
> +  )
> +{
> +  UINT64              *CpuCrystalCounterFrequency;
> +  EFI_HOB_GUID_TYPE   *GuidHob;
> +
> +  CpuCrystalCounterFrequency = NULL;
> +  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);  if
> + (GuidHob == NULL) {
> +    CpuCrystalCounterFrequency  =
> (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof
> (*CpuCrystalCounterFrequency));
> +    ASSERT (CpuCrystalCounterFrequency != NULL);
> +    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency
> + ();  } else {
> +    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA
> (GuidHob);
> + }
> +
> +  return  *CpuCrystalCounterFrequency;
> +}
> +
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> new file mode 100644
> index 0000000000..7af0fc44a6
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> @@ -0,0 +1,36 @@
> +## @file
> +#  PEI CPU Timer Library
> +#
> +#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance #  counter features are provided by the processors time
> stamp counter.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = PeiCpuTimerLib
> +  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM
> +  MODULE_UNI_FILE                = PeiCpuTimerLib.uni
> +
> +[Sources]
> +  CpuTimerLib.c
> +  PeiCpuTimerLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib
> +  HobLib
> +
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ##
> +CONSUMES
> diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> new file mode 100644
> index 0000000000..49beb44908
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
> @@ -0,0 +1,17 @@
> +// /** @file
> +// PEI CPU Timer Library
> +//
> +// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.
> +The performance // counter features are provided by the processors time
> stamp counter.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer
> Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic
> timer support using CPUID Leaf 0x15 XTAL frequency."
> +
> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index
> 14ddaa8633..86ad61f64b 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dec
> +++ b/UefiCpuPkg/UefiCpuPkg.dec
> @@ -211,6 +211,14 @@
>    # @Prompt If CPU features will be initialized during S3 resume.
> 
> gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLE
> AN|0x0000001D
> 
> +  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal
> Clock Frequency.
> +  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
> +  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H =
> 25000000 (25MHz)
> +  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor
> Family = 24000000 (24MHz)
> +  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID
> signature 06_5CH = 19200000 (19.2MHz)
> +  # @Prompt This PCD is the nominal frequency of the core crystal clock
> + in Hz as is CPUID Leaf 0x15:ECX
> +
> +
> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|U
> IN
> + T64|0x32132113
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
>    ## Specifies max supported number of Logical Processors.
>    # @Prompt Configure max supported number of Logical Processors diff --git
> a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> bf690d3978..e7dfe30eda 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -101,6 +101,9 @@
>    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
> 
> UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
>    UefiCpuPkg/Application/Cpuid/Cpuid.inf
> +  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> +  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> +  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> 
>  [Components.IA32, Components.X64]
>    UefiCpuPkg/CpuDxe/CpuDxe.inf
> diff --git a/UefiCpuPkg/UefiCpuPkg.uni b/UefiCpuPkg/UefiCpuPkg.uni index
> 80af4fc1d2..fbf7680726 100644
> --- a/UefiCpuPkg/UefiCpuPkg.uni
> +++ b/UefiCpuPkg/UefiCpuPkg.uni
> @@ -242,3 +242,13 @@
>  #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuKnownGoodStackSize_HELP
> #language en-US "Size of good stack for an exception.\n"
>                                                                                       "This PCD will only take into
> effect if PcdCpuStackGuard is enabled.\n"
> 
> +#string
> STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_PROM
> PT  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and
> Nominal Core Crystal Clock Frequency."
> +
> +#string
> STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_HELP
> #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal
> Core Crystal Clock Frequency.<BR><BR>\n"
> +                                                                                            "TSC Frequency = ECX (core
> crystal clock frequency) * EBX/EAX.<BR><BR>\n"
> +                                                                                            "This PCD is the nominal
> frequency of the core crystal clock in Hz as is CPUID Leaf
> 0x15:ECX.<BR><BR>\n"
> +                                                                                            "Default value is 24000000
> for 6th and 7th generation Intel Core processors and Intel Xeon W Processor
> Family.<BR>\n"
> +                                                                                            "25000000  -  Intel Xeon
> Processor Scalable Family with CPUID signature 06_55H(25MHz).<BR>\n"
> +                                                                                            "24000000  -  6th and 7th
> generation Intel Core processors and Intel Xeon W Processor
> Family(24MHz).<BR>\n"
> +                                                                                            "19200000  -  Intel Atom
> processors based on Goldmont Microarchitecture with CPUID signature
> 06_5CH(19.2MHz).<BR>\n"
> +
> --
> 2.14.2.windows.3


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-15  4:02     ` Liming Gao
  2019-08-15  4:40       ` Donald Kuo
@ 2019-08-16 16:16       ` Laszlo Ersek
  2019-08-16 20:40         ` Laszlo Ersek
  1 sibling, 1 reply; 27+ messages in thread
From: Laszlo Ersek @ 2019-08-16 16:16 UTC (permalink / raw)
  To: Gao, Liming, Kuo, Donald, Dong, Eric, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, leif.lindholm@linaro.org, afish@apple.com,
	Kinney, Michael D

On 08/15/19 06:02, Gao, Liming wrote:
> Donald: This change is a new feature. Now, it is not in edk2 feature
> planning list. If you want to catch it into 201908 stable tag, please
> get approve from Stewards first. I have cc this mail to all Stewards.
- I don't mind adding a new feature, as long as it gets properly
reviewed by package owners before we enter the soft feature freeze.

- Looking at the BZ
<https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit more
documentation would be nice.

- On the negative side, I'm very much *not* a fan of adding features to
the open source edk2 tree without actually *consuming* the feature in an
open source tree. Are the new library instances going to be put to use
in edk2-platforms, perhaps?

We discussed this topic earlier on some of the stewards' calls. On one
hand, it's not uncommon to see library instances from Intel enter core
edk2 packages without any dependent platform code, or even a detailed
problem statement / purpose description (see e.g. commit 5c9bb86f171c
and its surrounding commits). On the other hand, attempts in the past,
to add libraries with well demonstrated and direct in-tree use cases, to
edk2 core, have been rejected, from other submitters. (Here's one
example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.) I'm not
prying at proprietary platform information, but a new library added to
edk2 core *should* be well-justified.

The commit message on this patch is empty. It only references
<https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I open the
BZ, this is all I get:

    Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
    For new platform (start from SKL) can use CPUID and retire/remove
    the current override from AcpiTimerLib.

Does this read like an actual feature request? (TimerLib is an MdePkg
library class, so not exactly "niche".)

Plus, the BZ isn't even marked as a feature request, to begin with (the
Product field is wrong, it says "EDK2", which is for bugs, not
features). Also, the patch is on the list, and the status is still
CONFIRMED, and not IN_PROGRESS.

Why are we making a joke of bug tracking? The purpose of a public
bugzilla instance on the web is not just more red tape, not just to have
one more administrative tool that we can abuse, ignore, and write off
with make-believe actions.

It's not like another issue tracker system (JIRA, Launchpad, GitHub,
GitLab, you name it) would properly work with this level of neglect, either.

In summary: I don't mind the feature, but the documentation around it
should be *much* better.

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-16 16:16       ` Laszlo Ersek
@ 2019-08-16 20:40         ` Laszlo Ersek
  2019-08-20  2:43           ` Donald Kuo
  0 siblings, 1 reply; 27+ messages in thread
From: Laszlo Ersek @ 2019-08-16 20:40 UTC (permalink / raw)
  To: Gao, Liming, Kuo, Donald, Dong, Eric, devel@edk2.groups.io
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, leif.lindholm@linaro.org, afish@apple.com,
	Kinney, Michael D

On 08/16/19 18:16, Laszlo Ersek wrote:
> On 08/15/19 06:02, Gao, Liming wrote:
>> Donald: This change is a new feature. Now, it is not in edk2 feature
>> planning list. If you want to catch it into 201908 stable tag, please
>> get approve from Stewards first. I have cc this mail to all Stewards.
> - I don't mind adding a new feature, as long as it gets properly
> reviewed by package owners before we enter the soft feature freeze.
> 
> - Looking at the BZ
> <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit more
> documentation would be nice.
> 
> - On the negative side, I'm very much *not* a fan of adding features to
> the open source edk2 tree without actually *consuming* the feature in an
> open source tree. Are the new library instances going to be put to use
> in edk2-platforms, perhaps?
> 
> We discussed this topic earlier on some of the stewards' calls. On one
> hand, it's not uncommon to see library instances from Intel enter core
> edk2 packages without any dependent platform code, or even a detailed
> problem statement / purpose description (see e.g. commit 5c9bb86f171c
> and its surrounding commits). On the other hand, attempts in the past,
> to add libraries with well demonstrated and direct in-tree use cases, to
> edk2 core, have been rejected, from other submitters. (Here's one
> example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.) I'm not
> prying at proprietary platform information, but a new library added to
> edk2 core *should* be well-justified.
> 
> The commit message on this patch is empty. It only references
> <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I open the
> BZ, this is all I get:
> 
>     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
>     For new platform (start from SKL) can use CPUID and retire/remove
>     the current override from AcpiTimerLib.
> 
> Does this read like an actual feature request? (TimerLib is an MdePkg
> library class, so not exactly "niche".)

In comparison, the following email does read like a feature request:

[edk2-devel] Determining TSC frequency programmatically
https://edk2.groups.io/g/devel/message/45750
http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-4D641576D58E@protonmail.com

If the posting is related to TianoCore#1909, then I urge the BZ assignee to please reference the message in the TianoCore BZ.

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-16 20:40         ` Laszlo Ersek
@ 2019-08-20  2:43           ` Donald Kuo
  2019-08-20  6:51             ` Liming Gao
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-20  2:43 UTC (permalink / raw)
  To: devel@edk2.groups.io, lersek@redhat.com, Gao, Liming, Dong, Eric
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, leif.lindholm@linaro.org, afish@apple.com,
	Kinney, Michael D

Thanks Laszlo help to review and great feedbacks. That we did miss to fulfil BZ. 

I had updated Bugzilla https://bugzilla.tianocore.org/show_bug.cgi?id=1909 for more documentation.

As I know for the edk2-platforms should be consumed as KBL (7th Generation) platform in Client, and this feature based on SDM is supported on SKL (6th Generation, Family 06h) onwards. So it's ok to use as TimerLib instances for edk2-platforms.

And I think the library is new instances for TimerLib for supported CPU, and those non-supported CPU will still keep using AcpiTimerlib as TimerLib instances.

Thanks,
Donald

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Laszlo Ersek
> Sent: Saturday, August 17, 2019 4:40 AM
> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
> devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin
> Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> using CPUID(0x15) TSC leaf
> 
> On 08/16/19 18:16, Laszlo Ersek wrote:
> > On 08/15/19 06:02, Gao, Liming wrote:
> >> Donald: This change is a new feature. Now, it is not in edk2 feature
> >> planning list. If you want to catch it into 201908 stable tag, please
> >> get approve from Stewards first. I have cc this mail to all Stewards.
> > - I don't mind adding a new feature, as long as it gets properly
> > reviewed by package owners before we enter the soft feature freeze.
> >
> > - Looking at the BZ
> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit more
> > documentation would be nice.
> >
> > - On the negative side, I'm very much *not* a fan of adding features
> > to the open source edk2 tree without actually *consuming* the feature
> > in an open source tree. Are the new library instances going to be put
> > to use in edk2-platforms, perhaps?
> >
> > We discussed this topic earlier on some of the stewards' calls. On one
> > hand, it's not uncommon to see library instances from Intel enter core
> > edk2 packages without any dependent platform code, or even a detailed
> > problem statement / purpose description (see e.g. commit 5c9bb86f171c
> > and its surrounding commits). On the other hand, attempts in the past,
> > to add libraries with well demonstrated and direct in-tree use cases,
> > to
> > edk2 core, have been rejected, from other submitters. (Here's one
> > example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.) I'm
> > not prying at proprietary platform information, but a new library
> > added to
> > edk2 core *should* be well-justified.
> >
> > The commit message on this patch is empty. It only references
> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I open
> > the BZ, this is all I get:
> >
> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
> >     For new platform (start from SKL) can use CPUID and retire/remove
> >     the current override from AcpiTimerLib.
> >
> > Does this read like an actual feature request? (TimerLib is an MdePkg
> > library class, so not exactly "niche".)
> 
> In comparison, the following email does read like a feature request:
> 
> [edk2-devel] Determining TSC frequency programmatically
> https://edk2.groups.io/g/devel/message/45750
> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
> 4D641576D58E@protonmail.com
> 
> If the posting is related to TianoCore#1909, then I urge the BZ assignee to
> please reference the message in the TianoCore BZ.
> 
> Thanks
> Laszlo
> 
> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-20  2:43           ` Donald Kuo
@ 2019-08-20  6:51             ` Liming Gao
  2019-08-20  7:21               ` Donald Kuo
  0 siblings, 1 reply; 27+ messages in thread
From: Liming Gao @ 2019-08-20  6:51 UTC (permalink / raw)
  To: Kuo, Donald, devel@edk2.groups.io, lersek@redhat.com, Dong, Eric
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, leif.lindholm@linaro.org, afish@apple.com,
	Kinney, Michael D

Donald:
  Please also attach the patch linker in BZs. 

  And, please submit another BZ for edk2-platforms\Platform\Intel\KabylakeOpenBoardPkg to apply this new library instance. 

Thanks
Liming
>-----Original Message-----
>From: Kuo, Donald
>Sent: Tuesday, August 20, 2019 10:44 AM
>To: devel@edk2.groups.io; lersek@redhat.com; Gao, Liming
><liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>
>Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan, Amy
><amy.chan@intel.com>; Chaganty, Rangasai V
><rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin Y
><kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
>Michael D <michael.d.kinney@intel.com>
>Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
>using CPUID(0x15) TSC leaf
>
>Thanks Laszlo help to review and great feedbacks. That we did miss to fulfil BZ.
>
>I had updated Bugzilla https://bugzilla.tianocore.org/show_bug.cgi?id=1909
>for more documentation.
>
>As I know for the edk2-platforms should be consumed as KBL (7th Generation)
>platform in Client, and this feature based on SDM is supported on SKL (6th
>Generation, Family 06h) onwards. So it's ok to use as TimerLib instances for
>edk2-platforms.
>
>And I think the library is new instances for TimerLib for supported CPU, and
>those non-supported CPU will still keep using AcpiTimerlib as TimerLib
>instances.
>
>Thanks,
>Donald
>
>> -----Original Message-----
>> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
>> Laszlo Ersek
>> Sent: Saturday, August 17, 2019 4:40 AM
>> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
>> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
>> devel@edk2.groups.io
>> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
>> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
>> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin
>> Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com;
>Kinney,
>> Michael D <michael.d.kinney@intel.com>
>> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
>> using CPUID(0x15) TSC leaf
>>
>> On 08/16/19 18:16, Laszlo Ersek wrote:
>> > On 08/15/19 06:02, Gao, Liming wrote:
>> >> Donald: This change is a new feature. Now, it is not in edk2 feature
>> >> planning list. If you want to catch it into 201908 stable tag, please
>> >> get approve from Stewards first. I have cc this mail to all Stewards.
>> > - I don't mind adding a new feature, as long as it gets properly
>> > reviewed by package owners before we enter the soft feature freeze.
>> >
>> > - Looking at the BZ
>> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit more
>> > documentation would be nice.
>> >
>> > - On the negative side, I'm very much *not* a fan of adding features
>> > to the open source edk2 tree without actually *consuming* the feature
>> > in an open source tree. Are the new library instances going to be put
>> > to use in edk2-platforms, perhaps?
>> >
>> > We discussed this topic earlier on some of the stewards' calls. On one
>> > hand, it's not uncommon to see library instances from Intel enter core
>> > edk2 packages without any dependent platform code, or even a detailed
>> > problem statement / purpose description (see e.g. commit 5c9bb86f171c
>> > and its surrounding commits). On the other hand, attempts in the past,
>> > to add libraries with well demonstrated and direct in-tree use cases,
>> > to
>> > edk2 core, have been rejected, from other submitters. (Here's one
>> > example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.) I'm
>> > not prying at proprietary platform information, but a new library
>> > added to
>> > edk2 core *should* be well-justified.
>> >
>> > The commit message on this patch is empty. It only references
>> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I open
>> > the BZ, this is all I get:
>> >
>> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
>> >     For new platform (start from SKL) can use CPUID and retire/remove
>> >     the current override from AcpiTimerLib.
>> >
>> > Does this read like an actual feature request? (TimerLib is an MdePkg
>> > library class, so not exactly "niche".)
>>
>> In comparison, the following email does read like a feature request:
>>
>> [edk2-devel] Determining TSC frequency programmatically
>> https://edk2.groups.io/g/devel/message/45750
>> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
>> 4D641576D58E@protonmail.com
>>
>> If the posting is related to TianoCore#1909, then I urge the BZ assignee to
>> please reference the message in the TianoCore BZ.
>>
>> Thanks
>> Laszlo
>>
>> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-20  6:51             ` Liming Gao
@ 2019-08-20  7:21               ` Donald Kuo
  2019-08-20 11:56                 ` Liming Gao
  0 siblings, 1 reply; 27+ messages in thread
From: Donald Kuo @ 2019-08-20  7:21 UTC (permalink / raw)
  To: Gao, Liming, devel@edk2.groups.io, lersek@redhat.com, Dong, Eric
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, leif.lindholm@linaro.org, afish@apple.com,
	Kinney, Michael D

Hi Liming,

Done.

Patch is attached to https://bugzilla.tianocore.org/show_bug.cgi?id=1909

Another BZ to apply CpuTimerLib will be tracking on:  https://bugzilla.tianocore.org/show_bug.cgi?id=2096

Thanks,
Donald

> -----Original Message-----
> From: Gao, Liming
> Sent: Tuesday, August 20, 2019 2:51 PM
> To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin
> Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> using CPUID(0x15) TSC leaf
> 
> Donald:
>   Please also attach the patch linker in BZs.
> 
>   And, please submit another BZ for edk2-
> platforms\Platform\Intel\KabylakeOpenBoardPkg to apply this new library
> instance.
> 
> Thanks
> Liming
> >-----Original Message-----
> >From: Kuo, Donald
> >Sent: Tuesday, August 20, 2019 10:44 AM
> >To: devel@edk2.groups.io; lersek@redhat.com; Gao, Liming
> ><liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>
> >Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> >Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> ><rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> >Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> >afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> >Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> >by using CPUID(0x15) TSC leaf
> >
> >Thanks Laszlo help to review and great feedbacks. That we did miss to fulfil
> BZ.
> >
> >I had updated Bugzilla
> >https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> >for more documentation.
> >
> >As I know for the edk2-platforms should be consumed as KBL (7th
> >Generation) platform in Client, and this feature based on SDM is
> >supported on SKL (6th Generation, Family 06h) onwards. So it's ok to
> >use as TimerLib instances for edk2-platforms.
> >
> >And I think the library is new instances for TimerLib for supported
> >CPU, and those non-supported CPU will still keep using AcpiTimerlib as
> >TimerLib instances.
> >
> >Thanks,
> >Donald
> >
> >> -----Original Message-----
> >> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> >> Laszlo Ersek
> >> Sent: Saturday, August 17, 2019 4:40 AM
> >> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> >> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
> >> devel@edk2.groups.io
> >> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> >> Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> >> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> >> Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> >> afish@apple.com;
> >Kinney,
> >> Michael D <michael.d.kinney@intel.com>
> >> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> >> library by using CPUID(0x15) TSC leaf
> >>
> >> On 08/16/19 18:16, Laszlo Ersek wrote:
> >> > On 08/15/19 06:02, Gao, Liming wrote:
> >> >> Donald: This change is a new feature. Now, it is not in edk2
> >> >> feature planning list. If you want to catch it into 201908 stable
> >> >> tag, please get approve from Stewards first. I have cc this mail to all
> Stewards.
> >> > - I don't mind adding a new feature, as long as it gets properly
> >> > reviewed by package owners before we enter the soft feature freeze.
> >> >
> >> > - Looking at the BZ
> >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit more
> >> > documentation would be nice.
> >> >
> >> > - On the negative side, I'm very much *not* a fan of adding
> >> > features to the open source edk2 tree without actually *consuming*
> >> > the feature in an open source tree. Are the new library instances
> >> > going to be put to use in edk2-platforms, perhaps?
> >> >
> >> > We discussed this topic earlier on some of the stewards' calls. On
> >> > one hand, it's not uncommon to see library instances from Intel
> >> > enter core
> >> > edk2 packages without any dependent platform code, or even a
> >> > detailed problem statement / purpose description (see e.g. commit
> >> > 5c9bb86f171c and its surrounding commits). On the other hand,
> >> > attempts in the past, to add libraries with well demonstrated and
> >> > direct in-tree use cases, to
> >> > edk2 core, have been rejected, from other submitters. (Here's one
> >> > example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.) I'm
> >> > not prying at proprietary platform information, but a new library
> >> > added to
> >> > edk2 core *should* be well-justified.
> >> >
> >> > The commit message on this patch is empty. It only references
> >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I
> >> > open the BZ, this is all I get:
> >> >
> >> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
> >> >     For new platform (start from SKL) can use CPUID and retire/remove
> >> >     the current override from AcpiTimerLib.
> >> >
> >> > Does this read like an actual feature request? (TimerLib is an
> >> > MdePkg library class, so not exactly "niche".)
> >>
> >> In comparison, the following email does read like a feature request:
> >>
> >> [edk2-devel] Determining TSC frequency programmatically
> >> https://edk2.groups.io/g/devel/message/45750
> >> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
> >> 4D641576D58E@protonmail.com
> >>
> >> If the posting is related to TianoCore#1909, then I urge the BZ
> >> assignee to please reference the message in the TianoCore BZ.
> >>
> >> Thanks
> >> Laszlo
> >>
> >> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-20  7:21               ` Donald Kuo
@ 2019-08-20 11:56                 ` Liming Gao
  2019-08-20 14:00                   ` Zeng, Star
  0 siblings, 1 reply; 27+ messages in thread
From: Liming Gao @ 2019-08-20 11:56 UTC (permalink / raw)
  To: Kuo, Donald, devel@edk2.groups.io, lersek@redhat.com, Dong, Eric
  Cc: Ni, Ray, Zeng, Star, Chan, Amy, Chaganty, Rangasai V, Lai, Luke,
	Li, Kevin Y, leif.lindholm@linaro.org, afish@apple.com,
	Kinney, Michael D

Donald:
  Thanks for your update. If no other comment, I will help push this patch tomorrow. 

Thanks
Liming
> -----Original Message-----
> From: Kuo, Donald
> Sent: Tuesday, August 20, 2019 3:22 PM
> To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io; lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
> 
> Hi Liming,
> 
> Done.
> 
> Patch is attached to https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> 
> Another BZ to apply CpuTimerLib will be tracking on:  https://bugzilla.tianocore.org/show_bug.cgi?id=2096
> 
> Thanks,
> Donald
> 
> > -----Original Message-----
> > From: Gao, Liming
> > Sent: Tuesday, August 20, 2019 2:51 PM
> > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> > Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin
> > Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
> > Michael D <michael.d.kinney@intel.com>
> > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> > using CPUID(0x15) TSC leaf
> >
> > Donald:
> >   Please also attach the patch linker in BZs.
> >
> >   And, please submit another BZ for edk2-
> > platforms\Platform\Intel\KabylakeOpenBoardPkg to apply this new library
> > instance.
> >
> > Thanks
> > Liming
> > >-----Original Message-----
> > >From: Kuo, Donald
> > >Sent: Tuesday, August 20, 2019 10:44 AM
> > >To: devel@edk2.groups.io; lersek@redhat.com; Gao, Liming
> > ><liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>
> > >Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan,
> > >Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > ><rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > >Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > >afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > >Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> > >by using CPUID(0x15) TSC leaf
> > >
> > >Thanks Laszlo help to review and great feedbacks. That we did miss to fulfil
> > BZ.
> > >
> > >I had updated Bugzilla
> > >https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > >for more documentation.
> > >
> > >As I know for the edk2-platforms should be consumed as KBL (7th
> > >Generation) platform in Client, and this feature based on SDM is
> > >supported on SKL (6th Generation, Family 06h) onwards. So it's ok to
> > >use as TimerLib instances for edk2-platforms.
> > >
> > >And I think the library is new instances for TimerLib for supported
> > >CPU, and those non-supported CPU will still keep using AcpiTimerlib as
> > >TimerLib instances.
> > >
> > >Thanks,
> > >Donald
> > >
> > >> -----Original Message-----
> > >> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > >> Laszlo Ersek
> > >> Sent: Saturday, August 17, 2019 4:40 AM
> > >> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> > >> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
> > >> devel@edk2.groups.io
> > >> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > >> Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > >> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > >> Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > >> afish@apple.com;
> > >Kinney,
> > >> Michael D <michael.d.kinney@intel.com>
> > >> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > >> library by using CPUID(0x15) TSC leaf
> > >>
> > >> On 08/16/19 18:16, Laszlo Ersek wrote:
> > >> > On 08/15/19 06:02, Gao, Liming wrote:
> > >> >> Donald: This change is a new feature. Now, it is not in edk2
> > >> >> feature planning list. If you want to catch it into 201908 stable
> > >> >> tag, please get approve from Stewards first. I have cc this mail to all
> > Stewards.
> > >> > - I don't mind adding a new feature, as long as it gets properly
> > >> > reviewed by package owners before we enter the soft feature freeze.
> > >> >
> > >> > - Looking at the BZ
> > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit more
> > >> > documentation would be nice.
> > >> >
> > >> > - On the negative side, I'm very much *not* a fan of adding
> > >> > features to the open source edk2 tree without actually *consuming*
> > >> > the feature in an open source tree. Are the new library instances
> > >> > going to be put to use in edk2-platforms, perhaps?
> > >> >
> > >> > We discussed this topic earlier on some of the stewards' calls. On
> > >> > one hand, it's not uncommon to see library instances from Intel
> > >> > enter core
> > >> > edk2 packages without any dependent platform code, or even a
> > >> > detailed problem statement / purpose description (see e.g. commit
> > >> > 5c9bb86f171c and its surrounding commits). On the other hand,
> > >> > attempts in the past, to add libraries with well demonstrated and
> > >> > direct in-tree use cases, to
> > >> > edk2 core, have been rejected, from other submitters. (Here's one
> > >> > example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.) I'm
> > >> > not prying at proprietary platform information, but a new library
> > >> > added to
> > >> > edk2 core *should* be well-justified.
> > >> >
> > >> > The commit message on this patch is empty. It only references
> > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I
> > >> > open the BZ, this is all I get:
> > >> >
> > >> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
> > >> >     For new platform (start from SKL) can use CPUID and retire/remove
> > >> >     the current override from AcpiTimerLib.
> > >> >
> > >> > Does this read like an actual feature request? (TimerLib is an
> > >> > MdePkg library class, so not exactly "niche".)
> > >>
> > >> In comparison, the following email does read like a feature request:
> > >>
> > >> [edk2-devel] Determining TSC frequency programmatically
> > >> https://edk2.groups.io/g/devel/message/45750
> > >> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
> > >> 4D641576D58E@protonmail.com
> > >>
> > >> If the posting is related to TianoCore#1909, then I urge the BZ
> > >> assignee to please reference the message in the TianoCore BZ.
> > >>
> > >> Thanks
> > >> Laszlo
> > >>
> > >> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-20 11:56                 ` Liming Gao
@ 2019-08-20 14:00                   ` Zeng, Star
  2019-08-21 13:45                     ` Liming Gao
  0 siblings, 1 reply; 27+ messages in thread
From: Zeng, Star @ 2019-08-20 14:00 UTC (permalink / raw)
  To: Gao, Liming, Kuo, Donald, devel@edk2.groups.io, lersek@redhat.com,
	Dong, Eric
  Cc: Ni, Ray, Chan, Amy, Chaganty, Rangasai V, Lai, Luke, Li, Kevin Y,
	leif.lindholm@linaro.org, afish@apple.com, Kinney, Michael D,
	Zeng, Star

Remember to add entry for it at https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-Planning.

> -----Original Message-----
> From: Gao, Liming
> Sent: Tuesday, August 20, 2019 7:56 PM
> To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan, Amy
> <amy.chan@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin Y
> <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> using CPUID(0x15) TSC leaf
> 
> Donald:
>   Thanks for your update. If no other comment, I will help push this patch
> tomorrow.
> 
> Thanks
> Liming
> > -----Original Message-----
> > From: Kuo, Donald
> > Sent: Tuesday, August 20, 2019 3:22 PM
> > To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io;
> > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> > by using CPUID(0x15) TSC leaf
> >
> > Hi Liming,
> >
> > Done.
> >
> > Patch is attached to
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> >
> > Another BZ to apply CpuTimerLib will be tracking on:
> > https://bugzilla.tianocore.org/show_bug.cgi?id=2096
> >
> > Thanks,
> > Donald
> >
> > > -----Original Message-----
> > > From: Gao, Liming
> > > Sent: Tuesday, August 20, 2019 2:51 PM
> > > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> > > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > > Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > library by using CPUID(0x15) TSC leaf
> > >
> > > Donald:
> > >   Please also attach the patch linker in BZs.
> > >
> > >   And, please submit another BZ for edk2-
> > > platforms\Platform\Intel\KabylakeOpenBoardPkg to apply this new
> > > library instance.
> > >
> > > Thanks
> > > Liming
> > > >-----Original Message-----
> > > >From: Kuo, Donald
> > > >Sent: Tuesday, August 20, 2019 10:44 AM
> > > >To: devel@edk2.groups.io; lersek@redhat.com; Gao, Liming
> > > ><liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>
> > > >Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > >Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > ><rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>;
> > > >Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > >afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > >Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > >library by using CPUID(0x15) TSC leaf
> > > >
> > > >Thanks Laszlo help to review and great feedbacks. That we did miss
> > > >to fulfil
> > > BZ.
> > > >
> > > >I had updated Bugzilla
> > > >https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > > >for more documentation.
> > > >
> > > >As I know for the edk2-platforms should be consumed as KBL (7th
> > > >Generation) platform in Client, and this feature based on SDM is
> > > >supported on SKL (6th Generation, Family 06h) onwards. So it's ok
> > > >to use as TimerLib instances for edk2-platforms.
> > > >
> > > >And I think the library is new instances for TimerLib for supported
> > > >CPU, and those non-supported CPU will still keep using AcpiTimerlib
> > > >as TimerLib instances.
> > > >
> > > >Thanks,
> > > >Donald
> > > >
> > > >> -----Original Message-----
> > > >> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On
> > > >> Behalf Of Laszlo Ersek
> > > >> Sent: Saturday, August 17, 2019 4:40 AM
> > > >> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> > > >> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
> > > >> devel@edk2.groups.io
> > > >> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > >> Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > >> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>;
> > > >> Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > >> afish@apple.com;
> > > >Kinney,
> > > >> Michael D <michael.d.kinney@intel.com>
> > > >> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > >> library by using CPUID(0x15) TSC leaf
> > > >>
> > > >> On 08/16/19 18:16, Laszlo Ersek wrote:
> > > >> > On 08/15/19 06:02, Gao, Liming wrote:
> > > >> >> Donald: This change is a new feature. Now, it is not in edk2
> > > >> >> feature planning list. If you want to catch it into 201908
> > > >> >> stable tag, please get approve from Stewards first. I have cc
> > > >> >> this mail to all
> > > Stewards.
> > > >> > - I don't mind adding a new feature, as long as it gets
> > > >> > properly reviewed by package owners before we enter the soft
> feature freeze.
> > > >> >
> > > >> > - Looking at the BZ
> > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit
> > > >> > more documentation would be nice.
> > > >> >
> > > >> > - On the negative side, I'm very much *not* a fan of adding
> > > >> > features to the open source edk2 tree without actually
> > > >> > *consuming* the feature in an open source tree. Are the new
> > > >> > library instances going to be put to use in edk2-platforms, perhaps?
> > > >> >
> > > >> > We discussed this topic earlier on some of the stewards' calls.
> > > >> > On one hand, it's not uncommon to see library instances from
> > > >> > Intel enter core
> > > >> > edk2 packages without any dependent platform code, or even a
> > > >> > detailed problem statement / purpose description (see e.g.
> > > >> > commit 5c9bb86f171c and its surrounding commits). On the other
> > > >> > hand, attempts in the past, to add libraries with well
> > > >> > demonstrated and direct in-tree use cases, to
> > > >> > edk2 core, have been rejected, from other submitters. (Here's
> > > >> > one
> > > >> > example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.)
> > > >> > I'm not prying at proprietary platform information, but a new
> > > >> > library added to
> > > >> > edk2 core *should* be well-justified.
> > > >> >
> > > >> > The commit message on this patch is empty. It only references
> > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I
> > > >> > open the BZ, this is all I get:
> > > >> >
> > > >> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
> > > >> >     For new platform (start from SKL) can use CPUID and
> retire/remove
> > > >> >     the current override from AcpiTimerLib.
> > > >> >
> > > >> > Does this read like an actual feature request? (TimerLib is an
> > > >> > MdePkg library class, so not exactly "niche".)
> > > >>
> > > >> In comparison, the following email does read like a feature request:
> > > >>
> > > >> [edk2-devel] Determining TSC frequency programmatically
> > > >> https://edk2.groups.io/g/devel/message/45750
> > > >> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
> > > >> 4D641576D58E@protonmail.com
> > > >>
> > > >> If the posting is related to TianoCore#1909, then I urge the BZ
> > > >> assignee to please reference the message in the TianoCore BZ.
> > > >>
> > > >> Thanks
> > > >> Laszlo
> > > >>
> > > >> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-20 14:00                   ` Zeng, Star
@ 2019-08-21 13:45                     ` Liming Gao
  2019-08-21 14:54                       ` Donald Kuo
  0 siblings, 1 reply; 27+ messages in thread
From: Liming Gao @ 2019-08-21 13:45 UTC (permalink / raw)
  To: Zeng, Star, Kuo, Donald, devel@edk2.groups.io, lersek@redhat.com,
	Dong, Eric
  Cc: Ni, Ray, Chan, Amy, Chaganty, Rangasai V, Lai, Luke, Li, Kevin Y,
	leif.lindholm@linaro.org, afish@apple.com, Kinney, Michael D

Done. And, push @30781febe2106cc0d7186e70136120353cd67df2

Thanks
Liming
> -----Original Message-----
> From: Zeng, Star
> Sent: Tuesday, August 20, 2019 10:00 PM
> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io; lersek@redhat.com; Dong, Eric
> <eric.dong@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Lai, Luke
> <luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney, Michael D
> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
> 
> Remember to add entry for it at https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-Planning.
> 
> > -----Original Message-----
> > From: Gao, Liming
> > Sent: Tuesday, August 20, 2019 7:56 PM
> > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Chan, Amy
> > <amy.chan@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li, Kevin Y
> > <kevin.y.li@intel.com>; leif.lindholm@linaro.org; afish@apple.com; Kinney,
> > Michael D <michael.d.kinney@intel.com>
> > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> > using CPUID(0x15) TSC leaf
> >
> > Donald:
> >   Thanks for your update. If no other comment, I will help push this patch
> > tomorrow.
> >
> > Thanks
> > Liming
> > > -----Original Message-----
> > > From: Kuo, Donald
> > > Sent: Tuesday, August 20, 2019 3:22 PM
> > > To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io;
> > > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > > Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> > > by using CPUID(0x15) TSC leaf
> > >
> > > Hi Liming,
> > >
> > > Done.
> > >
> > > Patch is attached to
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > >
> > > Another BZ to apply CpuTimerLib will be tracking on:
> > > https://bugzilla.tianocore.org/show_bug.cgi?id=2096
> > >
> > > Thanks,
> > > Donald
> > >
> > > > -----Original Message-----
> > > > From: Gao, Liming
> > > > Sent: Tuesday, August 20, 2019 2:51 PM
> > > > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> > > > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > > > Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > > afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > > library by using CPUID(0x15) TSC leaf
> > > >
> > > > Donald:
> > > >   Please also attach the patch linker in BZs.
> > > >
> > > >   And, please submit another BZ for edk2-
> > > > platforms\Platform\Intel\KabylakeOpenBoardPkg to apply this new
> > > > library instance.
> > > >
> > > > Thanks
> > > > Liming
> > > > >-----Original Message-----
> > > > >From: Kuo, Donald
> > > > >Sent: Tuesday, August 20, 2019 10:44 AM
> > > > >To: devel@edk2.groups.io; lersek@redhat.com; Gao, Liming
> > > > ><liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>
> > > > >Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > > >Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > > ><rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>;
> > > > >Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > > >afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > > >Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > > >library by using CPUID(0x15) TSC leaf
> > > > >
> > > > >Thanks Laszlo help to review and great feedbacks. That we did miss
> > > > >to fulfil
> > > > BZ.
> > > > >
> > > > >I had updated Bugzilla
> > > > >https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > > > >for more documentation.
> > > > >
> > > > >As I know for the edk2-platforms should be consumed as KBL (7th
> > > > >Generation) platform in Client, and this feature based on SDM is
> > > > >supported on SKL (6th Generation, Family 06h) onwards. So it's ok
> > > > >to use as TimerLib instances for edk2-platforms.
> > > > >
> > > > >And I think the library is new instances for TimerLib for supported
> > > > >CPU, and those non-supported CPU will still keep using AcpiTimerlib
> > > > >as TimerLib instances.
> > > > >
> > > > >Thanks,
> > > > >Donald
> > > > >
> > > > >> -----Original Message-----
> > > > >> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On
> > > > >> Behalf Of Laszlo Ersek
> > > > >> Sent: Saturday, August 17, 2019 4:40 AM
> > > > >> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> > > > >> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
> > > > >> devel@edk2.groups.io
> > > > >> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > > >> Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > > >> <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>;
> > > > >> Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > > >> afish@apple.com;
> > > > >Kinney,
> > > > >> Michael D <michael.d.kinney@intel.com>
> > > > >> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > > >> library by using CPUID(0x15) TSC leaf
> > > > >>
> > > > >> On 08/16/19 18:16, Laszlo Ersek wrote:
> > > > >> > On 08/15/19 06:02, Gao, Liming wrote:
> > > > >> >> Donald: This change is a new feature. Now, it is not in edk2
> > > > >> >> feature planning list. If you want to catch it into 201908
> > > > >> >> stable tag, please get approve from Stewards first. I have cc
> > > > >> >> this mail to all
> > > > Stewards.
> > > > >> > - I don't mind adding a new feature, as long as it gets
> > > > >> > properly reviewed by package owners before we enter the soft
> > feature freeze.
> > > > >> >
> > > > >> > - Looking at the BZ
> > > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a bit
> > > > >> > more documentation would be nice.
> > > > >> >
> > > > >> > - On the negative side, I'm very much *not* a fan of adding
> > > > >> > features to the open source edk2 tree without actually
> > > > >> > *consuming* the feature in an open source tree. Are the new
> > > > >> > library instances going to be put to use in edk2-platforms, perhaps?
> > > > >> >
> > > > >> > We discussed this topic earlier on some of the stewards' calls.
> > > > >> > On one hand, it's not uncommon to see library instances from
> > > > >> > Intel enter core
> > > > >> > edk2 packages without any dependent platform code, or even a
> > > > >> > detailed problem statement / purpose description (see e.g.
> > > > >> > commit 5c9bb86f171c and its surrounding commits). On the other
> > > > >> > hand, attempts in the past, to add libraries with well
> > > > >> > demonstrated and direct in-tree use cases, to
> > > > >> > edk2 core, have been rejected, from other submitters. (Here's
> > > > >> > one
> > > > >> > example: <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.)
> > > > >> > I'm not prying at proprietary platform information, but a new
> > > > >> > library added to
> > > > >> > edk2 core *should* be well-justified.
> > > > >> >
> > > > >> > The commit message on this patch is empty. It only references
> > > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I
> > > > >> > open the BZ, this is all I get:
> > > > >> >
> > > > >> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for TSC.
> > > > >> >     For new platform (start from SKL) can use CPUID and
> > retire/remove
> > > > >> >     the current override from AcpiTimerLib.
> > > > >> >
> > > > >> > Does this read like an actual feature request? (TimerLib is an
> > > > >> > MdePkg library class, so not exactly "niche".)
> > > > >>
> > > > >> In comparison, the following email does read like a feature request:
> > > > >>
> > > > >> [edk2-devel] Determining TSC frequency programmatically
> > > > >> https://edk2.groups.io/g/devel/message/45750
> > > > >> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
> > > > >> 4D641576D58E@protonmail.com
> > > > >>
> > > > >> If the posting is related to TianoCore#1909, then I urge the BZ
> > > > >> assignee to please reference the message in the TianoCore BZ.
> > > > >>
> > > > >> Thanks
> > > > >> Laszlo
> > > > >>
> > > > >> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
  2019-08-21 13:45                     ` Liming Gao
@ 2019-08-21 14:54                       ` Donald Kuo
  0 siblings, 0 replies; 27+ messages in thread
From: Donald Kuo @ 2019-08-21 14:54 UTC (permalink / raw)
  To: Gao, Liming, Zeng, Star, devel@edk2.groups.io, lersek@redhat.com,
	Dong, Eric
  Cc: Ni, Ray, Chan, Amy, Chaganty, Rangasai V, Lai, Luke, Li, Kevin Y,
	leif.lindholm@linaro.org, afish@apple.com, Kinney, Michael D

Thanks Liming help :)

Donald
> -----Original Message-----
> From: Gao, Liming
> Sent: Wednesday, August 21, 2019 9:46 PM
> To: Zeng, Star <star.zeng@intel.com>; Kuo, Donald <donald.kuo@intel.com>;
> devel@edk2.groups.io; lersek@redhat.com; Dong, Eric
> <eric.dong@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Chan, Amy <amy.chan@intel.com>;
> Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Lai, Luke
> <luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>;
> leif.lindholm@linaro.org; afish@apple.com; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library by
> using CPUID(0x15) TSC leaf
> 
> Done. And, push @30781febe2106cc0d7186e70136120353cd67df2
> 
> Thanks
> Liming
> > -----Original Message-----
> > From: Zeng, Star
> > Sent: Tuesday, August 20, 2019 10:00 PM
> > To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> > <donald.kuo@intel.com>; devel@edk2.groups.io; lersek@redhat.com;
> Dong,
> > Eric <eric.dong@intel.com>
> > Cc: Ni, Ray <ray.ni@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Lai, Luke
> > <luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>;
> > leif.lindholm@linaro.org; afish@apple.com; Kinney, Michael D
> > <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC library
> > by using CPUID(0x15) TSC leaf
> >
> > Remember to add entry for it at
> https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-
> Planning.
> >
> > > -----Original Message-----
> > > From: Gao, Liming
> > > Sent: Tuesday, August 20, 2019 7:56 PM
> > > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> > > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>; Li,
> > > Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > library by using CPUID(0x15) TSC leaf
> > >
> > > Donald:
> > >   Thanks for your update. If no other comment, I will help push this
> > > patch tomorrow.
> > >
> > > Thanks
> > > Liming
> > > > -----Original Message-----
> > > > From: Kuo, Donald
> > > > Sent: Tuesday, August 20, 2019 3:22 PM
> > > > To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io;
> > > > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>;
> > > > Chan, Amy <amy.chan@intel.com>; Chaganty, Rangasai V
> > > > <rangasai.v.chaganty@intel.com>; Lai, Luke <luke.lai@intel.com>;
> > > > Li, Kevin Y <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > > afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>
> > > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > > library by using CPUID(0x15) TSC leaf
> > > >
> > > > Hi Liming,
> > > >
> > > > Done.
> > > >
> > > > Patch is attached to
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > > >
> > > > Another BZ to apply CpuTimerLib will be tracking on:
> > > > https://bugzilla.tianocore.org/show_bug.cgi?id=2096
> > > >
> > > > Thanks,
> > > > Donald
> > > >
> > > > > -----Original Message-----
> > > > > From: Gao, Liming
> > > > > Sent: Tuesday, August 20, 2019 2:51 PM
> > > > > To: Kuo, Donald <donald.kuo@intel.com>; devel@edk2.groups.io;
> > > > > lersek@redhat.com; Dong, Eric <eric.dong@intel.com>
> > > > > Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star
> > > > > <star.zeng@intel.com>; Chan, Amy <amy.chan@intel.com>;
> Chaganty,
> > > > > Rangasai V <rangasai.v.chaganty@intel.com>; Lai, Luke
> > > > > <luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>;
> > > > > leif.lindholm@linaro.org; afish@apple.com; Kinney, Michael D
> > > > > <michael.d.kinney@intel.com>
> > > > > Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > > > library by using CPUID(0x15) TSC leaf
> > > > >
> > > > > Donald:
> > > > >   Please also attach the patch linker in BZs.
> > > > >
> > > > >   And, please submit another BZ for edk2-
> > > > > platforms\Platform\Intel\KabylakeOpenBoardPkg to apply this new
> > > > > library instance.
> > > > >
> > > > > Thanks
> > > > > Liming
> > > > > >-----Original Message-----
> > > > > >From: Kuo, Donald
> > > > > >Sent: Tuesday, August 20, 2019 10:44 AM
> > > > > >To: devel@edk2.groups.io; lersek@redhat.com; Gao, Liming
> > > > > ><liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>
> > > > > >Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star
> > > > > ><star.zeng@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > > > > >Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Lai, Luke
> > > > > ><luke.lai@intel.com>; Li, Kevin Y <kevin.y.li@intel.com>;
> > > > > >leif.lindholm@linaro.org; afish@apple.com; Kinney, Michael D
> > > > > ><michael.d.kinney@intel.com>
> > > > > >Subject: RE: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new TSC
> > > > > >library by using CPUID(0x15) TSC leaf
> > > > > >
> > > > > >Thanks Laszlo help to review and great feedbacks. That we did
> > > > > >miss to fulfil
> > > > > BZ.
> > > > > >
> > > > > >I had updated Bugzilla
> > > > > >https://bugzilla.tianocore.org/show_bug.cgi?id=1909
> > > > > >for more documentation.
> > > > > >
> > > > > >As I know for the edk2-platforms should be consumed as KBL (7th
> > > > > >Generation) platform in Client, and this feature based on SDM
> > > > > >is supported on SKL (6th Generation, Family 06h) onwards. So
> > > > > >it's ok to use as TimerLib instances for edk2-platforms.
> > > > > >
> > > > > >And I think the library is new instances for TimerLib for
> > > > > >supported CPU, and those non-supported CPU will still keep
> > > > > >using AcpiTimerlib as TimerLib instances.
> > > > > >
> > > > > >Thanks,
> > > > > >Donald
> > > > > >
> > > > > >> -----Original Message-----
> > > > > >> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On
> > > > > >> Behalf Of Laszlo Ersek
> > > > > >> Sent: Saturday, August 17, 2019 4:40 AM
> > > > > >> To: Gao, Liming <liming.gao@intel.com>; Kuo, Donald
> > > > > >> <donald.kuo@intel.com>; Dong, Eric <eric.dong@intel.com>;
> > > > > >> devel@edk2.groups.io
> > > > > >> Cc: Ni, Ray <ray.ni@intel.com>; Zeng, Star
> > > > > >> <star.zeng@intel.com>; Chan, Amy <amy.chan@intel.com>;
> > > > > >> Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Lai,
> > > > > >> Luke <luke.lai@intel.com>; Li, Kevin Y
> > > > > >> <kevin.y.li@intel.com>; leif.lindholm@linaro.org;
> > > > > >> afish@apple.com;
> > > > > >Kinney,
> > > > > >> Michael D <michael.d.kinney@intel.com>
> > > > > >> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg: Adding a new
> > > > > >> TSC library by using CPUID(0x15) TSC leaf
> > > > > >>
> > > > > >> On 08/16/19 18:16, Laszlo Ersek wrote:
> > > > > >> > On 08/15/19 06:02, Gao, Liming wrote:
> > > > > >> >> Donald: This change is a new feature. Now, it is not in
> > > > > >> >> edk2 feature planning list. If you want to catch it into
> > > > > >> >> 201908 stable tag, please get approve from Stewards first.
> > > > > >> >> I have cc this mail to all
> > > > > Stewards.
> > > > > >> > - I don't mind adding a new feature, as long as it gets
> > > > > >> > properly reviewed by package owners before we enter the
> > > > > >> > soft
> > > feature freeze.
> > > > > >> >
> > > > > >> > - Looking at the BZ
> > > > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>, a
> > > > > >> > bit more documentation would be nice.
> > > > > >> >
> > > > > >> > - On the negative side, I'm very much *not* a fan of adding
> > > > > >> > features to the open source edk2 tree without actually
> > > > > >> > *consuming* the feature in an open source tree. Are the new
> > > > > >> > library instances going to be put to use in edk2-platforms,
> perhaps?
> > > > > >> >
> > > > > >> > We discussed this topic earlier on some of the stewards' calls.
> > > > > >> > On one hand, it's not uncommon to see library instances
> > > > > >> > from Intel enter core
> > > > > >> > edk2 packages without any dependent platform code, or even
> > > > > >> > a detailed problem statement / purpose description (see e.g.
> > > > > >> > commit 5c9bb86f171c and its surrounding commits). On the
> > > > > >> > other hand, attempts in the past, to add libraries with
> > > > > >> > well demonstrated and direct in-tree use cases, to
> > > > > >> > edk2 core, have been rejected, from other submitters.
> > > > > >> > (Here's one
> > > > > >> > example:
> > > > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=957>.)
> > > > > >> > I'm not prying at proprietary platform information, but a
> > > > > >> > new library added to
> > > > > >> > edk2 core *should* be well-justified.
> > > > > >> >
> > > > > >> > The commit message on this patch is empty. It only
> > > > > >> > references
> > > > > >> > <https://bugzilla.tianocore.org/show_bug.cgi?id=1909>. And if I
> open the BZ, this is all I get:
> > > > > >> >
> > > > > >> >     Need a new TSC library to check the CPUID leaf (EAX=0x15) for
> TSC.
> > > > > >> >     For new platform (start from SKL) can use CPUID and
> > > retire/remove
> > > > > >> >     the current override from AcpiTimerLib.
> > > > > >> >
> > > > > >> > Does this read like an actual feature request? (TimerLib is
> > > > > >> > an MdePkg library class, so not exactly "niche".)
> > > > > >>
> > > > > >> In comparison, the following email does read like a feature request:
> > > > > >>
> > > > > >> [edk2-devel] Determining TSC frequency programmatically
> > > > > >> https://edk2.groups.io/g/devel/message/45750
> > > > > >> http://mid.mail-archive.com/8EC14D0D-DFA5-412D-A4E1-
> > > > > >> 4D641576D58E@protonmail.com
> > > > > >>
> > > > > >> If the posting is related to TianoCore#1909, then I urge the
> > > > > >> BZ assignee to please reference the message in the TianoCore BZ.
> > > > > >>
> > > > > >> Thanks
> > > > > >> Laszlo
> > > > > >>
> > > > > >> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2019-08-21 14:54 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-08-13 10:53 [PATCH] UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf Donald Kuo
2019-08-15  2:45 ` [edk2-devel] " Dong, Eric
2019-08-15  3:02   ` Donald Kuo
2019-08-15  4:02     ` Liming Gao
2019-08-15  4:40       ` Donald Kuo
2019-08-16 16:16       ` Laszlo Ersek
2019-08-16 20:40         ` Laszlo Ersek
2019-08-20  2:43           ` Donald Kuo
2019-08-20  6:51             ` Liming Gao
2019-08-20  7:21               ` Donald Kuo
2019-08-20 11:56                 ` Liming Gao
2019-08-20 14:00                   ` Zeng, Star
2019-08-21 13:45                     ` Liming Gao
2019-08-21 14:54                       ` Donald Kuo
  -- strict thread matches above, loose matches on Subject: below --
2019-08-15  9:11 Donald Kuo
2019-08-16  4:27 ` Dong, Eric
2019-08-15  4:37 Donald Kuo
2019-08-12 11:23 Donald Kuo
2019-08-13  2:26 ` Dong, Eric
2019-08-13  3:26   ` Donald Kuo
2019-08-13  5:45     ` Dong, Eric
2019-08-12 11:03 Donald Kuo
2019-08-12  5:56 Donald Kuo
2019-08-12 10:26 ` Zeng, Star
2019-08-12  5:42 Donald Kuo
2019-08-12  5:24 Donald Kuo
2019-08-12  5:14 Donald Kuo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox