]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg: Shadow microcode patch according to FIT microcode entry.
authorSiyuan Fu <siyuan.fu@intel.com>
Wed, 8 Jan 2020 03:22:30 +0000 (11:22 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 10 Jan 2020 06:20:42 +0000 (06:20 +0000)
The existing MpInitLib will shadow the microcode update patches from
flash to memory and this is done by searching microcode region specified
by PCD PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.
This brings a limition to platform FW that all the microcode patches must
be placed in one continuous flash space.

This patch shadows microcode update according to FIT microcode entries if
it's present, otherwise it will fallback to original logic (by PCD).

A new featured PCD gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit
is added for enabling/disabling this support.

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: Eric Dong <eric.dong@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
UefiCpuPkg/Library/MpInitLib/Microcode.c
UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
UefiCpuPkg/UefiCpuPkg.dec
UefiCpuPkg/UefiCpuPkg.uni

index cd912ab0c5ee483ed5a03cabe6675a1338cf2693..bf5d18d521e9491cd9b61bb40b01a6d2dfe9042b 100644 (file)
@@ -68,5 +68,6 @@
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize         ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode                       ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate                   ## SOMETIMES_CONSUMES\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit             ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard                  ## CONSUMES\r
 \r
index 8f4d4da40c76f5b1beab32af3c47e9389ea22585..9389e52ae519a1df30d16b5f30aa219cd6a29acb 100644 (file)
@@ -318,7 +318,7 @@ Done:
 }\r
 \r
 /**\r
-  Determine if a microcode patch will be loaded into memory.\r
+  Determine if a microcode patch matchs the specific processor signature and flag.\r
 \r
   @param[in]  CpuMpData             The pointer to CPU MP Data structure.\r
   @param[in]  ProcessorSignature    The processor signature field value\r
@@ -330,7 +330,7 @@ Done:
   @retval FALSE    The specified microcode patch will not be loaded.\r
 **/\r
 BOOLEAN\r
