From a674eea1c47a6aa0170b2beb07d4f2bbefc798e0 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 22 Dec 2016 19:41:14 +0800 Subject: BroxtonSiPkg: Add Cpu Include file and Library Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../Library/Private/PeiMpServiceLib/Microcode.c | 221 +++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Microcode.c') 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.
+ + 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 +#include + +/** + 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; +} + -- cgit v1.2.3