summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-12-22 19:41:14 +0800
committerGuo Mang <mang.guo@intel.com>2016-12-26 19:15:02 +0800
commita674eea1c47a6aa0170b2beb07d4f2bbefc798e0 (patch)
tree3db2b004775c74c311c7c5b7b3998f0c6dc91c32 /Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c
parentf0a77159beb39438f311993bf6cd4136aa7e02fc (diff)
downloadedk2-platforms-a674eea1c47a6aa0170b2beb07d4f2bbefc798e0.tar.xz
BroxtonSiPkg: Add Cpu Include file and Library
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c
new file mode 100644
index 0000000000..1b4a0b581e
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c
@@ -0,0 +1,221 @@
+/** @file
+ CPU microcode update library.
+
+ Copyright (c) 1999 - 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Private/Library/MpServiceLib.h>
+#include <CpuRegs.h>
+
+/**
+ Check if this is non-core processor - HT AP thread
+
+ @retval TRUE If this is HT AP thread
+ @retval FALSE If this is core thread
+
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ )
+{
+ UINT32 ApicID;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT8 CpuCount;
+ UINT8 CoreCount;
+ UINT8 CpuPerCore;
+ UINT32 Mask;
+
+ ApicID = GetCpuApicId ();
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEdx & 0x10000000) == 0) {
+ return FALSE;
+ }
+
+ CpuCount = (UINT8) ((CpuidRegisters.RegEbx >> 16) & 0xff);
+ if (CpuCount == 1) {
+ return FALSE;
+ }
+
+ AsmCpuid (
+ CPUID_SIGNATURE,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if (CpuidRegisters.RegEax > 3) {
+
+ CoreCount = GetMaxSupportedCoreCount ();
+ } else {
+ CoreCount = 1;
+ }
+ //
+ // Assumes there is symmetry across core boundary, i.e. each core within a package has the same number of logical processors
+ //
+ if (CpuCount == CoreCount) {
+ return FALSE;
+ }
+
+ CpuPerCore = CpuCount / CoreCount;
+
+ //
+ // Assume 1 Core has no more than 8 threads
+ //
+ if (CpuPerCore == 2) {
+ Mask = 0x1;
+ } else if (CpuPerCore <= 4) {
+ Mask = 0x3;
+ } else {
+ Mask = 0x7;
+ }
+
+ if ((ApicID & Mask) == 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ Wait until all primary threads are done with the microcode load.
+
+ @param[in] ExchangeInfo Pointer to the exchange info buffer for output.
+
+**/
+VOID
+WaitForPrimaryThreadMcuUpdate (
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo
+ )
+{
+ UINTN CoreNumber;
+
+ CoreNumber = (UINTN) ((RShiftU64 (AsmReadMsr64 (MSR_CORE_THREAD_COUNT), 16)) & 0xffff);
+ if (IsSecondaryThread ()) {
+ while (ExchangeInfo->McuLoadCount < CoreNumber) {
+ CpuPause ();
+ }
+ }
+}
+
+
+/**
+ This will load the microcode to the processors.
+
+ @param[in] MicrocodeEntryPoint The microcode update pointer
+ @param[in, out] Revision The current (before load this microcode update) microcode revision
+ as output parameter, the microcode revision after microcode update is loaded
+
+ @retval EFI_SUCCESS Microcode loaded
+ @retval EFI_LOAD_ERROR Microcode not loaded
+
+**/
+EFI_STATUS
+LoadMicrocode (
+ IN CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN OUT UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NewRevision;
+
+ Status = EFI_SUCCESS;
+
+#ifdef EFI_DEBUG
+ if (IsBsp()) {
+ DEBUG ((DEBUG_INFO, "LoadMicrocode: Before load, revision = 0x%x\n", *Revision));
+ }
+#endif
+
+ //
+ // Load the Processor Microcode
+ //
+ AsmWriteMsr64 (
+ MSR_IA32_BIOS_UPDT_TRIG,
+ (UINT64) ((UINTN) MicrocodeEntryPoint + sizeof (CPU_MICROCODE_HEADER))
+ );
+
+ NewRevision = GetCpuUcodeRevision ();
+
+#ifdef EFI_DEBUG
+ if (IsBsp ()) {
+ DEBUG ((DEBUG_INFO, "LoadMicrocode: After load, revision = 0x%x\n", NewRevision));
+ }
+#endif
+
+ //
+ // Verify that the microcode has been loaded
+ //
+ if (NewRevision == *Revision) {
+ return EFI_LOAD_ERROR;
+ }
+ *Revision = MicrocodeEntryPoint->UpdateRevision;
+
+ return Status;
+}
+
+
+/**
+ This will check if the microcode address is valid for this processor, and if so, it will
+ load it to the processor.
+
+ @param[in] ExchangeInfo Pointer to the exchange info buffer for output.
+ @param[in] MicrocodeAddress The address of the microcode update binary (in memory).
+ @param[out] FailedRevision The microcode revision that fails to be loaded.
+
+ @retval EFI_SUCCESS A new microcode update is loaded.
+ @retval Other Due to some reason, no new microcode update is loaded.
+
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN CPU_MICROCODE_HEADER *MicrocodeAddress,
+ OUT UINT32 *FailedRevision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPUID_REGISTER Cpuid;
+ UINT32 UcodeRevision;
+ ACPI_CPU_DATA *mAcpiCpuData;
+
+ Status = EFI_NOT_FOUND;
+
+ mAcpiCpuData = (ACPI_CPU_DATA *) (ExchangeInfo->AcpiCpuDataAddress);
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &Cpuid.RegEax,
+ &Cpuid.RegEbx,
+ &Cpuid.RegEcx,
+ &Cpuid.RegEdx
+ );
+
+ WaitForPrimaryThreadMcuUpdate (ExchangeInfo);
+ UcodeRevision = GetCpuUcodeRevision ();
+
+ if (CheckMicrocode (Cpuid.RegEax, MicrocodeAddress, &UcodeRevision)) {
+ Status = LoadMicrocode (MicrocodeAddress, &UcodeRevision);
+ *FailedRevision = UcodeRevision;
+ }
+ InterlockedIncrement (&(ExchangeInfo->McuLoadCount));
+
+ return Status;
+}
+