UefiCpuPkg: Remove FIT based microcode shadow logic from MpInitLib.

Commit c7c964b and dd01704 add header file for FIT table and update
MpInitLib to support FIT based microcode shadow operation. There are
comments that FIT is Intel specific specification instead of industry
standard, which should not be placed in EDK2 MdePkg and UefiCpuPkg.
So this patch adds a platform PPI for the microcode shadow logic, and
remove the FIT related code from EDK2.
The FIT based microcode shadow support will be implemented as a new
platform PEIM in IntelSiliconPkg in edk2-platforms.
This patch doesn't provide a DXE version shadow microcode protocol,
a platform which only uses DxeMpInitLib instance only supports PCD
based microcode shadowing.

A detailed design doc can be found here:
https://edk2.groups.io/g/devel/files/Designs/2020/0214/Support%20
the%202nd%20Microcode%20FV%20Flash%20Region.pdf

TEST: Tested on FIT enabled platform.
BZ: https://tianocore.acgmultimedia.com/show_bug.cgi?id=2449

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Siyuan Fu <siyuan.fu@intel.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Siyuan Fu 2020-02-11 21:30:48 +08:00 committed by mergify[bot]
parent 534fcb84de
commit c788c2b1ad
9 changed files with 183 additions and 123 deletions

View File

@ -0,0 +1,66 @@
/** @file
This file declares EDKII Shadow Microcode PPI.
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __PPI_SHADOW_MICROCODE_H__
#define __PPI_SHADOW_MICROCODE_H__
#define EDKII_PEI_SHADOW_MICROCODE_PPI_GUID \
{ \
0x430f6965, 0x9a69, 0x41c5, { 0x93, 0xed, 0x8b, 0xf0, 0x64, 0x35, 0xc1, 0xc6 } \
}
typedef struct _EDKII_PEI_SHADOW_MICROCODE_PPI EDKII_PEI_SHADOW_MICROCODE_PPI;
typedef struct {
UINT32 ProcessorSignature;
UINT8 PlatformId;
} EDKII_PEI_MICROCODE_CPU_ID;
/**
Shadow microcode update patches to memory.
The function is used for shadowing microcode update patches to a continuous memory.
It shall allocate memory buffer and only shadow the microcode patches for those
processors specified by MicrocodeCpuId array. The checksum verification may be
skiped in this function so the caller must perform checksum verification before
using the microcode patches in returned memory buffer.
@param[in] This The PPI instance pointer.
@param[in] CpuIdCount Number of elements in MicrocodeCpuId array.
@param[in] MicrocodeCpuId A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
structures.
@param[out] BufferSize Pointer to receive the total size of Buffer.
@param[out] Buffer Pointer to receive address of allocated memory
with microcode patches data in it.
@retval EFI_SUCCESS The microcode has been shadowed to memory.
@retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_PEI_SHADOW_MICROCODE) (
IN EDKII_PEI_SHADOW_MICROCODE_PPI *This,
IN UINTN CpuIdCount,
IN EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId,
OUT UINTN *BufferSize,
OUT VOID **Buffer
);
///
/// This PPI is installed by some platform or chipset-specific PEIM that
/// abstracts handling microcode shadow support.
///
struct _EDKII_PEI_SHADOW_MICROCODE_PPI {
EDKII_PEI_SHADOW_MICROCODE ShadowMicrocode;
};
extern EFI_GUID gEdkiiPeiShadowMicrocodePpiGuid;
#endif

View File

@ -69,6 +69,5 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES

View File

@ -1,7 +1,7 @@
/** @file /** @file
MP initialize support functions for DXE phase. MP initialize support functions for DXE phase.
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR> Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@ -816,3 +816,27 @@ MpInitLibEnableDisableAP (
return Status; return Status;
} }
/**
This funtion will try to invoke platform specific microcode shadow logic to
relocate microcode update patches into memory.
@param[in] CpuMpData The pointer to CPU MP Data structure.
@retval EFI_SUCCESS Shadow microcode success.
@retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
@retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
PPI/Protocol.
**/
EFI_STATUS
PlatformShadowMicrocode (
IN OUT CPU_MP_DATA *CpuMpData
)
{
//
// There is no DXE version of platform shadow microcode protocol so far.
// A platform which only uses DxeMpInitLib instance could only supports
// the PCD based microcode shadowing.
//
return EFI_UNSUPPORTED;
}

View File

