/** @file\r
Implementation of loading microcode on processors.\r
\r
- Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
/**\r
Detect whether specified processor can find matching microcode patch and load it.\r
\r
- @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+ @param[in] CpuMpData The pointer to CPU MP Data structure.\r
+ @param[in] IsBspCallIn Indicate whether the caller is BSP or not.\r
**/\r
VOID\r
MicrocodeDetect (\r
- IN CPU_MP_DATA *CpuMpData\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ IN BOOLEAN IsBspCallIn\r
)\r
{\r
UINT32 ExtendedTableLength;\r
BOOLEAN CorrectMicrocode;\r
VOID *MicrocodeData;\r
MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;\r
+ UINT32 ProcessorFlags;\r
+ UINT32 ThreadId;\r
\r
if (CpuMpData->MicrocodePatchRegionSize == 0) {\r
//\r
}\r
\r
CurrentRevision = GetCurrentMicrocodeSignature ();\r
- if (CurrentRevision != 0) {\r
+ if (CurrentRevision != 0 && !IsBspCallIn) {\r
//\r
// Skip loading microcode if it has been loaded successfully\r
//\r
return;\r
}\r
\r
+ GetProcessorLocationByApicId (GetInitialApicId (), NULL, NULL, &ThreadId);\r
+ if (ThreadId != 0) {\r
+ //\r
+ // Skip loading microcode if it is not the first thread in one core.\r
+ //\r
+ return;\r
+ }\r
+\r
ExtendedTableLength = 0;\r
//\r
// Here data of CPUID leafs have not been collected into context buffer, so\r
- // GetProcessorCpuid() cannot be used here to retrieve sCPUID data.\r
+ // GetProcessorCpuid() cannot be used here to retrieve CPUID data.\r
//\r
AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);\r
\r
PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);\r
PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;\r
\r
+ //\r
+ // Check whether AP has same processor with BSP.\r
+ // If yes, direct use microcode info saved by BSP.\r
+ //\r
+ if (!IsBspCallIn) {\r
+ if ((CpuMpData->ProcessorSignature == Eax.Uint32) &&\r
+ (CpuMpData->ProcessorFlags & (1 << PlatformId)) != 0) {\r
+ MicrocodeData = (VOID *)(UINTN) CpuMpData->MicrocodeDataAddress;\r
+ LatestRevision = CpuMpData->MicrocodeRevision;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
LatestRevision = 0;\r
MicrocodeData = NULL;\r
MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize);\r
}\r
if (CheckSum32 == 0) {\r
CorrectMicrocode = TRUE;\r
+ ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags;\r
}\r
} else if ((MicrocodeEntryPoint->DataSize != 0) &&\r
(MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {\r
// Find one\r
//\r
CorrectMicrocode = TRUE;\r
+ ProcessorFlags = ExtendedTable->ProcessorFlag;\r
break;\r
}\r
}\r
MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);\r
} while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));\r
\r
+Done:\r
if (LatestRevision > CurrentRevision) {\r
//\r
// BIOS only authenticate updates that contain a numerically larger revision\r
ReleaseSpinLock(&CpuMpData->MpLock);\r
}\r
}\r
+\r
+ if (IsBspCallIn && (LatestRevision != 0)) {\r
+ //\r
+ // Save BSP processor info and microcode info for later AP use.\r
+ //\r
+ CpuMpData->ProcessorSignature = Eax.Uint32;\r
+ CpuMpData->ProcessorFlags = ProcessorFlags;\r
+ CpuMpData->MicrocodeDataAddress = (UINTN) MicrocodeData;\r
+ CpuMpData->MicrocodeRevision = LatestRevision;\r
+ DEBUG ((DEBUG_INFO, "BSP Microcode:: signature [0x%08x], ProcessorFlags [0x%08x], \\r
+ MicroData [0x%08x], Revision [0x%08x]\n", Eax.Uint32, ProcessorFlags, (UINTN) MicrocodeData, LatestRevision));\r
+ }\r
}\r