public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Jeff Fan <jeff.fan@intel.com>
To: edk2-devel@lists.01.org
Cc: Michael D Kinney <michael.d.kinney@intel.com>,
	Eric Dong <eric.dong@intel.com>, Ruiyu Ni <ruiyu.ni@intel.com>
Subject: [PATCH] UefiCpuPkg/SecPeiDxeTimerLibUefiCpu: Add GetIntendFsbFrequency()
Date: Thu,  6 Jul 2017 15:39:23 +0800	[thread overview]
Message-ID: <20170706073923.12400-1-jeff.fan@intel.com> (raw)

The current implementation gets CPU FSB frequency by PcdFSBClock. However, IA32
SDM defined accurate FSB for some specific processors. Actually, we could try to
get FSB frequency by hardware instead of by PcdFSBClock. If FSB frequency is not
documented by IA32 SDM, we still could get it by PcdFSBClock.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
---
 .../Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c | 114 ++++++++++++++++++++-
 1 file changed, 111 insertions(+), 3 deletions(-)

diff --git a/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c b/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c
index f703d7e..606ad0a 100644
--- a/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c
+++ b/UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/X86TimerLib.c
@@ -3,7 +3,7 @@
 
   This library uses the local APIC library so that it supports x2APIC mode.
   
-  Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2010 - 2017, 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
@@ -20,6 +20,108 @@
 #include <Library/PcdLib.h>
 #include <Library/DebugLib.h>
 #include <Library/LocalApicLib.h>
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+
+//
+// The following array is FSB frequencies defined in Pentinum 4 family, Core, Core 2
+// and Atom CPUs, its value unit is HZ.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32                          mPentinum4FSBFrequencies[] = {
+  266666667,
+  133333333,
+  200000000,
+  166666667,
+  333333333,
+  100000000,
+  400000000
+};
+
+//
+// The following array is FSB frequencies defined in SivlerMont, Airmont
+// CPUs, its value unit is HZ.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32                          mSivlerMontFSBFrequencies[] = {
+   83333333,
+  100000000,
+  133333333,
+  116666667,
+   80000000,
+   93333333,
+   90000000,
+   88888889,
+   87500000
+};
+
+/**
+  The function to get CPU intended FSB frequency.
+
+  This function reads the type of CPU by CPUID and returns FSB frequecny,
+
+  @retval CPU intended FSB frequency.
+
+**/
+UINT32
+GetIntendFsbFrequency (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX                   Eax;
+  CPUID_VERSION_INFO_ECX                   Ecx;
+  CPUID_VERSION_INFO_EDX                   Edx;
+  UINT32                                   DisplayedFamily;
+  UINT32                                   DisplayedModel;
+  MSR_PENTIUM_4_EBC_FREQUENCY_ID_REGISTER  Pentium4Msr;
+  MSR_CORE_FSB_FREQ_REGISTER               CoreMsr;
+  MSR_SILVERMONT_FSB_FREQ_REGISTER         SilvermontMsr;
+  UINT32                                   Freq;
+  UINTN                                    FrequencyIndex;
+
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, &Ecx.Uint32, &Edx.Uint32);
+
+  DisplayedFamily = Eax.Bits.FamilyId;
+  if (Eax.Bits.FamilyId == 0x0F) {
+    DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);
+  }
+
+  DisplayedModel = Eax.Bits.Model;
+  if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
+    DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);
+  }
+
+  Freq = 0;
+  if (IS_PENTIUM_4_PROCESSOR (DisplayedFamily, DisplayedModel)) {
+    Pentium4Msr.Uint64 = AsmReadMsr64 (MSR_PENTIUM_4_EBC_FREQUENCY_ID);
+    FrequencyIndex = Pentium4Msr.Bits.ScalableBusSpeed;
+    if (FrequencyIndex == 0 && DisplayedModel == 0x02) {
+      //
+      // FrequencyIndex:000B DisplayedModel:2 is 100 MHz
+      //
+      Freq = 100000000;
+    }
+    ASSERT (FrequencyIndex < (sizeof (mPentinum4FSBFrequencies) / sizeof (UINT32)));
+    Freq = mPentinum4FSBFrequencies[FrequencyIndex];
+  } else if (IS_CORE_PROCESSOR  (DisplayedFamily, DisplayedModel) ||
+             IS_CORE2_PROCESSOR (DisplayedFamily, DisplayedModel) ||
+             IS_ATOM_PROCESSOR  (DisplayedFamily, DisplayedModel)) {
+    CoreMsr.Uint64 = AsmReadMsr64 (MSR_CORE_FSB_FREQ);
+    FrequencyIndex = CoreMsr.Bits.ScalableBusSpeed;
+    ASSERT (FrequencyIndex < (sizeof (mPentinum4FSBFrequencies) / sizeof (UINT32)));
+    Freq = mPentinum4FSBFrequencies[FrequencyIndex];
+  } else if (IS_SILVERMONT_PROCESSOR (DisplayedFamily, DisplayedModel)) {
+    SilvermontMsr.Uint64 = AsmReadMsr64 (MSR_SILVERMONT_FSB_FREQ);
+    FrequencyIndex = SilvermontMsr.Bits.ScalableBusSpeed;
+    ASSERT (FrequencyIndex < (sizeof (mSivlerMontFSBFrequencies) / sizeof (UINT32)));
+    Freq = mSivlerMontFSBFrequencies[FrequencyIndex];
+  }
+
+  //
+  // If processor is not in supported list, then 0 will be return
+  //
+  return Freq;
+}
 
 /**
   Internal function to return the frequency of the local APIC timer.
@@ -33,10 +135,16 @@ InternalX86GetTimerFrequency (
   VOID
   )
 {
-  UINTN Divisor;
+  UINT32 Freq;
+  UINTN  Divisor;
+
+  Freq = GetIntendFsbFrequency ();
+  if (Freq == 0) {
+    Freq = PcdGet32(PcdFSBClock);
+  }
 
   GetApicTimerState (&Divisor, NULL, NULL);
-  return PcdGet32(PcdFSBClock) / (UINT32)Divisor;
+  return Freq / (UINT32)Divisor;
 }
 
 /**
-- 
2.9.3.windows.2



                 reply	other threads:[~2017-07-06  7:37 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20170706073923.12400-1-jeff.fan@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