@ -619,109 +619,6 @@ OnExit:
return; return;
} }
/**
Shadow the required microcode patches data into memory according to FIT microcode entry.
@param[in, out] CpuMpData The pointer to CPU MP Data structure.
@return EFI_SUCCESS Microcode patch is shadowed into memory.
@return EFI_UNSUPPORTED FIT based microcode shadowing is not supported.
@return EFI_OUT_OF_RESOURCES No enough memory resource.
@return EFI_NOT_FOUND There is something wrong in FIT microcode entry.
**/
EFI_STATUS
ShadowMicrocodePatchByFit (
IN OUT CPU_MP_DATA *CpuMpData
)
{
UINT64 FitPointer;
FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
UINT32 EntryNum;
UINT32 Index;
MICROCODE_PATCH_INFO *PatchInfoBuffer;
UINTN MaxPatchNumber;
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
UINTN PatchCount;
UINTN TotalSize;
UINTN TotalLoadSize;
if (!FeaturePcdGet (PcdCpuShadowMicrocodeByFit)) {
return EFI_UNSUPPORTED;
}
FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
if ((FitPointer == 0) ||
(FitPointer == 0xFFFFFFFFFFFFFFFF) ||
(FitPointer == 0xEEEEEEEEEEEEEEEE)) {
//
// No FIT table.
//
ASSERT (FALSE);
return EFI_NOT_FOUND;
}
FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
(FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
//
// Invalid FIT table, treat it as no FIT table.
//
ASSERT (FALSE);
return EFI_NOT_FOUND;
}
EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
//
// Calculate microcode entry number
//
MaxPatchNumber = 0;
for (Index = 0; Index < EntryNum; Index++) {
if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
MaxPatchNumber++;
}
}
if (MaxPatchNumber == 0) {
return EFI_NOT_FOUND;
}
PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));
if (PatchInfoBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Fill up microcode patch info buffer according to FIT table.
//
PatchCount = 0;
TotalLoadSize = 0;
for (Index = 0; Index < EntryNum; Index++) {
if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) FitEntry[Index].Address;
TotalSize = (MicrocodeEntryPoint->DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {
PatchInfoBuffer[PatchCount].Address = (UINTN) MicrocodeEntryPoint;
PatchInfoBuffer[PatchCount].Size = TotalSize;
TotalLoadSize += TotalSize;
PatchCount++;
}
}
}
if (PatchCount != 0) {
DEBUG ((
DEBUG_INFO,
"%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
__FUNCTION__, PatchCount, TotalLoadSize
));
ShadowMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);
}
FreePool (PatchInfoBuffer);
return EFI_SUCCESS;
}
/** /**
Shadow the required microcode patches data into memory. Shadow the required microcode patches data into memory.
@ -734,7 +631,7 @@ ShadowMicrocodeUpdatePatch (
{ {
EFI_STATUS Status; EFI_STATUS Status;
Status = ShadowMicrocodePatchByFit (CpuMpData); Status = PlatformShadowMicrocode (CpuMpData);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
ShadowMicrocodePatchByPcd (CpuMpData); ShadowMicrocodePatchByPcd (CpuMpData);
} }

View File

@ -31,9 +31,6 @@
#include <Guid/MicrocodePatchHob.h> #include <Guid/MicrocodePatchHob.h>
#include <IndustryStandard/FirmwareInterfaceTable.h>
#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P') #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
#define CPU_INIT_MP_LIB_HOB_GUID \ #define CPU_INIT_MP_LIB_HOB_GUID \
@ -657,5 +654,21 @@ GetProcessorNumber (
OUT UINTN *ProcessorNumber OUT UINTN *ProcessorNumber
); );
/**
This funtion will try to invoke platform specific microcode shadow logic to
relocate microcode update patches into memory.
@param[in] CpuMpData The pointer to CPU MP Data structure.
@retval EFI_SUCCESS Shadow microcode success.
@retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
@retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
PPI/Protocol.
**/
EFI_STATUS
PlatformShadowMicrocode (
IN OUT CPU_MP_DATA *CpuMpData
);
#endif #endif

View File

