From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3DBC121CC534B for ; Thu, 6 Jul 2017 00:37:54 -0700 (PDT) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Jul 2017 00:39:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,316,1496127600"; d="scan'208";a="123445710" Received: from jfan12-desk.ccr.corp.intel.com ([10.239.158.57]) by fmsmga006.fm.intel.com with ESMTP; 06 Jul 2017 00:39:32 -0700 From: Jeff Fan To: edk2-devel@lists.01.org Cc: Michael D Kinney , Eric Dong , Ruiyu Ni Date: Thu, 6 Jul 2017 15:39:23 +0800 Message-Id: <20170706073923.12400-1-jeff.fan@intel.com> X-Mailer: git-send-email 2.9.3.windows.2 Subject: [PATCH] UefiCpuPkg/SecPeiDxeTimerLibUefiCpu: Add GetIntendFsbFrequency() X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Jul 2017 07:37:54 -0000 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 Cc: Eric Dong Cc: Ruiyu Ni Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan --- .../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.
+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
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 #include #include +#include +#include + +// +// 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