-IsMicrocodePatchNeedLoad (\r
+IsProcessorMatchedMicrocodePatch (\r
   IN CPU_MP_DATA                 *CpuMpData,\r
   IN UINT32                      ProcessorSignature,\r
   IN UINT32                      ProcessorFlags\r
@@ -351,7 +351,77 @@ IsMicrocodePatchNeedLoad (
 }\r
 \r
 /**\r
-  Actual worker function that loads the required microcode patches into memory.\r
+  Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode\r
+  patch header with the CPUID and PlatformID of the processors within\r
+  system to decide if it will be copied into memory.\r
+\r
+  @param[in]  CpuMpData             The pointer to CPU MP Data structure.\r
+  @param[in]  MicrocodeEntryPoint   The pointer to the microcode patch header.\r
+\r
+  @retval TRUE     The specified microcode patch need to be loaded.\r
+  @retval FALSE    The specified microcode patch dosen't need to be loaded.\r
+**/\r
+BOOLEAN\r
+IsMicrocodePatchNeedLoad (\r
+  IN CPU_MP_DATA                 *CpuMpData,\r
+  CPU_MICROCODE_HEADER           *MicrocodeEntryPoint\r
+  )\r
+{\r
+  BOOLEAN                                NeedLoad;\r
+  UINTN                                  DataSize;\r
+  UINTN                                  TotalSize;\r
+  CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;\r
+  UINT32                                 ExtendedTableCount;\r
+  CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;\r
+  UINTN                                  Index;\r
+\r
+  //\r
+  // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.\r
+  //\r
+  NeedLoad = IsProcessorMatchedMicrocodePatch (\r
+               CpuMpData,\r
+               MicrocodeEntryPoint->ProcessorSignature.Uint32,\r
+               MicrocodeEntryPoint->ProcessorFlags\r
+               );\r
+\r
+  //\r
+  // If the Extended Signature Table exists, check if the processor is in the\r
+  // support list\r
+  //\r
+  DataSize  = MicrocodeEntryPoint->DataSize;\r
+  TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
+  if ((!NeedLoad) && (DataSize != 0) &&\r
+      (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +\r
+                              sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {\r
+    ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
+                            + DataSize + sizeof (CPU_MICROCODE_HEADER));\r
+    ExtendedTableCount  = ExtendedTableHeader->ExtendedSignatureCount;\r
+    ExtendedTable       = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
+\r
+    for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
+      //\r
+      // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended\r
+      // Signature Table entry with the CPUID and PlatformID of the processors\r
+      // within system to decide if it will be copied into memory\r
+      //\r
+      NeedLoad = IsProcessorMatchedMicrocodePatch (\r
+                   CpuMpData,\r
+                   ExtendedTable->ProcessorSignature.Uint32,\r
+                   ExtendedTable->ProcessorFlag\r
+                   );\r
+      if (NeedLoad) {\r
+        break;\r
+      }\r
+      ExtendedTable ++;\r
+    }\r
+  }\r
+\r
+  return NeedLoad;\r
+}\r
+\r
+\r
+/**\r
+  Actual worker function that shadows the required microcode patches into memory.\r
 \r
   @param[in, out]  CpuMpData        The pointer to CPU MP Data structure.\r
   @param[in]       Patches          The pointer to an array of information on\r
@@ -363,7 +433,7 @@ IsMicrocodePatchNeedLoad (
                                     to be loaded.\r
 **/\r
 VOID\r
-LoadMicrocodePatchWorker (\r
+ShadowMicrocodePatchWorker (\r
   IN OUT CPU_MP_DATA             *CpuMpData,\r
   IN     MICROCODE_PATCH_INFO    *Patches,\r
   IN     UINTN                   PatchCount,\r
@@ -390,7 +460,6 @@ LoadMicrocodePatchWorker (
       (VOID *) Patches[Index].Address,\r
       Patches[Index].Size\r
       );\r
-\r
     Walker += Patches[Index].Size;\r
   }\r
 \r
@@ -410,12 +479,13 @@ LoadMicrocodePatchWorker (
 }\r
 \r
 /**\r
-  Load the required microcode patches data into memory.\r
+  Shadow the required microcode patches data into memory according to PCD\r
+  PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.\r
 \r
   @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.\r
 **/\r
 VOID\r
-LoadMicrocodePatch (\r
+ShadowMicrocodePatchByPcd (\r
   IN OUT CPU_MP_DATA             *CpuMpData\r
   )\r
 {\r
@@ -423,15 +493,10 @@ LoadMicrocodePatch (
   UINTN                                  MicrocodeEnd;\r
   UINTN                                  DataSize;\r
   UINTN                                  TotalSize;\r
-  CPU_MICROCODE_EXTENDED_TABLE_HEADER    *ExtendedTableHeader;\r
-  UINT32                                 ExtendedTableCount;\r
-  CPU_MICROCODE_EXTENDED_TABLE           *ExtendedTable;\r
   MICROCODE_PATCH_INFO                   *PatchInfoBuffer;\r
   UINTN                                  MaxPatchNumber;\r
   UINTN                                  PatchCount;\r
   UINTN                                  TotalLoadSize;\r
-  UINTN                                  Index;\r
-  BOOLEAN                                NeedLoad;\r
 \r
   //\r
   // Initialize the microcode patch related fields in CpuMpData as the values\r
@@ -487,55 +552,7 @@ LoadMicrocodePatch (
       continue;\r
     }\r
 \r
-    //\r
-    // Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode\r
-    // patch header with the CPUID and PlatformID of the processors within\r
-    // system to decide if it will be copied into memory\r
-    //\r
-    NeedLoad = IsMicrocodePatchNeedLoad (\r
-                 CpuMpData,\r
-                 MicrocodeEntryPoint->ProcessorSignature.Uint32,\r
-                 MicrocodeEntryPoint->ProcessorFlags\r
-                 );\r
-\r
-    //\r
-    // If the Extended Signature Table exists, check if the processor is in the\r
-    // support list\r
-    //\r
-    if ((!NeedLoad) && (DataSize != 0) &&\r
-        (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +\r
-                                sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {\r
-      ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)\r
-                              + DataSize + sizeof (CPU_MICROCODE_HEADER));\r
-      ExtendedTableCount  = ExtendedTableHeader->ExtendedSignatureCount;\r
-      ExtendedTable       = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);\r
-\r
-      for (Index = 0; Index < ExtendedTableCount; Index ++) {\r
-        //\r
-        // Avoid access content beyond MicrocodeEnd\r
-        //\r
-        if ((UINTN) ExtendedTable > MicrocodeEnd - sizeof (CPU_MICROCODE_EXTENDED_TABLE)) {\r
-          break;\r
-        }\r
-\r
-        //\r
-        // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended\r
-        // Signature Table entry with the CPUID and PlatformID of the processors\r
-        // within system to decide if it will be copied into memory\r
-        //\r
-        NeedLoad = IsMicrocodePatchNeedLoad (\r
-                     CpuMpData,\r
-                     ExtendedTable->ProcessorSignature.Uint32,\r
-                     ExtendedTable->ProcessorFlag\r
-                     );\r
-        if (NeedLoad) {\r
-          break;\r
-        }\r
-        ExtendedTable ++;\r
-      }\r
-    }\r
-\r
-    if (NeedLoad) {\r
+    if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {\r
       PatchCount++;\r
       if (PatchCount > MaxPatchNumber) {\r
         //\r
@@ -581,7 +598,7 @@ LoadMicrocodePatch (
       __FUNCTION__, PatchCount, TotalLoadSize\r
       ));\r
 \r
-    LoadMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
+    ShadowMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
   }\r
 \r
 OnExit:\r
@@ -590,3 +607,124 @@ OnExit:
   }\r
   return;\r
 }\r
+\r
+/**\r
+  Shadow the required microcode patches data into memory according to FIT microcode entry.\r
+\r
+  @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.\r
+\r
+  @return EFI_SUCCESS           Microcode patch is shadowed into memory.\r
+  @return EFI_UNSUPPORTED       FIT based microcode shadowing is not supported.\r
+  @return EFI_OUT_OF_RESOURCES  No enough memory resource.\r
+  @return EFI_NOT_FOUND         There is something wrong in FIT microcode entry.\r
+\r
+**/\r
+EFI_STATUS\r
+ShadowMicrocodePatchByFit (\r
+  IN OUT CPU_MP_DATA             *CpuMpData\r
+  )\r
+{\r
+  UINT64                            FitPointer;\r
+  FIRMWARE_INTERFACE_TABLE_ENTRY    *FitEntry;\r
+  UINT32                            EntryNum;\r
+  UINT32                            Index;\r
+  MICROCODE_PATCH_INFO              *PatchInfoBuffer;\r
+  UINTN                             MaxPatchNumber;\r
+  CPU_MICROCODE_HEADER              *MicrocodeEntryPoint;\r
+  UINTN                             PatchCount;\r
+  UINTN                             TotalSize;\r
+  UINTN                             TotalLoadSize;\r
+\r
+  if (!FeaturePcdGet (PcdCpuShadowMicrocodeByFit)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;\r
+  if ((FitPointer == 0) ||\r
+      (FitPointer == 0xFFFFFFFFFFFFFFFF) ||\r
+      (FitPointer == 0xEEEEEEEEEEEEEEEE)) {\r
+    //\r
+    // No FIT table.\r
+    //\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;\r
+  if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||\r
+      (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {\r
+    //\r
+    // Invalid FIT table, treat it as no FIT table.\r
+    //\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;\r
+\r
+  //\r
+  // Calculate microcode entry number\r
+  //\r
+  MaxPatchNumber = 0;\r
+  for (Index = 0; Index < EntryNum; Index++) {\r
+    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+      MaxPatchNumber++;\r
+    }\r
+  }\r
+  if (MaxPatchNumber == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  PatchInfoBuffer = AllocatePool (MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO));\r
+  if (PatchInfoBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Fill up microcode patch info buffer according to FIT table.\r
+  //\r
+  PatchCount = 0;\r
+  TotalLoadSize = 0;\r
+  for (Index = 0; Index < EntryNum; Index++) {\r
+    if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
+      MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) FitEntry[Index].Address;\r
+      TotalSize = (MicrocodeEntryPoint->DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;\r
+      if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {\r
+        PatchInfoBuffer[PatchCount].Address     = (UINTN) MicrocodeEntryPoint;\r
+        PatchInfoBuffer[PatchCount].Size        = TotalSize;\r
+        TotalLoadSize += TotalSize;\r
+        PatchCount++;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (PatchCount != 0) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",\r
+      __FUNCTION__, PatchCount, TotalLoadSize\r
+      ));\r
+\r
+    ShadowMicrocodePatchWorker (CpuMpData, PatchInfoBuffer, PatchCount, TotalLoadSize);\r
+  }\r
+\r
+  FreePool (PatchInfoBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Shadow the required microcode patches data into memory.\r
+\r
+  @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.\r
+**/\r
+VOID\r
+ShadowMicrocodeUpdatePatch (\r
+  IN OUT CPU_MP_DATA             *CpuMpData\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+\r
+  Status = ShadowMicrocodePatchByFit (CpuMpData);\r
+  if (EFI_ERROR (Status)) {\r
+    ShadowMicrocodePatchByPcd (CpuMpData);\r
+  }\r
+}\r
index e611a8ca40637815054414ae98178203418d643f..6ec9b172b86face6dec68c7e6e13a19d05c52362 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   CPU MP Initialize Library common functions.\r
 \r
-  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -1744,7 +1744,7 @@ MpInitLibInitialize (
     //\r
     // Load required microcode patches data into memory\r
     //\r
-    LoadMicrocodePatch (CpuMpData);\r
+    ShadowMicrocodeUpdatePatch (CpuMpData);\r
   } else {\r
     //\r
     // APs have been wakeup before, just get the CPU Information\r
index b6e5a1afab0044cdde2e82abb6b4c6504a1e98b3..7c62d75accfb7335f44a2e84598fdb07c0639b76 100644 (file)
@@ -29,6 +29,9 @@
 #include <Library/MtrrLib.h>\r
 #include <Library/HobLib.h>\r
 \r
+#include <IndustryStandard/FirmwareInterfaceTable.h>\r
+\r
+\r
 #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')\r
 \r
 #define CPU_INIT_MP_LIB_HOB_GUID \\r
@@ -587,12 +590,12 @@ MicrocodeDetect (
   );\r
 \r
 /**\r
-  Load the required microcode patches data into memory.\r
+  Shadow the required microcode patches data into memory.\r
 \r
   @param[in, out]  CpuMpData    The pointer to CPU MP Data structure.\r
 **/\r
 VOID\r
-LoadMicrocodePatch (\r
+ShadowMicrocodeUpdatePatch (\r
   IN OUT CPU_MP_DATA             *CpuMpData\r
   );\r
 \r
index 326703cc9ad336dea6dbdee9f127547195deb2b9..555125a7c575c6300b604a8115dd96c4ae9990c4 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  MP Initialize Library instance for PEI driver.\r
 #\r
-#  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 ##\r
@@ -60,6 +60,7 @@
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize         ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode                       ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate                   ## SOMETIMES_CONSUMES\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit             ## CONSUMES\r
 \r
 [Guids]\r
   gEdkiiS3SmmInitDoneGuid\r
index 45b267ac61d5cf713f9dc2a09fb3a765ff2861e3..a6ebdde1cfb6bf0db4b9ec4e7bfd1d7f112c932c 100644 (file)
   # @Prompt Lock SMM Feature Control MSR.\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B\r
 \r
+  ## Indicates if FIT based microcode shadowing will be enabled.<BR><BR>\r
+  #   TRUE  - FIT base microcode shadowing will be enabled.<BR>\r
+  #   FALSE - FIT base microcode shadowing will be disabled.<BR>\r
+  # @Prompt FIT based microcode shadowing.\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuShadowMicrocodeByFit|FALSE|BOOLEAN|0x3213210D\r
+\r
 [PcdsFixedAtBuild]\r
   ## List of exception vectors which need switching stack.\r
   #  This PCD will only take into effect if PcdCpuStackGuard is enabled.\r
index c0d6ed513678a4ce5ea40a1fdfea6a5241dbcb68..2db49e841b4ac862a93e7978893797f57b0abf42 100644 (file)
                                                                                            "TRUE  - locked.<BR>\n"\r
                                                                                            "FALSE - unlocked.<BR>"\r
 \r
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuShadowMicrocodeByFit_PROMPT  #language en-US "FIT based microcode shadowing"\r
+\r
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuShadowMicrocodeByFit_HELP  #language en-US "Indicates if FIT based microcode shadowing will be enabled.<BR><BR>\n"\r
+                                                                                       "TRUE  - FIT base microcode shadowing will be enabled.<BR>\n"\r
+                                                                                       "FALSE - FIT base microcode shadowing will be disabled.<BR>"\r
+\r
 #string STR_gUefiCpuPkgTokenSpaceGuid_PcdPeiTemporaryRamStackSize_PROMPT  #language en-US "Stack size in the temporary RAM"\r
 \r
 #string STR_gUefiCpuPkgTokenSpaceGuid_PcdPeiTemporaryRamStackSize_HELP  #language en-US "Specifies stack size in the temporary RAM. 0 means half of TemporaryRamSize."\r