@ -60,7 +60,9 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit ## CONSUMES
[Ppis]
gEdkiiPeiShadowMicrocodePpiGuid ## SOMETIMES_CONSUMES
[Guids] [Guids]
gEdkiiS3SmmInitDoneGuid gEdkiiS3SmmInitDoneGuid

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 <Ppi/ShadowMicrocode.h>
/** /**
S3 SMM Init Done notification function. S3 SMM Init Done notification function.
@ -639,4 +640,71 @@ MpInitLibEnableDisableAP (
return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag); return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
} }
/**
This funtion will try to invoke platform specific microcode shadow logic to
relocate microcode update patches into memory.
@param[in] CpuMpData The pointer to CPU MP Data structure.
@retval EFI_SUCCESS Shadow microcode success.
@retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
@retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
PPI/Protocol.
**/
EFI_STATUS
PlatformShadowMicrocode (
IN OUT CPU_MP_DATA *CpuMpData
)
{
EFI_STATUS Status;
EDKII_PEI_SHADOW_MICROCODE_PPI *ShadowMicrocodePpi;
UINTN CpuCount;
EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId;
UINTN Index;
UINTN BufferSize;
VOID *Buffer;
Status = PeiServicesLocatePpi (
&gEdkiiPeiShadowMicrocodePpiGuid,
0,
NULL,
(VOID **) &ShadowMicrocodePpi
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
CpuCount = CpuMpData->CpuCount;
MicrocodeCpuId = (EDKII_PEI_MICROCODE_CPU_ID *) AllocateZeroPool (sizeof (EDKII_PEI_MICROCODE_CPU_ID) * CpuCount);
if (MicrocodeCpuId == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
MicrocodeCpuId[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;
MicrocodeCpuId[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;
}
Status = ShadowMicrocodePpi->ShadowMicrocode (
ShadowMicrocodePpi,
CpuCount,
MicrocodeCpuId,
&BufferSize,
&Buffer
);
FreePool (MicrocodeCpuId);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
CpuMpData->MicrocodePatchAddress = (UINTN) Buffer;
CpuMpData->MicrocodePatchRegionSize = BufferSize;
DEBUG ((
DEBUG_INFO,
"%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
__FUNCTION__, CpuMpData->MicrocodePatchAddress, CpuMpData->MicrocodePatchRegionSize
));
return EFI_SUCCESS;
}

View File

@ -1,7 +1,7 @@
## @file UefiCpuPkg.dec ## @file UefiCpuPkg.dec
# This Package provides UEFI compatible CPU modules and libraries. # This Package provides UEFI compatible CPU modules and libraries.
# #
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -81,6 +81,9 @@
[Ppis] [Ppis]
gEdkiiPeiMpServices2PpiGuid = { 0x5cb9cb3d, 0x31a4, 0x480c, { 0x94, 0x98, 0x29, 0xd2, 0x69, 0xba, 0xcf, 0xba}} gEdkiiPeiMpServices2PpiGuid = { 0x5cb9cb3d, 0x31a4, 0x480c, { 0x94, 0x98, 0x29, 0xd2, 0x69, 0xba, 0xcf, 0xba}}
## Include/Ppi/ShadowMicrocode.h
gEdkiiPeiShadowMicrocodePpiGuid = { 0x430f6965, 0x9a69, 0x41c5, { 0x93, 0xed, 0x8b, 0xf0, 0x64, 0x35, 0xc1, 0xc6 }}
[PcdsFeatureFlag] [PcdsFeatureFlag]
## Indicates if SMM Profile will be enabled. ## Indicates if SMM Profile will be enabled.
# If enabled, instruction executions in and data accesses to memory outside of SMRAM will be logged. # If enabled, instruction executions in and data accesses to memory outside of SMRAM will be logged.
@ -139,12 +142,6 @@
# @Prompt Lock SMM Feature Control MSR. # @Prompt Lock SMM Feature Control MSR.
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B
## Indicates if FIT based microcode shadowing will be enabled.<BR><BR>
# TRUE - FIT base microcode shadowing will be enabled.<BR>
# FALSE - FIT base microcode shadowing will be disabled.<BR>
# @Prompt FIT based microcode shadowing.
gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit|FALSE|BOOLEAN|0x3213210D
[PcdsFixedAtBuild] [PcdsFixedAtBuild]
## List of exception vectors which need switching stack. ## List of exception vectors which need switching stack.
# This PCD will only take into effect if PcdCpuStackGuard is enabled. # This PCD will only take into effect if PcdCpuStackGuard is enabled.

View File

@ -100,12 +100,6 @@
"TRUE - locked.<BR>\n" "TRUE - locked.<BR>\n"
"FALSE - unlocked.<BR>" "FALSE - unlocked.<BR>"
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuShadowMicrocodeByFit_PROMPT #language en-US "FIT based microcode shadowing"
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuShadowMicrocodeByFit_HELP #language en-US "Indicates if FIT based microcode shadowing will be enabled.<BR><BR>\n"
"TRUE - FIT base microcode shadowing will be enabled.<BR>\n"
"FALSE - FIT base microcode shadowing will be disabled.<BR>"
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdPeiTemporaryRamStackSize_PROMPT #language en-US "Stack size in the temporary RAM" #string STR_gUefiCpuPkgTokenSpaceGuid_PcdPeiTemporaryRamStackSize_PROMPT #language en-US "Stack size in the temporary RAM"
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdPeiTemporaryRamStackSize_HELP #language en-US "Specifies stack size in the temporary RAM. 0 means half of TemporaryRamSize." #string STR_gUefiCpuPkgTokenSpaceGuid_PcdPeiTemporaryRamStackSize_HELP #language en-US "Specifies stack size in the temporary RAM. 0 means half of TemporaryRamSize."