UefiCpuPkg/MpInitLib: Produce EDKII microcode patch HOB

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2430

This commit will update the MpInitLib to:

A. Collect the base address and size information after microcode patches
   being loaded into memory;
B. Collect the detected microcode patch for each processor within system;
C. Based on the collected information, produce the EDKII microcode patch
   HOB.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Hao A Wu <hao.a.wu@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Hao A Wu 2019-12-23 14:32:49 +08:00 committed by mergify[bot]
parent 253909974a
commit e1ed55738e
5 changed files with 100 additions and 8 deletions

View File

@ -65,13 +65,15 @@ GetCurrentMicrocodeSignature (
It does not guarantee that the data has not been modified. It does not guarantee that the data has not been modified.
CPU has its own mechanism to verify Microcode Binary part. CPU has its own mechanism to verify Microcode Binary part.
@param[in] CpuMpData The pointer to CPU MP Data structure. @param[in] CpuMpData The pointer to CPU MP Data structure.
@param[in] IsBspCallIn Indicate whether the caller is BSP or not. @param[in] ProcessorNumber The handle number of the processor. The range is
from 0 to the total number of logical processors
minus 1.
**/ **/
VOID VOID
MicrocodeDetect ( MicrocodeDetect (
IN CPU_MP_DATA *CpuMpData, IN CPU_MP_DATA *CpuMpData,
IN BOOLEAN IsBspCallIn IN UINTN ProcessorNumber
) )
{ {
UINT32 ExtendedTableLength; UINT32 ExtendedTableLength;
@ -93,6 +95,7 @@ MicrocodeDetect (
MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr; MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;
UINT32 ProcessorFlags; UINT32 ProcessorFlags;
UINT32 ThreadId; UINT32 ThreadId;
BOOLEAN IsBspCallIn;
// //
// set ProcessorFlags to suppress incorrect compiler/analyzer warnings // set ProcessorFlags to suppress incorrect compiler/analyzer warnings
@ -107,6 +110,7 @@ MicrocodeDetect (
} }
CurrentRevision = GetCurrentMicrocodeSignature (); CurrentRevision = GetCurrentMicrocodeSignature ();
IsBspCallIn = (ProcessorNumber == (UINTN)CpuMpData->BspNumber) ? TRUE : FALSE;
if (CurrentRevision != 0 && !IsBspCallIn) { if (CurrentRevision != 0 && !IsBspCallIn) {
// //
// Skip loading microcode if it has been loaded successfully // Skip loading microcode if it has been loaded successfully
@ -295,6 +299,16 @@ MicrocodeDetect (
} while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd)); } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
Done: Done:
if (LatestRevision != 0) {
//
// Save the detected microcode patch entry address (including the
// microcode patch header) for each processor.
// It will be used when building the microcode patch cache HOB.
//
CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =
(UINTN) MicrocodeData - sizeof (CPU_MICROCODE_HEADER);
}
if (LatestRevision > CurrentRevision) { if (LatestRevision > CurrentRevision) {
// //
// BIOS only authenticate updates that contain a numerically larger revision // BIOS only authenticate updates that contain a numerically larger revision

View File

@ -399,12 +399,16 @@ ApInitializeSync (
) )
{ {
CPU_MP_DATA *CpuMpData; CPU_MP_DATA *CpuMpData;
UINTN ProcessorNumber;
EFI_STATUS Status;
CpuMpData = (CPU_MP_DATA *) Buffer; CpuMpData = (CPU_MP_DATA *) Buffer;
Status = GetProcessorNumber (CpuMpData, &ProcessorNumber);
ASSERT_EFI_ERROR (Status);
// //
// Load microcode on AP // Load microcode on AP
// //
MicrocodeDetect (CpuMpData, FALSE); MicrocodeDetect (CpuMpData, ProcessorNumber);
// //
// Sync BSP's MTRR table to AP // Sync BSP's MTRR table to AP
// //
@ -1761,7 +1765,7 @@ MpInitLibInitialize (
// //
// Detect and apply Microcode on BSP // Detect and apply Microcode on BSP
// //
MicrocodeDetect (CpuMpData, TRUE); MicrocodeDetect (CpuMpData, CpuMpData->BspNumber);
// //
// Store BSP's MTRR setting // Store BSP's MTRR setting
// //

View File

@ -138,6 +138,7 @@ typedef struct {
EFI_EVENT WaitEvent; EFI_EVENT WaitEvent;
UINT32 ProcessorSignature; UINT32 ProcessorSignature;
UINT8 PlatformId; UINT8 PlatformId;
UINT64 MicrocodeEntryAddr;
} CPU_AP_DATA; } CPU_AP_DATA;
// //
@ -580,13 +581,15 @@ CheckAndUpdateApsStatus (
/** /**
Detect whether specified processor can find matching microcode patch and load it. Detect whether specified processor can find matching microcode patch and load it.
@param[in] CpuMpData The pointer to CPU MP Data structure. @param[in] CpuMpData The pointer to CPU MP Data structure.
@param[in] IsBspCallIn Indicate whether the caller is BSP or not. @param[in] ProcessorNumber The handle number of the processor. The range is
from 0 to the total number of logical processors
minus 1.
**/ **/
VOID VOID
MicrocodeDetect ( MicrocodeDetect (
IN CPU_MP_DATA *CpuMpData, IN CPU_MP_DATA *CpuMpData,
IN BOOLEAN IsBspCallIn IN UINTN ProcessorNumber
); );
/** /**
@ -619,5 +622,20 @@ EnableDebugAgent (
VOID VOID
); );
/**
Find the current Processor number by APIC ID.
@param[in] CpuMpData Pointer to PEI CPU MP Data
@param[out] ProcessorNumber Return the pocessor number found
@retval EFI_SUCCESS ProcessorNumber is found and returned.
@retval EFI_NOT_FOUND ProcessorNumber is not found.
**/
EFI_STATUS
GetProcessorNumber (
IN CPU_MP_DATA *CpuMpData,
OUT UINTN *ProcessorNumber
);
#endif #endif

View File

@ -63,3 +63,4 @@
[Guids] [Guids]
gEdkiiS3SmmInitDoneGuid gEdkiiS3SmmInitDoneGuid
gEdkiiMicrocodePatchHobGuid

View File

@ -9,6 +9,7 @@
#include "MpLib.h" #include "MpLib.h"
#include <Library/PeiServicesLib.h> #include <Library/PeiServicesLib.h>
#include <Guid/S3SmmInitDone.h> #include <Guid/S3SmmInitDone.h>
#include <Guid/MicrocodePatchHob.h>
/** /**
S3 SMM Init Done notification function. S3 SMM Init Done notification function.
@ -290,6 +291,59 @@ CheckAndUpdateApsStatus (
{ {
} }
/**
Build the microcode patch HOB that contains the base address and size of the
microcode patch stored in the memory.
@param[in] CpuMpData Pointer to the CPU_MP_DATA structure.
**/
VOID
BuildMicrocodeCacheHob (
IN CPU_MP_DATA *CpuMpData
)
{
EDKII_MICROCODE_PATCH_HOB *MicrocodeHob;
UINTN HobDataLength;
UINT32 Index;
HobDataLength = sizeof (EDKII_MICROCODE_PATCH_HOB) +
sizeof (UINT64) * CpuMpData->CpuCount;
MicrocodeHob = AllocatePool (HobDataLength);
if (MicrocodeHob == NULL) {
ASSERT (FALSE);
return;
}
//
// Store the information of the memory region that holds the microcode patches.
//
MicrocodeHob->MicrocodePatchAddress = CpuMpData->MicrocodePatchAddress;
MicrocodeHob->MicrocodePatchRegionSize = CpuMpData->MicrocodePatchRegionSize;
//
// Store the detected microcode patch for each processor as well.
//
MicrocodeHob->ProcessorCount = CpuMpData->CpuCount;
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {
MicrocodeHob->ProcessorSpecificPatchOffset[Index] =
CpuMpData->CpuData[Index].MicrocodeEntryAddr - CpuMpData->MicrocodePatchAddress;
} else {
MicrocodeHob->ProcessorSpecificPatchOffset[Index] = MAX_UINT64;
}
}
BuildGuidDataHob (
&gEdkiiMicrocodePatchHobGuid,
MicrocodeHob,
HobDataLength
);
return;
}
/** /**
Initialize global data for MP support. Initialize global data for MP support.
@ -302,6 +356,7 @@ InitMpGlobalData (
{ {
EFI_STATUS Status; EFI_STATUS Status;
BuildMicrocodeCacheHob (CpuMpData);
SaveCpuMpData (CpuMpData); SaveCpuMpData (CpuMpData);
/// ///