]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg: Adding a new TSC library by using CPUID(0x15) TSC leaf
authorDonald Kuo <donald.kuo@intel.com>
Mon, 12 Aug 2019 04:34:39 +0000 (12:34 +0800)
committerLiming Gao <liming.gao@intel.com>
Wed, 21 Aug 2019 13:36:56 +0000 (21:36 +0800)
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>
Reviewed-by: Eric Dong <eric.dong@intel.com>
13 files changed:
UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf [new file with mode: 0644]
UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni [new file with mode: 0644]
UefiCpuPkg/UefiCpuPkg.dec
UefiCpuPkg/UefiCpuPkg.dsc
UefiCpuPkg/UefiCpuPkg.uni

diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.c
new file mode 100644 (file)
index 0000000..6ddf917
--- /dev/null
@@ -0,0 +1,41 @@
+/** @file\r
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as Base Timer Library.\r
+\r
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+\r
+/**\r
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.\r
+\r
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.\r
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+CpuidCoreClockCalculateTscFrequency (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+InternalGetPerformanceCounterFrequency (\r
+  VOID\r
+  )\r
+{\r
+  return CpuidCoreClockCalculateTscFrequency ();\r
+}\r
+\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
new file mode 100644 (file)
index 0000000..fd93adc
--- /dev/null
@@ -0,0 +1,35 @@
+## @file\r
+#  Base CPU Timer Library\r
+#\r
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance\r
+#  counter features are provided by the processors time stamp counter.\r
+#\r
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BaseCpuTimerLib\r
+  FILE_GUID                      = F10B5B91-D15A-496C-B044-B5235721AA08\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib|SEC PEI_CORE PEIM\r
+  MODULE_UNI_FILE                = BaseCpuTimerLib.uni\r
+\r
+[Sources]\r
+  CpuTimerLib.c\r
+  BaseCpuTimerLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  PcdLib\r
+  DebugLib\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.uni
new file mode 100644 (file)
index 0000000..fcf2b0f
--- /dev/null
@@ -0,0 +1,17 @@
+// /** @file\r
+// Base CPU Timer Library\r
+//\r
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance\r
+// counter features are provided by the processors time stamp counter.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."\r
+\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c
new file mode 100644 (file)
index 0000000..192a401
--- /dev/null
@@ -0,0 +1,279 @@
+/** @file\r
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.\r
+\r
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Register/Cpuid.h>\r
+\r
+GUID mCpuCrystalFrequencyHobGuid = { 0xe1ec5ad0, 0x8569, 0x46bd, { 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a } };\r
+\r
+/**\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+InternalGetPerformanceCounterFrequency (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.\r
+\r
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.\r
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+CpuidCoreClockCalculateTscFrequency (\r
+  VOID\r
+  )\r
+{\r
+  UINT64                 TscFrequency;\r
+  UINT64                 CoreXtalFrequency;\r
+  UINT32                 RegEax;\r
+  UINT32                 RegEbx;\r
+  UINT32                 RegEcx;\r
+\r
+  //\r
+  // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information\r
+  // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.\r
+  // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.\r
+  //\r
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);\r
+\r
+  //\r
+  // If EAX or EBX returns 0, the XTAL ratio is not enumerated.\r
+  //\r
+  if (RegEax == 0 || RegEbx ==0 ) {\r
+    ASSERT (RegEax != 0);\r
+    ASSERT (RegEbx != 0);\r
+    return 0;\r
+  }\r
+  //\r
+  // If ECX returns 0, the XTAL frequency is not enumerated.\r
+  // And PcdCpuCoreCrystalClockFrequency defined should base on processor series.\r
+  //\r
+  if (RegEcx == 0) {\r
+    CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);\r
+  } else {\r
+    CoreXtalFrequency = (UINT64) RegEcx;\r
+  }\r
+\r
+  //\r
+  // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX\r
+  //\r
+  TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);\r
+\r
+  return TscFrequency;\r
+}\r
+\r
+/**\r
+  Stalls the CPU for at least the given number of ticks.\r
+\r
+  Stalls the CPU for at least the given number of ticks. It's invoked by\r
+  MicroSecondDelay() and NanoSecondDelay().\r
+\r
+  @param  Delay     A period of time to delay in ticks.\r
+\r
+**/\r
+VOID\r
+InternalCpuDelay (\r
+  IN UINT64  Delay\r
+  )\r
+{\r
+  UINT64  Ticks;\r
+\r
+  //\r
+  // The target timer count is calculated here\r
+  //\r
+  Ticks = AsmReadTsc() + Delay;\r
+\r
+  //\r
+  // Wait until time out\r
+  // Timer wrap-arounds are NOT handled correctly by this function.\r
+  // Thus, this function must be called within 10 years of reset since\r
+  // Intel guarantees a minimum of 10 years before the TSC wraps.\r
+  //\r
+  while (AsmReadTsc() <= Ticks) {\r
+    CpuPause();\r
+  }\r
+}\r
+\r
+/**\r
+  Stalls the CPU for at least the given number of microseconds.\r
+\r
+  Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
+\r
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.\r
+\r
+  @return MicroSeconds\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+MicroSecondDelay (\r
+  IN UINTN  MicroSeconds\r
+  )\r
+{\r
+\r
+  InternalCpuDelay (\r
+    DivU64x32 (\r
+      MultU64x64 (\r
+        MicroSeconds,\r
+        InternalGetPerformanceCounterFrequency ()\r
+        ),\r
+      1000000u\r
+    )\r
+  );\r
+\r
+  return MicroSeconds;\r
+}\r
+\r
+/**\r
+  Stalls the CPU for at least the given number of nanoseconds.\r
+\r
+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.\r
+\r
+  @param  NanoSeconds The minimum number of nanoseconds to delay.\r
+\r
+  @return NanoSeconds\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+NanoSecondDelay (\r
+  IN UINTN  NanoSeconds\r
+  )\r
+{\r
+\r
+  InternalCpuDelay (\r
+    DivU64x32 (\r
+      MultU64x64 (\r
+        NanoSeconds,\r
+        InternalGetPerformanceCounterFrequency ()\r
+        ),\r
+      1000000000u\r
+    )\r
+  );\r
+\r
+  return NanoSeconds;\r
+}\r
+\r
+/**\r
+  Retrieves the current value of a 64-bit free running performance counter.\r
+\r
+  Retrieves the current value of a 64-bit free running performance counter. The\r
+  counter can either count up by 1 or count down by 1. If the physical\r
+  performance counter counts by a larger increment, then the counter values\r
+  must be translated. The properties of the counter can be retrieved from\r
+  GetPerformanceCounterProperties().\r
+\r
+  @return The current value of the free running performance counter.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounter (\r
+  VOID\r
+  )\r
+{\r
+  return AsmReadTsc ();\r
+}\r
+\r
+/**\r
+  Retrieves the 64-bit frequency in Hz and the range of performance counter\r
+  values.\r
+\r
+  If StartValue is not NULL, then the value that the performance counter starts\r
+  with immediately after is it rolls over is returned in StartValue. If\r
+  EndValue is not NULL, then the value that the performance counter end with\r
+  immediately before it rolls over is returned in EndValue. The 64-bit\r
+  frequency of the performance counter in Hz is always returned. If StartValue\r
+  is less than EndValue, then the performance counter counts up. If StartValue\r
+  is greater than EndValue, then the performance counter counts down. For\r
+  example, a 64-bit free running counter that counts up would have a StartValue\r
+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter\r
+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.\r
+\r
+  @param  StartValue  The value the performance counter starts with when it\r
+                      rolls over.\r
+  @param  EndValue    The value that the performance counter ends with before\r
+                      it rolls over.\r
+\r
+  @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounterProperties (\r
+  OUT UINT64  *StartValue,  OPTIONAL\r
+  OUT UINT64  *EndValue     OPTIONAL\r
+  )\r
+{\r
+  if (StartValue != NULL) {\r
+    *StartValue = 0;\r
+  }\r
+\r
+  if (EndValue != NULL) {\r
+    *EndValue = 0xffffffffffffffffULL;\r
+  }\r
+  return InternalGetPerformanceCounterFrequency ();\r
+}\r
+\r
+/**\r
+  Converts elapsed ticks of performance counter to time in nanoseconds.\r
+\r
+  This function converts the elapsed ticks of running performance counter to\r
+  time value in unit of nanoseconds.\r
+\r
+  @param  Ticks     The number of elapsed ticks of running performance counter.\r
+\r
+  @return The elapsed time in nanoseconds.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetTimeInNanoSecond (\r
+  IN UINT64  Ticks\r
+  )\r
+{\r
+  UINT64  Frequency;\r
+  UINT64  NanoSeconds;\r
+  UINT64  Remainder;\r
+  INTN    Shift;\r
+\r
+  Frequency = GetPerformanceCounterProperties (NULL, NULL);\r
+\r
+  //\r
+  //          Ticks\r
+  // Time = --------- x 1,000,000,000\r
+  //        Frequency\r
+  //\r
+  NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);\r
+\r
+  //\r
+  // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.\r
+  // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,\r
+  // i.e. highest bit set in Remainder should <= 33.\r
+  //\r
+  Shift = MAX (0, HighBitSet64 (Remainder) - 33);\r
+  Remainder = RShiftU64 (Remainder, (UINTN) Shift);\r
+  Frequency = RShiftU64 (Frequency, (UINTN) Shift);\r
+  NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);\r
+\r
+  return NanoSeconds;\r
+}\r
+\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
new file mode 100644 (file)
index 0000000..269e5a3
--- /dev/null
@@ -0,0 +1,85 @@
+/** @file\r
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.\r
+\r
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/HobLib.h>\r
+\r
+extern GUID mCpuCrystalFrequencyHobGuid;\r
+\r
+/**\r
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.\r
+\r
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.\r
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+CpuidCoreClockCalculateTscFrequency (\r
+  VOID\r
+  );\r
+\r
+//\r
+// Cached CPU Crystal counter frequency\r
+//\r
+UINT64  mCpuCrystalCounterFrequency = 0;\r
+\r
+\r
+/**\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+InternalGetPerformanceCounterFrequency (\r
+  VOID\r
+  )\r
+{\r
+  return mCpuCrystalCounterFrequency;\r
+}\r
+\r
+/**\r
+  The constructor function is to initialize CpuCrystalCounterFrequency.\r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS   The constructor always returns RETURN_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeCpuTimerLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE   *GuidHob;\r
+\r
+  //\r
+  // Initialize CpuCrystalCounterFrequency\r
+  //\r
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);\r
+  if (GuidHob != NULL) {\r
+    mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);\r
+  } else {\r
+    mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();\r
+  }\r
+\r
+  if (mCpuCrystalCounterFrequency == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
new file mode 100644 (file)
index 0000000..6c83549
--- /dev/null
@@ -0,0 +1,37 @@
+## @file\r
+#  DXE CPU Timer Library\r
+#\r
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance\r
+#  counter features are provided by the processors time stamp counter.\r
+#\r
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DxeCpuTimerLib\r
+  FILE_GUID                      = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE\r
+  CONSTRUCTOR                    = DxeCpuTimerLibConstructor\r
+  MODULE_UNI_FILE                = DxeCpuTimerLib.uni\r
+\r
+[Sources]\r
+  CpuTimerLib.c\r
+  DxeCpuTimerLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  PcdLib\r
+  DebugLib\r
+  HobLib\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
new file mode 100644 (file)
index 0000000..f55b92a
--- /dev/null
@@ -0,0 +1,17 @@
+// /** @file\r
+// DXE CPU Timer Library\r
+//\r
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance\r
+// counter features are provided by the processors time stamp counter.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."\r
+\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
new file mode 100644 (file)
index 0000000..91a7212
--- /dev/null
@@ -0,0 +1,58 @@
+/** @file\r
+  CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer Library.\r
+\r
+  Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+extern GUID mCpuCrystalFrequencyHobGuid;\r
+\r
+/**\r
+  CPUID Leaf 0x15 for Core Crystal Clock Frequency.\r
+\r
+  The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.\r
+  In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+CpuidCoreClockCalculateTscFrequency (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  Internal function to retrieves the 64-bit frequency in Hz.\r
+\r
+  @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+InternalGetPerformanceCounterFrequency (\r
+  VOID\r
+  )\r
+{\r
+  UINT64              *CpuCrystalCounterFrequency;\r
+  EFI_HOB_GUID_TYPE   *GuidHob;\r
+\r
+  CpuCrystalCounterFrequency = NULL;\r
+  GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);\r
+  if (GuidHob == NULL) {\r
+    CpuCrystalCounterFrequency  = (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof (*CpuCrystalCounterFrequency));\r
+    ASSERT (CpuCrystalCounterFrequency != NULL);\r
+    *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();\r
+  } else {\r
+    CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob);\r
+  }\r
+\r
+  return  *CpuCrystalCounterFrequency;\r
+}\r
+\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
new file mode 100644 (file)
index 0000000..7af0fc4
--- /dev/null
@@ -0,0 +1,36 @@
+## @file\r
+#  PEI CPU Timer Library\r
+#\r
+#  Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance\r
+#  counter features are provided by the processors time stamp counter.\r
+#\r
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PeiCpuTimerLib\r
+  FILE_GUID                      = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib|PEI_CORE PEIM\r
+  MODULE_UNI_FILE                = PeiCpuTimerLib.uni\r
+\r
+[Sources]\r
+  CpuTimerLib.c\r
+  PeiCpuTimerLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  PcdLib\r
+  DebugLib\r
+  HobLib\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency  ## CONSUMES\r
diff --git a/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni b/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
new file mode 100644 (file)
index 0000000..49beb44
--- /dev/null
@@ -0,0 +1,17 @@
+// /** @file\r
+// PEI CPU Timer Library\r
+//\r
+// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency.  The performance\r
+// counter features are provided by the processors time stamp counter.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "CPU Timer Library"\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."\r
+\r
index 14ddaa8633c62cf587a332f9278b59637054d9aa..86ad61f64b06dcc90f5a81cb07d443a7c4bb63a2 100644 (file)
   # @Prompt If CPU features will be initialized during S3 resume.\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D\r
 \r
+  ## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.\r
+  # TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.\r
+  #   Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz)\r
+  #   6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz)\r
+  #   Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz)\r
+  # @Prompt This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency|24000000|UINT64|0x32132113\r
+\r
 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]\r
   ## Specifies max supported number of Logical Processors.\r
   # @Prompt Configure max supported number of Logical Processors\r
index bf690d3978f168f3c5dc94c75b813410fb63441a..e7dfe30eda1c681e1b2eb6c8e977258b5779962d 100644 (file)
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf\r
   UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf\r
   UefiCpuPkg/Application/Cpuid/Cpuid.inf\r
+  UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf\r
+  UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf\r
+  UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf\r
 \r
 [Components.IA32, Components.X64]\r
   UefiCpuPkg/CpuDxe/CpuDxe.inf\r
index 80af4fc1d20014ad867263aa8e93cc7bccf0dcf9..fbf7680726683171ee0d4c97116218ff19a139d3 100644 (file)
 #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuKnownGoodStackSize_HELP  #language en-US "Size of good stack for an exception.\n"\r
                                                                                      "This PCD will only take into effect if PcdCpuStackGuard is enabled.\n"\r
 \r
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_PROMPT  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency."\r
+\r
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuCoreCrystalClockFrequency_HELP  #language en-US "Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.<BR><BR>\n"\r
+                                                                                            "TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.<BR><BR>\n"\r
+                                                                                            "This PCD is the nominal frequency of the core crystal clock in Hz as is CPUID Leaf 0x15:ECX.<BR><BR>\n"\r
+                                                                                            "Default value is 24000000 for 6th and 7th generation Intel Core processors and Intel Xeon W Processor Family.<BR>\n"\r
+                                                                                            "25000000  -  Intel Xeon Processor Scalable Family with CPUID signature 06_55H(25MHz).<BR>\n"\r
+                                                                                            "24000000  -  6th and 7th generation Intel Core processors and Intel Xeon W Processor Family(24MHz).<BR>\n"\r
+                                                                                            "19200000  -  Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH(19.2MHz).<BR>\n"\r
+\r