Reviewed-by: : Michael D Kinney <michael.d.kin...@intel.com>

> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, August 10, 2016 7:38 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.z...@intel.com>; Kinney, Michael D 
> <michael.d.kin...@intel.com>;
> Gao, Liming <liming....@intel.com>; Lohr, Paul A <paul.a.l...@intel.com>
> Subject: [PATCH] PcAtChipsetPkg AcpiTimerLib: Get more accurate TSC Frequency
> 
> Minimize the code overhead between the two TSC reads by adding
> new internal API to calculate TSC Frequency instead of reusing
> MicroSecondDelay ().
> 
> Cc: Michael D Kinney <michael.d.kin...@intel.com>
> Cc: Liming Gao <liming....@intel.com>
> Cc: Paul A Lohr <paul.a.l...@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Star Zeng <star.z...@intel.com>
> ---
>  PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c | 56 
> +++++++++++++++++++++-
>  .../Library/AcpiTimerLib/BaseAcpiTimerLib.c        | 33 ++++++++-----
>  .../Library/AcpiTimerLib/DxeAcpiTimerLib.c         | 31 ++++++++----
>  3 files changed, 99 insertions(+), 21 deletions(-)
> 
> diff --git a/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c
> b/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c
> index 806a4f7ce24c..e6fea231123d 100644
> --- a/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c
> +++ b/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    ACPI Timer implements one instance of Timer Library.
> 
> -  Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD 
> License
>    which accompanies this distribution.  The full text of the license may be 
> found at
> @@ -335,3 +335,57 @@ GetTimeInNanoSecond (
> 
>    return NanoSeconds;
>  }
> +
> +/**
> +  Calculate TSC frequency.
> +
> +  The TSC counting frequency is determined by comparing how far it counts
> +  during a 100us period as determined by the ACPI timer. The ACPI timer is
> +  used because it counts at a known frequency.
> +  The TSC is sampled, followed by waiting for ACPI_TIMER_FREQUENCY / 10000
> +  clocks of the ACPI timer, or 100us. The TSC is then sampled again. The
> +  difference multiplied by 10000 is the TSC frequency. There will be a small
> +  error because of the overhead of reading the ACPI timer. An attempt is
> +  made to determine and compensate for this error.
> +
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +InternalCalculateTscFrequency (
> +  VOID
> +  )
> +{
> +  UINT64      StartTSC;
> +  UINT64      EndTSC;
> +  UINT16      TimerAddr;
> +  UINT32      Ticks;
> +  UINT64      TscFrequency;
> +  BOOLEAN     InterruptState;
> +
> +  InterruptState = SaveAndDisableInterrupts ();
> +
> +  TimerAddr = InternalAcpiGetAcpiTimerIoPort ();
> +  Ticks = IoRead32 (TimerAddr) + (ACPI_TIMER_FREQUENCY / 10000);    // Set 
> Ticks to
> 100us in the future
> +
> +  StartTSC = AsmReadTsc ();                                         // Get 
> base
> value for the TSC
> +  //
> +  // Wait until the ACPI timer has counted 100us.
> +  // Timer wrap-arounds are handled correctly by this function.
> +  // When the current ACPI timer value is greater than 'Ticks', the while 
> loop will
> exit.
> +  //
> +  while (((Ticks - IoRead32 (TimerAddr)) & BIT23) == 0) {
> +    CpuPause();
> +  }
> +  EndTSC = AsmReadTsc ();                                           // TSC 
> value
> 100us later
> +
> +  TscFrequency = MultU64x32 (
> +                   (EndTSC - StartTSC),                             // 
> Number of TSC
> counts in 100us
> +                   10000                                            // 
> Number of
> 100us in a second
> +                   );
> +
> +  SetInterruptState (InterruptState);
> +
> +  return TscFrequency;
> +}
> +
> diff --git a/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c
> b/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c
> index 21fdb79908b8..8819ebcfccef 100644
> --- a/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c
> +++ b/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    ACPI Timer implements one instance of Timer Library.
> 
> -  Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD 
> License
>    which accompanies this distribution.  The full text of the license may be 
> found at
> @@ -17,6 +17,26 @@
>  #include <Library/BaseLib.h>
> 
>  /**
> +  Calculate TSC frequency.
> +
> +  The TSC counting frequency is determined by comparing how far it counts
> +  during a 100us period as determined by the ACPI timer. The ACPI timer is
> +  used because it counts at a known frequency.
> +  The TSC is sampled, followed by waiting for ACPI_TIMER_FREQUENCY / 10000
> +  clocks of the ACPI timer, or 100us. The TSC is then sampled again. The
> +  difference multiplied by 10000 is the TSC frequency. There will be a small
> +  error because of the overhead of reading the ACPI timer. An attempt is
> +  made to determine and compensate for this error.
> +
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +InternalCalculateTscFrequency (
> +  VOID
> +  );
> +
> +/**
>    Internal function to retrieves the 64-bit frequency in Hz.
> 
>    Internal function to retrieves the 64-bit frequency in Hz.
> @@ -29,14 +49,5 @@ InternalGetPerformanceCounterFrequency (
>    VOID
>    )
>  {
> -  BOOLEAN  InterruptState;
> -  UINT64   Count;
> -  UINT64   Frequency;
> -
> -  InterruptState = SaveAndDisableInterrupts ();
> -  Count = GetPerformanceCounter ();
> -  MicroSecondDelay (100);
> -  Frequency = MultU64x32 (GetPerformanceCounter () - Count, 10000);
> -  SetInterruptState (InterruptState);
> -  return Frequency;
> +  return InternalCalculateTscFrequency ();
>  }
> diff --git a/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
> b/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
> index 6f5c07a4f0b4..7f7b0f8f6294 100644
> --- a/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
> +++ b/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    ACPI Timer implements one instance of Timer Library.
> 
> -  Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD 
> License
>    which accompanies this distribution.  The full text of the license may be 
> found at
> @@ -16,6 +16,26 @@
>  #include <Library/TimerLib.h>
>  #include <Library/BaseLib.h>
> 
> +/**
> +  Calculate TSC frequency.
> +
> +  The TSC counting frequency is determined by comparing how far it counts
> +  during a 100us period as determined by the ACPI timer. The ACPI timer is
> +  used because it counts at a known frequency.
> +  The TSC is sampled, followed by waiting for ACPI_TIMER_FREQUENCY / 10000
> +  clocks of the ACPI timer, or 100us. The TSC is then sampled again. The
> +  difference multiplied by 10000 is the TSC frequency. There will be a small
> +  error because of the overhead of reading the ACPI timer. An attempt is
> +  made to determine and compensate for this error.
> +
> +  @return The number of TSC counts per second.
> +
> +**/
> +UINT64
> +InternalCalculateTscFrequency (
> +  VOID
> +  );
> +
>  //
>  // Cached performance counter frequency
>  //
> @@ -34,15 +54,8 @@ InternalGetPerformanceCounterFrequency (
>    VOID
>    )
>  {
> -  BOOLEAN  InterruptState;
> -  UINT64   Count;
> -
>    if (mPerformanceCounterFrequency == 0) {
> -    InterruptState = SaveAndDisableInterrupts ();
> -    Count = GetPerformanceCounter ();
> -    MicroSecondDelay (100);
> -    mPerformanceCounterFrequency = MultU64x32 (GetPerformanceCounter () - 
> Count,
> 10000);
> -    SetInterruptState (InterruptState);
> +    mPerformanceCounterFrequency = InternalCalculateTscFrequency ();
>    }
>    return  mPerformanceCounterFrequency;
>  }
> --
> 2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to