]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add BaseTscTimerLib, and then merge the three TscTimerLib to one directory.
authorlzeng14 <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>
Sun, 30 Oct 2011 13:14:44 +0000 (13:14 +0000)
committerlzeng14 <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>
Sun, 30 Oct 2011 13:14:44 +0000 (13:14 +0000)
Signed-off-by: lzeng14
Reviewed-by: lgao4
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12604 6f19259b-4bc3-4df7-8a09-765794883524

13 files changed:
PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.c [deleted file]
PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf [deleted file]
PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.c [deleted file]
PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.inf [deleted file]
PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c [new file with mode: 0644]
PerformancePkg/PerformancePkg.dsc

diff --git a/PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.c b/PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.c
deleted file mode 100644 (file)
index b7e4d68..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/** @file\r
-  A Dxe Timer Library implementation which uses the Time Stamp Counter in the processor.\r
-\r
-  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
-    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
-    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
-    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
-    for Intel Atom processors (family [06H], display_model [1CH]):\r
-  the time-stamp counter increments at a constant rate.\r
-  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
-  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
-  differ from the maximum qualified frequency of the processor.\r
-\r
-  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
-  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
-  the processor core changes frequency. This is the architectural behavior moving forward.\r
-\r
-  A Processor's support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
-\r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution. The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <PiDxe.h>\r
-#include <Ich/GenericIch.h>\r
-\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/TimerLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PciLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/DebugLib.h>\r
-\r
-#include <Guid/TscFrequency.h>\r
-\r
-UINT64 mTscFrequency;\r
-\r
-/** The constructor function determines the actual TSC frequency.\r
-\r
-  First, Get TSC frequency from system configuration table with TSC frequency GUID,\r
-  if the table is not found, install it.\r
-\r
-  The TSC counting frequency is determined by comparing how far it counts\r
-  during a 1ms period as determined by the ACPI timer. The ACPI timer is\r
-  used because it counts at a known frequency.\r
-  If ACPI I/O space not enabled, this function will enable it. Then the\r
-  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
-  The TSC is then sampled again. The difference multiplied by 1000 is the TSC\r
-  frequency. There will be a small error because of the overhead of reading\r
-  the ACPI timer. An attempt is made to determine and compensate for this error.\r
-  This function will always return EFI_SUCCESS.\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 EFI_SUCCESS.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-DxeTscTimerLibConstructor (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT64      *TscFrequency;\r
-  UINT64      StartTSC;\r
-  UINT64      EndTSC;\r
-  UINT32      TimerAddr;\r
-  UINT32      Ticks;\r
-\r
-  //\r
-  // Get TSC frequency from system configuration table with TSC frequency GUID.\r
-  //\r
-  Status = EfiGetSystemConfigurationTable (&gEfiTscFrequencyGuid, (VOID **) &TscFrequency);\r
-  if (Status == EFI_SUCCESS) {\r
-    mTscFrequency = *TscFrequency;\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // TSC frequency GUID system configuration table is not found, install it.\r
-  //\r
-\r
-  //\r
-  // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it.\r
-  //\r
-  if ((PciRead8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT)) & B_ICH_LPC_ACPI_CNT_ACPI_EN) == 0) {\r
-    PciWrite16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE), PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress));\r
-    PciOr8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT), B_ICH_LPC_ACPI_CNT_ACPI_EN);\r
-  }\r
-\r
-  //\r
-  // ACPI I/O space should be enabled now, locate the ACPI Timer.\r
-  // ACPI I/O base address maybe have be initialized by other driver with different value,\r
-  // So get it from PCI space directly.\r
-  //\r
-  TimerAddr = ((PciRead16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE))) & B_ICH_LPC_ACPI_BASE_BAR) + R_ACPI_PM1_TMR;\r
-  Ticks    = IoRead32 (TimerAddr) + (3579);   // Set Ticks to 1ms in the future\r
-  StartTSC = AsmReadTsc();                    // Get base value for the TSC\r
-  //\r
-  // Wait until the ACPI timer has counted 1ms.\r
-  // Timer wrap-arounds are handled correctly by this function.\r
-  // When the current ACPI timer value is greater than 'Ticks', the while loop will exit.\r
-  //\r
-  while (((Ticks - IoRead32 (TimerAddr)) & BIT23) == 0) {\r
-    CpuPause();\r
-  }\r
-  EndTSC = AsmReadTsc();    // TSC value 1ms later\r
-\r
-  Status = gBS->AllocatePool (EfiBootServicesData, sizeof (UINT64), (VOID **) &TscFrequency);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  *TscFrequency = MultU64x32 (\r
-                    (EndTSC - StartTSC),      // Number of TSC counts in 1ms\r
-                    1000                      // Number of ms in a second\r
-                  );\r
-  //\r
-  // TscFrequency now points to the number of TSC counts per second, install system configuration table for it.\r
-  //\r
-  gBS->InstallConfigurationTable (&gEfiTscFrequencyGuid, TscFrequency);\r
-\r
-  mTscFrequency = *TscFrequency;\r
-  return EFI_SUCCESS;\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[in]  Delay     A period of time to delay in ticks.\r
-\r
-**/\r
-VOID\r
-InternalX86Delay (\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) CpuPause();\r
-}\r
-\r
-/**  Stalls the CPU for at least the specified number of MicroSeconds.\r
-\r
-  @param[in]  MicroSeconds  The minimum number of microseconds to delay.\r
-\r
-  @return The value of MicroSeconds input.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-MicroSecondDelay (\r
-  IN      UINTN                     MicroSeconds\r
-  )\r
-{\r
-  InternalX86Delay (\r
-    DivU64x32 (\r
-      MultU64x64 (\r
-        mTscFrequency,\r
-        MicroSeconds\r
-      ),\r
-      1000000u\r
-    )\r
-  );\r
-  return MicroSeconds;\r
-}\r
-\r
-/**  Stalls the CPU for at least the specified number of NanoSeconds.\r
-\r
-  @param[in]  NanoSeconds The minimum number of nanoseconds to delay.\r
-\r
-  @return The value of NanoSeconds input.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-NanoSecondDelay (\r
-  IN      UINTN                     NanoSeconds\r
-  )\r
-{\r
-  InternalX86Delay (\r
-    DivU64x32 (\r
-      MultU64x32 (\r
-        mTscFrequency,\r
-        (UINT32)NanoSeconds\r
-      ),\r
-    1000000000u\r
-    )\r
-  );\r
-  return NanoSeconds;\r
-}\r
-\r
-/**  Retrieves the current value of the 64-bit free running Time-Stamp counter.\r
-\r
-  The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M,\r
-  Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and\r
-  later processors) is a 64-bit counter that is set to 0 following a RESET of\r
-  the processor.  Following a RESET, the counter increments even when the\r
-  processor is halted by the HLT instruction or the external STPCLK# pin. Note\r
-  that the assertion of the external DPSLP# pin may cause the time-stamp\r
-  counter to stop.\r
-\r
-  The properties of the counter can be retrieved by the\r
-  GetPerformanceCounterProperties() function.\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
-/**  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, 0x0, is returned in StartValue. If EndValue is not NULL, then the value\r
-  that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in\r
-  EndValue.\r
-\r
-  The 64-bit frequency of the performance counter, in Hz, is always returned.\r
-  To determine average processor clock frequency, Intel recommends the use of\r
-  EMON logic to count processor core clocks over the period of time for which\r
-  the average is required.\r
-\r
-\r
-  @param[out]   StartValue  Pointer to where the performance counter's starting value is saved, or NULL.\r
-  @param[out]   EndValue    Pointer to where the performance counter's ending value is saved, or NULL.\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
-  if (EndValue != NULL) {\r
-    *EndValue = 0xFFFFFFFFFFFFFFFFull;\r
-  }\r
-\r
-  return mTscFrequency;\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
diff --git a/PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf b/PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
deleted file mode 100644 (file)
index 8d2e6cf..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-## @file\r
-#  Dxe Timer Library which uses the Time Stamp Counter in the processor.\r
-#\r
-#  A version of the Timer Library using the processor's TSC.\r
-#  The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
-#  The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
-#  This is the architectural behavior moving forward.\r
-#  TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
-#  access to a platform resource.\r
-#\r
-#  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
-#  This program and the accompanying materials\r
-#  are licensed and made available under the terms and conditions of the BSD License\r
-#  which accompanies this distribution. The full text of the license may be found at\r
-#  http://opensource.org/licenses/bsd-license.php\r
-#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-##\r
-\r
-[Defines]\r
-  INF_VERSION                    = 0x00010005\r
-  BASE_NAME                      = DxeTscTimerLib\r
-  FILE_GUID                      = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9\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
-\r
-  CONSTRUCTOR                    = DxeTscTimerLibConstructor\r
-\r
-\r
-#\r
-#  VALID_ARCHITECTURES           = IA32 X64\r
-#\r
-\r
-[Sources.common]\r
-  DxeTscTimerLib.c\r
-\r
-\r
-[Packages]\r
-  MdePkg/MdePkg.dec\r
-  PerformancePkg/PerformancePkg.dec\r
-\r
-\r
-[LibraryClasses]\r
-  UefiBootServicesTableLib\r
-  PcdLib\r
-  PciLib\r
-  IoLib\r
-  BaseLib\r
-  UefiLib\r
-  DebugLib\r
-\r
-[Guids]\r
-  gEfiTscFrequencyGuid                          ## CONSUMES ## System Configuration Table\r
-\r
-[Pcd.common]\r
-  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
diff --git a/PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.c b/PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.c
deleted file mode 100644 (file)
index 4c37964..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/** @file\r
-  A Pei Timer Library implementation which uses the Time Stamp Counter in the processor.\r
-\r
-  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
-    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
-    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
-    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
-    for Intel Atom processors (family [06H], display_model [1CH]):\r
-  the time-stamp counter increments at a constant rate.\r
-  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
-  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
-  differ from the maximum qualified frequency of the processor.\r
-\r
-  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
-  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
-  the processor core changes frequency. This is the architectural behavior moving forward.\r
-\r
-  A Processor's support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
-\r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution. The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <PiPei.h>\r
-#include <Ich/GenericIch.h>\r
-\r
-#include <Library/TimerLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PciLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/HobLib.h>\r
-\r
-#include <Guid/TscFrequency.h>\r
-\r
-/**  Get TSC frequency from TSC frequency GUID HOB, if the HOB is not found, build it.\r
-\r
-  The TSC counting frequency is determined by comparing how far it counts\r
-  during a 1ms period as determined by the ACPI timer. The ACPI timer is\r
-  used because it counts at a known frequency.\r
-  If ACPI I/O space not enabled, this function will enable it. Then the\r
-  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
-  The TSC is then sampled again. The difference multiplied by 1000 is the TSC\r
-  frequency. There will be a small error because of the overhead of reading\r
-  the ACPI timer.\r
-\r
-  @return The number of TSC counts per second.\r
-\r
-**/\r
-UINT64\r
-InternalGetTscFrequency (\r
-  VOID\r
-  )\r
-{\r
-  EFI_HOB_GUID_TYPE       *GuidHob;\r
-  VOID        *DataInHob;\r
-  UINT64      StartTSC;\r
-  UINT64      EndTSC;\r
-  UINT32      TimerAddr;\r
-  UINT32      Ticks;\r
-  UINT64      TscFrequency;\r
-\r
-  //\r
-  // Get TSC frequency from TSC frequency GUID HOB.\r
-  //\r
-  GuidHob = GetFirstGuidHob (&gEfiTscFrequencyGuid);\r
-  if (GuidHob != NULL) {\r
-    DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
-    TscFrequency = * (UINT64 *) DataInHob;\r
-    return TscFrequency;\r
-  }\r
-\r
-  //\r
-  // TSC frequency GUID HOB is not found, build it.\r
-  //\r
-\r
-  //\r
-  // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it.\r
-  //\r
-  if ((PciRead8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT)) & B_ICH_LPC_ACPI_CNT_ACPI_EN) == 0) {\r
-    PciWrite16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE), PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress));\r
-    PciOr8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT), B_ICH_LPC_ACPI_CNT_ACPI_EN);\r
-  }\r
-\r
-  //\r
-  // ACPI I/O space should be enabled now, locate the ACPI Timer.\r
-  // ACPI I/O base address maybe have be initialized by other driver with different value,\r
-  // So get it from PCI space directly.\r
-  //\r
-  TimerAddr = ((PciRead16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE))) & B_ICH_LPC_ACPI_BASE_BAR) + R_ACPI_PM1_TMR;\r
-  Ticks    = IoRead32 (TimerAddr) + (3579);   // Set Ticks to 1ms in the future\r
-  StartTSC = AsmReadTsc();                    // Get base value for the TSC\r
-  //\r
-  // Wait until the ACPI timer has counted 1ms.\r
-  // Timer wrap-arounds are handled correctly by this function.\r
-  // When the current ACPI timer value is greater than 'Ticks', the while loop will exit.\r
-  //\r
-  while (((Ticks - IoRead32 (TimerAddr)) & BIT23) == 0) {\r
-    CpuPause();\r
-  }\r
-  EndTSC = AsmReadTsc();    // TSC value 1ms later\r
-\r
-  TscFrequency =   MultU64x32 (\r
-                      (EndTSC - StartTSC),    // Number of TSC counts in 1ms\r
-                      1000                    // Number of ms in a second\r
-                    );\r
-  //\r
-  // TscFrequency is now equal to the number of TSC counts per second, build GUID HOB for it.\r
-  //\r
-  BuildGuidDataHob (\r
-    &gEfiTscFrequencyGuid,\r
-    &TscFrequency,\r
-    sizeof (UINT64)\r
-    );\r
-\r
-  return TscFrequency;\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[in]  Delay     A period of time to delay in ticks.\r
-\r
-**/\r
-VOID\r
-InternalX86Delay (\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) CpuPause();\r
-}\r
-\r
-/**  Stalls the CPU for at least the specified number of MicroSeconds.\r
-\r
-  @param[in]  MicroSeconds  The minimum number of microseconds to delay.\r
-\r
-  @return The value of MicroSeconds input.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-MicroSecondDelay (\r
-  IN      UINTN                     MicroSeconds\r
-  )\r
-{\r
-  InternalX86Delay (\r
-    DivU64x32 (\r
-      MultU64x64 (\r
-        InternalGetTscFrequency (),\r
-        MicroSeconds\r
-      ),\r
-      1000000u\r
-    )\r
-  );\r
-  return MicroSeconds;\r
-}\r
-\r
-/**  Stalls the CPU for at least the specified number of NanoSeconds.\r
-\r
-  @param[in]  NanoSeconds The minimum number of nanoseconds to delay.\r
-\r
-  @return The value of NanoSeconds input.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-NanoSecondDelay (\r
-  IN      UINTN                     NanoSeconds\r
-  )\r
-{\r
-  InternalX86Delay (\r
-    DivU64x32 (\r
-      MultU64x32 (\r
-        InternalGetTscFrequency (),\r
-        (UINT32)NanoSeconds\r
-      ),\r
-    1000000000u\r
-    )\r
-  );\r
-  return NanoSeconds;\r
-}\r
-\r
-/**  Retrieves the current value of the 64-bit free running Time-Stamp counter.\r
-\r
-  The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M,\r
-  Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and\r
-  later processors) is a 64-bit counter that is set to 0 following a RESET of\r
-  the processor.  Following a RESET, the counter increments even when the\r
-  processor is halted by the HLT instruction or the external STPCLK# pin. Note\r
-  that the assertion of the external DPSLP# pin may cause the time-stamp\r
-  counter to stop.\r
-\r
-  The properties of the counter can be retrieved by the\r
-  GetPerformanceCounterProperties() function.\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
-/**  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, 0x0, is returned in StartValue. If EndValue is not NULL, then the value\r
-  that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in\r
-  EndValue.\r
-\r
-  The 64-bit frequency of the performance counter, in Hz, is always returned.\r
-  To determine average processor clock frequency, Intel recommends the use of\r
-  EMON logic to count processor core clocks over the period of time for which\r
-  the average is required.\r
-\r
-\r
-  @param[out]   StartValue  Pointer to where the performance counter's starting value is saved, or NULL.\r
-  @param[out]   EndValue    Pointer to where the performance counter's ending value is saved, or NULL.\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
-  if (EndValue != NULL) {\r
-    *EndValue = 0xFFFFFFFFFFFFFFFFull;\r
-  }\r
-\r
-  return InternalGetTscFrequency ();\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
diff --git a/PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.inf b/PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.inf
deleted file mode 100644 (file)
index 1a4bc19..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-## @file\r
-#  Pei Timer Library which uses the Time Stamp Counter in the processor.\r
-#\r
-#  A version of the Timer Library using the processor's TSC.\r
-#  The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
-#  The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
-#  This is the architectural behavior moving forward.\r
-#  TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
-#  access to a platform resource.\r
-#\r
-#  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
-#  This program and the accompanying materials\r
-#  are licensed and made available under the terms and conditions of the BSD License\r
-#  which accompanies this distribution. The full text of the license may be found at\r
-#  http://opensource.org/licenses/bsd-license.php\r
-#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-##\r
-\r
-[Defines]\r
-  INF_VERSION                    = 0x00010005\r
-  BASE_NAME                      = PeiTscTimerLib\r
-  FILE_GUID                      = 342C36C0-15DF-43b4-9EC9-FBF748BFB3D1\r
-  MODULE_TYPE                    = PEIM\r
-  VERSION_STRING                 = 1.0\r
-  LIBRARY_CLASS                  = TimerLib|SEC PEIM PEI_CORE\r
-\r
-\r
-#\r
-#  VALID_ARCHITECTURES           = IA32 X64\r
-#\r
-\r
-[Sources.common]\r
-  PeiTscTimerLib.c\r
-\r
-\r
-[Packages]\r
-  MdePkg/MdePkg.dec\r
-  PerformancePkg/PerformancePkg.dec\r
-\r
-\r
-[LibraryClasses]\r
-  PcdLib\r
-  PciLib\r
-  IoLib\r
-  BaseLib\r
-  HobLib\r
-\r
-[Guids]\r
-  gEfiTscFrequencyGuid                          ## PRODUCES ## Hob\r
-\r
-[Pcd.common]\r
-  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
diff --git a/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c b/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c
new file mode 100644 (file)
index 0000000..77bc04e
--- /dev/null
@@ -0,0 +1,57 @@
+/** @file\r
+  A Base Timer Library implementation which uses the Time Stamp Counter in the processor.\r
+\r
+  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
+    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
+    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
+    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
+    for Intel Atom processors (family [06H], display_model [1CH]):\r
+  the time-stamp counter increments at a constant rate.\r
+  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
+  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
+  differ from the maximum qualified frequency of the processor.\r
+\r
+  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
+  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
+  the processor core changes frequency. This is the architectural behavior moving forward.\r
+\r
+  A Processor's support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
+\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TscTimerLibInternal.h"\r
+\r
+UINT64  mTscFrequency = 0;\r
+\r
+/**  Get TSC frequency.\r
+\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalGetTscFrequency (\r
+  VOID\r
+  )\r
+{\r
+  UINT64    TscFrequency;\r
+\r
+  if (mTscFrequency != 0) {\r
+    return mTscFrequency;\r
+  }\r
+\r
+  TscFrequency = InternalCalculateTscFrequency ();\r
+\r
+  mTscFrequency = TscFrequency;\r
+\r
+  return TscFrequency;\r
+}\r
+\r
diff --git a/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf b/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf
new file mode 100644 (file)
index 0000000..2c33b77
--- /dev/null
@@ -0,0 +1,54 @@
+## @file\r
+#  Base Timer Library which uses the Time Stamp Counter in the processor.\r
+#\r
+#  Note: There will be 1ms penalty to get TSC frequency every time\r
+#    by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
+#\r
+#  A version of the Timer Library using the processor's TSC.\r
+#  The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
+#  The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
+#  This is the architectural behavior moving forward.\r
+#  TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
+#  access to a platform resource.\r
+#\r
+#  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BaseTscTimerLib\r
+  FILE_GUID                      = D29338B9-50FE-4e4f-B7D4-A150A2C1F4FB\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib\r
+\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+  TscTimerLibShare.c\r
+  BaseTscTimerLib.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  PerformancePkg/PerformancePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  PciLib\r
+  IoLib\r
+  BaseLib\r
+\r
+[Pcd.common]\r
+  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
diff --git a/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c b/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c
new file mode 100644 (file)
index 0000000..c5a7894
--- /dev/null
@@ -0,0 +1,100 @@
+/** @file\r
+  A Dxe Timer Library implementation which uses the Time Stamp Counter in the processor.\r
+\r
+  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
+    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
+    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
+    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
+    for Intel Atom processors (family [06H], display_model [1CH]):\r
+  the time-stamp counter increments at a constant rate.\r
+  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
+  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
+  differ from the maximum qualified frequency of the processor.\r
+\r
+  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
+  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
+  the processor core changes frequency. This is the architectural behavior moving forward.\r
+\r
+  A Processor's support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
+\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Guid/TscFrequency.h>\r
+#include "TscTimerLibInternal.h"\r
+\r
+UINT64 mTscFrequency;\r
+\r
+/** The constructor function determines the actual TSC frequency.\r
+\r
+  First, Get TSC frequency from system configuration table with TSC frequency GUID,\r
+  if the table is not found, install it.\r
+  This function will always return EFI_SUCCESS.\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 EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeTscTimerLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT64      *TscFrequency;\r
+\r
+  //\r
+  // Get TSC frequency from system configuration table with TSC frequency GUID.\r
+  //\r
+  Status = EfiGetSystemConfigurationTable (&gEfiTscFrequencyGuid, (VOID **) &TscFrequency);\r
+  if (Status == EFI_SUCCESS) {\r
+    mTscFrequency = *TscFrequency;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // TSC frequency GUID system configuration table is not found, install it.\r
+  //\r
+\r
+  Status = gBS->AllocatePool (EfiBootServicesData, sizeof (UINT64), (VOID **) &TscFrequency);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  *TscFrequency = InternalCalculateTscFrequency ();\r
+  //\r
+  // TscFrequency now points to the number of TSC counts per second, install system configuration table for it.\r
+  //\r
+  gBS->InstallConfigurationTable (&gEfiTscFrequencyGuid, TscFrequency);\r
+\r
+  mTscFrequency = *TscFrequency;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**  Get TSC frequency.\r
+\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalGetTscFrequency (\r
+  VOID\r
+  )\r
+{\r
+  return mTscFrequency;\r
+}\r
+\r
diff --git a/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf b/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf
new file mode 100644 (file)
index 0000000..e0edd6f
--- /dev/null
@@ -0,0 +1,59 @@
+## @file\r
+#  Dxe Timer Library which uses the Time Stamp Counter in the processor.\r
+#\r
+#  A version of the Timer Library using the processor's TSC.\r
+#  The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
+#  The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
+#  This is the architectural behavior moving forward.\r
+#  TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
+#  access to a platform resource.\r
+#\r
+#  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = DxeTscTimerLib\r
+  FILE_GUID                      = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9\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
+\r
+  CONSTRUCTOR                    = DxeTscTimerLibConstructor\r
+\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+  TscTimerLibShare.c\r
+  DxeTscTimerLib.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  PerformancePkg/PerformancePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  UefiBootServicesTableLib\r
+  PcdLib\r
+  PciLib\r
+  IoLib\r
+  BaseLib\r
+  UefiLib\r
+  DebugLib\r
+\r
+[Guids]\r
+  gEfiTscFrequencyGuid                          ## CONSUMES ## System Configuration Table\r
+\r
+[Pcd.common]\r
+  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
diff --git a/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c b/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c
new file mode 100644 (file)
index 0000000..af3600b
--- /dev/null
@@ -0,0 +1,76 @@
+/** @file\r
+  A Pei Timer Library implementation which uses the Time Stamp Counter in the processor.\r
+\r
+  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
+    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
+    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
+    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
+    for Intel Atom processors (family [06H], display_model [1CH]):\r
+  the time-stamp counter increments at a constant rate.\r
+  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
+  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
+  differ from the maximum qualified frequency of the processor.\r
+\r
+  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
+  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
+  the processor core changes frequency. This is the architectural behavior moving forward.\r
+\r
+  A Processor's support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
+\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/HobLib.h>\r
+#include <Guid/TscFrequency.h>\r
+#include "TscTimerLibInternal.h"\r
+\r
+/**  Get TSC frequency from TSC frequency GUID HOB, if the HOB is not found, build it.\r
+\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalGetTscFrequency (\r
+  VOID\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE       *GuidHob;\r
+  VOID        *DataInHob;\r
+  UINT64      TscFrequency;\r
+\r
+  //\r
+  // Get TSC frequency from TSC frequency GUID HOB.\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gEfiTscFrequencyGuid);\r
+  if (GuidHob != NULL) {\r
+    DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
+    TscFrequency = * (UINT64 *) DataInHob;\r
+    return TscFrequency;\r
+  }\r
+\r
+  //\r
+  // TSC frequency GUID HOB is not found, build it.\r
+  //\r
+\r
+  TscFrequency = InternalCalculateTscFrequency ();\r
+  //\r
+  // TscFrequency is now equal to the number of TSC counts per second, build GUID HOB for it.\r
+  //\r
+  BuildGuidDataHob (\r
+    &gEfiTscFrequencyGuid,\r
+    &TscFrequency,\r
+    sizeof (UINT64)\r
+    );\r
+\r
+  return TscFrequency;\r
+}\r
+\r
diff --git a/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf b/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf
new file mode 100644 (file)
index 0000000..177e4c3
--- /dev/null
@@ -0,0 +1,55 @@
+## @file\r
+#  Pei Timer Library which uses the Time Stamp Counter in the processor.\r
+#\r
+#  A version of the Timer Library using the processor's TSC.\r
+#  The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
+#  The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
+#  This is the architectural behavior moving forward.\r
+#  TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
+#  access to a platform resource.\r
+#\r
+#  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PeiTscTimerLib\r
+  FILE_GUID                      = 342C36C0-15DF-43b4-9EC9-FBF748BFB3D1\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib|PEIM PEI_CORE\r
+\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+  TscTimerLibShare.c\r
+  PeiTscTimerLib.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  PerformancePkg/PerformancePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  PciLib\r
+  IoLib\r
+  BaseLib\r
+  HobLib\r
+\r
+[Guids]\r
+  gEfiTscFrequencyGuid                          ## PRODUCES ## Hob\r
+\r
+[Pcd.common]\r
+  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
diff --git a/PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h b/PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h
new file mode 100644 (file)
index 0000000..a4ed0eb
--- /dev/null
@@ -0,0 +1,55 @@
+/** @file\r
+  Internal header file for TscTimerLib instances.\r
+\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _TSC_TIMER_LIB_INTERNAL_H_\r
+#define _TSC_TIMER_LIB_INTERNAL_H_\r
+\r
+#include <Ich/GenericIch.h>\r
+\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+/**  Get TSC frequency.\r
+\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalGetTscFrequency (\r
+  VOID\r
+  );\r
+\r
+/**  Calculate TSC frequency.\r
+\r
+  The TSC counting frequency is determined by comparing how far it counts\r
+  during a 1ms period as determined by the ACPI timer. The ACPI timer is\r
+  used because it counts at a known frequency.\r
+  If ACPI I/O space not enabled, this function will enable it. Then the\r
+  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
+  The TSC is then sampled again. The difference multiplied by 1000 is the TSC\r
+  frequency. There will be a small error because of the overhead of reading\r
+  the ACPI timer. An attempt is made to determine and compensate for this error.\r
+\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalCalculateTscFrequency (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c b/PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c
new file mode 100644 (file)
index 0000000..161af00
--- /dev/null
@@ -0,0 +1,275 @@
+/** @file\r
+  The Timer Library implementation which uses the Time Stamp Counter in the processor.\r
+\r
+  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
+    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
+    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
+    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
+    for Intel Atom processors (family [06H], display_model [1CH]):\r
+  the time-stamp counter increments at a constant rate.\r
+  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
+  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
+  differ from the maximum qualified frequency of the processor.\r
+\r
+  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
+  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
+  the processor core changes frequency. This is the architectural behavior moving forward.\r
+\r
+  A Processor's support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
+\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution. The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TscTimerLibInternal.h"\r
+\r
+/**  Calculate TSC frequency.\r
+\r
+  The TSC counting frequency is determined by comparing how far it counts\r
+  during a 1ms period as determined by the ACPI timer. The ACPI timer is\r
+  used because it counts at a known frequency.\r
+  If ACPI I/O space not enabled, this function will enable it. Then the\r
+  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
+  The TSC is then sampled again. The difference multiplied by 1000 is the TSC\r
+  frequency. There will be a small error because of the overhead of reading\r
+  the ACPI timer. An attempt is made to determine and compensate for this error.\r
+\r
+  @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalCalculateTscFrequency (\r
+  VOID\r
+  )\r
+{\r
+  UINT64      StartTSC;\r
+  UINT64      EndTSC;\r
+  UINT32      TimerAddr;\r
+  UINT32      Ticks;\r
+  UINT64      TscFrequency;\r
+\r
+  //\r
+  // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it.\r
+  //\r
+  if ((PciRead8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT)) & B_ICH_LPC_ACPI_CNT_ACPI_EN) == 0) {\r
+    PciWrite16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE), PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress));\r
+    PciOr8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT), B_ICH_LPC_ACPI_CNT_ACPI_EN);\r
+  }\r
+\r
+  //\r
+  // ACPI I/O space should be enabled now, locate the ACPI Timer.\r
+  // ACPI I/O base address maybe have be initialized by other driver with different value,\r
+  // So get it from PCI space directly.\r
+  //\r
+  TimerAddr = ((PciRead16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE))) & B_ICH_LPC_ACPI_BASE_BAR) + R_ACPI_PM1_TMR;\r
+  Ticks    = IoRead32 (TimerAddr) + (3579);   // Set Ticks to 1ms in the future\r
+  StartTSC = AsmReadTsc();                    // Get base value for the TSC\r
+  //\r
+  // Wait until the ACPI timer has counted 1ms.\r
+  // Timer wrap-arounds are handled correctly by this function.\r
+  // When the current ACPI timer value is greater than 'Ticks', the while loop will exit.\r
+  //\r
+  while (((Ticks - IoRead32 (TimerAddr)) & BIT23) == 0) {\r
+    CpuPause();\r
+  }\r
+  EndTSC = AsmReadTsc();    // TSC value 1ms later\r
+\r
+  TscFrequency =   MultU64x32 (\r
+                      (EndTSC - StartTSC),    // Number of TSC counts in 1ms\r
+                      1000                    // Number of ms in a second\r
+                    );\r
+\r
+  return TscFrequency;\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[in]  Delay     A period of time to delay in ticks.\r
+\r
+**/\r
+VOID\r
+InternalX86Delay (\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) CpuPause();\r
+}\r
+\r
+/**  Stalls the CPU for at least the specified number of MicroSeconds.\r
+\r
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.\r
+\r
+  @return The value of MicroSeconds input.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+MicroSecondDelay (\r
+  IN      UINTN                     MicroSeconds\r
+  )\r
+{\r
+  InternalX86Delay (\r
+    DivU64x32 (\r
+      MultU64x64 (\r
+        InternalGetTscFrequency (),\r
+        MicroSeconds\r
+      ),\r
+      1000000u\r
+    )\r
+  );\r
+  return MicroSeconds;\r
+}\r
+\r
+/**  Stalls the CPU for at least the specified number of NanoSeconds.\r
+\r
+  @param[in]  NanoSeconds The minimum number of nanoseconds to delay.\r
+\r
+  @return The value of NanoSeconds input.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+NanoSecondDelay (\r
+  IN      UINTN                     NanoSeconds\r
+  )\r
+{\r
+  InternalX86Delay (\r
+    DivU64x32 (\r
+      MultU64x32 (\r
+        InternalGetTscFrequency (),\r
+        (UINT32)NanoSeconds\r
+      ),\r
+    1000000000u\r
+    )\r
+  );\r
+  return NanoSeconds;\r
+}\r
+\r
+/**  Retrieves the current value of the 64-bit free running Time-Stamp counter.\r
+\r
+  The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M,\r
+  Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and\r
+  later processors) is a 64-bit counter that is set to 0 following a RESET of\r
+  the processor.  Following a RESET, the counter increments even when the\r
+  processor is halted by the HLT instruction or the external STPCLK# pin. Note\r
+  that the assertion of the external DPSLP# pin may cause the time-stamp\r
+  counter to stop.\r
+\r
+  The properties of the counter can be retrieved by the\r
+  GetPerformanceCounterProperties() function.\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
+/**  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, 0x0, is returned in StartValue. If EndValue is not NULL, then the value\r
+  that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in\r
+  EndValue.\r
+\r
+  The 64-bit frequency of the performance counter, in Hz, is always returned.\r
+  To determine average processor clock frequency, Intel recommends the use of\r
+  EMON logic to count processor core clocks over the period of time for which\r
+  the average is required.\r
+\r
+\r
+  @param[out]   StartValue  Pointer to where the performance counter's starting value is saved, or NULL.\r
+  @param[out]   EndValue    Pointer to where the performance counter's ending value is saved, or NULL.\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
+  if (EndValue != NULL) {\r
+    *EndValue = 0xFFFFFFFFFFFFFFFFull;\r
+  }\r
+\r
+  return InternalGetTscFrequency ();\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
index 0717322d9f449a6f717c6e32636df909b511e006..b6b6c2df17a4036adb6f135b59fb91e30dc38e42 100644 (file)
   # that is different than the one below.\r
   #\r
   # TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf\r
-  TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf\r
+  TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf\r
 \r
 [LibraryClasses.IPF]\r
   PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf\r
   TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
 \r
 [Components.IA32, Components.X64]\r
-  PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf\r
-  PerformancePkg/Library/PeiTscTimerLib/PeiTscTimerLib.inf\r
+  PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf\r
+  PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf\r
+  PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf\r
 \r
 [Components]\r
   PerformancePkg/Dp_App/Dp.inf\r