From: "Gao, Liming" <liming.gao@intel.com>
To: "Zeng, Star" <star.zeng@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>,
"Lohr, Paul A" <paul.a.lohr@intel.com>
Subject: Re: [PATCH] PcAtChipsetPkg AcpiTimerLib: Get more accurate TSC Frequency
Date: Thu, 11 Aug 2016 02:42:27 +0000 [thread overview]
Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A1155E9AA0@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <1470883079-4472-1-git-send-email-star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
> -----Original Message-----
> From: Zeng, Star
> Sent: Thursday, August 11, 2016 10:38 AM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Lohr,
> Paul A <paul.a.lohr@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.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Paul A Lohr <paul.a.lohr@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Star Zeng <star.zeng@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
next prev parent reply other threads:[~2016-08-11 2:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-11 2:37 [PATCH] PcAtChipsetPkg AcpiTimerLib: Get more accurate TSC Frequency Star Zeng
2016-08-11 2:42 ` Gao, Liming [this message]
2016-08-11 5:01 ` Kinney, Michael D
2016-08-11 13:41 ` Brian J. Johnson
2016-08-12 1:07 ` Zeng, Star
2016-08-12 8:31 ` Paolo Bonzini
2016-08-12 8:43 ` Zeng, Star
2016-08-12 18:27 ` Kinney, Michael D
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A89E2EF3DFEDB4C8BFDE51014F606A1155E9AA0@shsmsx102.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox