]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/Microcode.c
UefiCpuPkg/MpInitLib: Use BSP uCode for APs if possible.
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Microcode.c
index 0fd8e8c51bc8d7553198a7d5dafb869ac7cd65d9..30ceaa46adcd6526ceceec7311b8ccec6de4f895 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of loading microcode on processors.\r
 \r
-  Copyright (c) 2015 - 2016, 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
@@ -35,15 +35,15 @@ GetCurrentMicrocodeSignature (
 /**\r
   Detect whether specified processor can find matching microcode patch and load it.\r
 \r
-  @param[in] PeiCpuMpData        Pointer to PEI CPU MP Data\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
-  UINT64                                  MicrocodePatchAddress;\r
-  UINT64                                  MicrocodePatchRegionSize;\r
   UINT32                                  ExtendedTableLength;\r
   UINT32                                  ExtendedTableCount;\r
   CPU_MICROCODE_EXTENDED_TABLE            *ExtendedTable;\r
@@ -60,10 +60,9 @@ MicrocodeDetect (
   BOOLEAN                                 CorrectMicrocode;\r
   VOID                                    *MicrocodeData;\r
   MSR_IA32_PLATFORM_ID_REGISTER           PlatformIdMsr;\r
+  UINT32                                  ProcessorFlags;\r
 \r
-  MicrocodePatchAddress    = PcdGet64 (PcdCpuMicrocodePatchAddress);\r
-  MicrocodePatchRegionSize = PcdGet64 (PcdCpuMicrocodePatchRegionSize);\r
-  if (MicrocodePatchRegionSize == 0) {\r
+  if (CpuMpData->MicrocodePatchRegionSize == 0) {\r
     //\r
     // There is no microcode patches\r
     //\r
@@ -71,7 +70,7 @@ MicrocodeDetect (
   }\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
@@ -81,7 +80,7 @@ MicrocodeDetect (
   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
@@ -91,9 +90,23 @@ MicrocodeDetect (
   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
-  MicrocodeEnd = (UINTN) (MicrocodePatchAddress + MicrocodePatchRegionSize);\r
-  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) MicrocodePatchAddress;\r
+  MicrocodeData  = NULL;\r
+  MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize);\r
+  MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;\r
   do {\r
     //\r
     // Check if the microcode is for the Cpu and the version is newer\r
@@ -120,6 +133,7 @@ MicrocodeDetect (
         }\r
         if (CheckSum32 == 0) {\r
           CorrectMicrocode = TRUE;\r
+          ProcessorFlags = MicrocodeEntryPoint->ProcessorFlags;\r
         }\r
       } else if ((MicrocodeEntryPoint->DataSize != 0) &&\r
                  (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {\r
@@ -154,6 +168,7 @@ MicrocodeDetect (
                     // Find one\r
                     //\r
                     CorrectMicrocode = TRUE;\r
+                    ProcessorFlags = ExtendedTable->ProcessorFlag;\r
                     break;\r
                   }\r
                 }\r
@@ -191,6 +206,7 @@ MicrocodeDetect (
     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
@@ -198,6 +214,7 @@ MicrocodeDetect (
     // Revision. A processor with no loaded update is considered to have a\r
     // revision equal to zero.\r
     //\r
+    ASSERT (MicrocodeData != NULL);\r
     AsmWriteMsr64 (\r
         MSR_IA32_BIOS_UPDT_TRIG,\r
         (UINT64) (UINTN) MicrocodeData\r
@@ -213,4 +230,16 @@ MicrocodeDetect (
       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