2 Implementation of loading microcode on processors.
4 Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Detect whether specified processor can find matching microcode patch and load it.
14 @param[in] CpuMpData The pointer to CPU MP Data structure.
15 @param[in] ProcessorNumber The handle number of the processor. The range is
16 from 0 to the total number of logical processors
21 IN CPU_MP_DATA
*CpuMpData
,
22 IN UINTN ProcessorNumber
25 CPU_MICROCODE_HEADER
*Microcode
;
28 UINT32 LatestRevision
;
29 CPU_MICROCODE_HEADER
*LatestMicrocode
;
31 EDKII_PEI_MICROCODE_CPU_ID MicrocodeCpuId
;
33 if (CpuMpData
->MicrocodePatchRegionSize
== 0) {
35 // There is no microcode patches
40 GetProcessorLocationByApicId (GetInitialApicId (), NULL
, NULL
, &ThreadId
);
43 // Skip loading microcode if it is not the first thread in one core.
48 GetProcessorMicrocodeCpuId (&MicrocodeCpuId
);
50 if (ProcessorNumber
!= (UINTN
)CpuMpData
->BspNumber
) {
52 // Direct use microcode of BSP if AP is the same as BSP.
53 // Assume BSP calls this routine() before AP.
55 BspData
= &(CpuMpData
->CpuData
[CpuMpData
->BspNumber
]);
56 if ((BspData
->ProcessorSignature
== MicrocodeCpuId
.ProcessorSignature
) &&
57 (BspData
->PlatformId
== MicrocodeCpuId
.PlatformId
) &&
58 (BspData
->MicrocodeEntryAddr
!= 0))
60 LatestMicrocode
= (CPU_MICROCODE_HEADER
*)(UINTN
)BspData
->MicrocodeEntryAddr
;
61 LatestRevision
= LatestMicrocode
->UpdateRevision
;
67 // BSP or AP which is different from BSP runs here
68 // Use 0 as the starting revision to search for microcode because MicrocodePatchInfo HOB needs
69 // the latest microcode location even it's loaded to the processor.
72 LatestMicrocode
= NULL
;
73 Microcode
= (CPU_MICROCODE_HEADER
*)(UINTN
)CpuMpData
->MicrocodePatchAddress
;
74 MicrocodeEnd
= (UINTN
)Microcode
+ (UINTN
)CpuMpData
->MicrocodePatchRegionSize
;
77 if (!IsValidMicrocode (Microcode
, MicrocodeEnd
- (UINTN
)Microcode
, LatestRevision
, &MicrocodeCpuId
, 1, TRUE
)) {
79 // It is the padding data between the microcode patches for microcode patches alignment.
80 // Because the microcode patch is the multiple of 1-KByte, the padding data should not
81 // exist if the microcode patch alignment value is not larger than 1-KByte. So, the microcode
82 // alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
83 // find the next possible microcode patch header.
85 Microcode
= (CPU_MICROCODE_HEADER
*)((UINTN
)Microcode
+ SIZE_1KB
);
89 LatestMicrocode
= Microcode
;
90 LatestRevision
= LatestMicrocode
->UpdateRevision
;
92 Microcode
= (CPU_MICROCODE_HEADER
*)(((UINTN
)Microcode
) + GetMicrocodeLength (Microcode
));
93 } while ((UINTN
)Microcode
< MicrocodeEnd
);
96 if (LatestRevision
!= 0) {
98 // Save the detected microcode patch entry address (including the microcode
99 // patch header) for each processor even it's the same as the loaded one.
100 // It will be used when building the microcode patch cache HOB.
102 CpuMpData
->CpuData
[ProcessorNumber
].MicrocodeEntryAddr
= (UINTN
)LatestMicrocode
;
105 if (LatestRevision
> GetProcessorMicrocodeSignature ()) {
107 // BIOS only authenticate updates that contain a numerically larger revision
108 // than the currently loaded revision, where Current Signature < New Update
109 // Revision. A processor with no loaded update is considered to have a
110 // revision equal to zero.
112 LoadMicrocode (LatestMicrocode
);
116 // It's possible that the microcode fails to load. Just capture the CPU microcode revision after loading.
118 CpuMpData
->CpuData
[ProcessorNumber
].MicrocodeRevision
= GetProcessorMicrocodeSignature ();
122 Actual worker function that shadows the required microcode patches into memory.
124 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
125 @param[in] Patches The pointer to an array of information on
126 the microcode patches that will be loaded
128 @param[in] PatchCount The number of microcode patches that will
129 be loaded into memory.
130 @param[in] TotalLoadSize The total size of all the microcode patches
134 ShadowMicrocodePatchWorker (
135 IN OUT CPU_MP_DATA
*CpuMpData
,
136 IN MICROCODE_PATCH_INFO
*Patches
,
138 IN UINTN TotalLoadSize
142 VOID
*MicrocodePatchInRam
;
145 ASSERT ((Patches
!= NULL
) && (PatchCount
!= 0));
147 MicrocodePatchInRam
= AllocatePages (EFI_SIZE_TO_PAGES (TotalLoadSize
));
148 if (MicrocodePatchInRam
== NULL
) {
153 // Load all the required microcode patches into memory
155 for (Walker
= MicrocodePatchInRam
, Index
= 0; Index
< PatchCount
; Index
++) {
158 (VOID
*)Patches
[Index
].Address
,
161 Walker
+= Patches
[Index
].Size
;
165 // Update the microcode patch related fields in CpuMpData
167 CpuMpData
->MicrocodePatchAddress
= (UINTN
)MicrocodePatchInRam
;
168 CpuMpData
->MicrocodePatchRegionSize
= TotalLoadSize
;
172 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
174 CpuMpData
->MicrocodePatchAddress
,
175 CpuMpData
->MicrocodePatchRegionSize
182 Shadow the required microcode patches data into memory according to PCD
183 PcdCpuMicrocodePatchAddress and PcdCpuMicrocodePatchRegionSize.
185 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
188 ShadowMicrocodePatchByPcd (
189 IN OUT CPU_MP_DATA
*CpuMpData
193 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
196 MICROCODE_PATCH_INFO
*PatchInfoBuffer
;
197 UINTN MaxPatchNumber
;
200 EDKII_PEI_MICROCODE_CPU_ID
*MicrocodeCpuIds
;
204 // Initialize the microcode patch related fields in CpuMpData as the values
205 // specified by the PCD pair. If the microcode patches are loaded into memory,
206 // these fields will be updated.
208 CpuMpData
->MicrocodePatchAddress
= PcdGet64 (PcdCpuMicrocodePatchAddress
);
209 CpuMpData
->MicrocodePatchRegionSize
= PcdGet64 (PcdCpuMicrocodePatchRegionSize
);
211 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*)(UINTN
)CpuMpData
->MicrocodePatchAddress
;
212 MicrocodeEnd
= (UINTN
)MicrocodeEntryPoint
+
213 (UINTN
)CpuMpData
->MicrocodePatchRegionSize
;
214 if ((MicrocodeEntryPoint
== NULL
) || ((UINTN
)MicrocodeEntryPoint
== MicrocodeEnd
)) {
216 // There is no microcode patches
222 MaxPatchNumber
= DEFAULT_MAX_MICROCODE_PATCH_NUM
;
224 PatchInfoBuffer
= AllocatePool (MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
));
225 if (PatchInfoBuffer
== NULL
) {
229 MicrocodeCpuIds
= AllocatePages (
230 EFI_SIZE_TO_PAGES (CpuMpData
->CpuCount
* sizeof (EDKII_PEI_MICROCODE_CPU_ID
))
232 if (MicrocodeCpuIds
== NULL
) {
233 FreePool (PatchInfoBuffer
);
237 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
238 MicrocodeCpuIds
[Index
].PlatformId
= CpuMpData
->CpuData
[Index
].PlatformId
;
239 MicrocodeCpuIds
[Index
].ProcessorSignature
= CpuMpData
->CpuData
[Index
].ProcessorSignature
;
243 // Process the header of each microcode patch within the region.
244 // The purpose is to decide which microcode patch(es) will be loaded into memory.
245 // Microcode checksum is not verified because it's slow when performing on flash.
248 Valid
= IsValidMicrocode (
250 MicrocodeEnd
- (UINTN
)MicrocodeEntryPoint
,
258 // Padding data between the microcode patches, skip 1KB to check next entry.
260 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*)(((UINTN
)MicrocodeEntryPoint
) + SIZE_1KB
);
265 if (PatchCount
> MaxPatchNumber
) {
267 // Current 'PatchInfoBuffer' cannot hold the information, double the size
268 // and allocate a new buffer.
270 if (MaxPatchNumber
> MAX_UINTN
/ 2 / sizeof (MICROCODE_PATCH_INFO
)) {
272 // Overflow check for MaxPatchNumber
277 PatchInfoBuffer
= ReallocatePool (
278 MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
279 2 * MaxPatchNumber
* sizeof (MICROCODE_PATCH_INFO
),
282 if (PatchInfoBuffer
== NULL
) {
286 MaxPatchNumber
= MaxPatchNumber
* 2;
289 TotalSize
= GetMicrocodeLength (MicrocodeEntryPoint
);
292 // Store the information of this microcode patch
294 PatchInfoBuffer
[PatchCount
- 1].Address
= (UINTN
)MicrocodeEntryPoint
;
295 PatchInfoBuffer
[PatchCount
- 1].Size
= TotalSize
;
296 TotalLoadSize
+= TotalSize
;
299 // Process the next microcode patch
301 MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*)((UINTN
)MicrocodeEntryPoint
+ TotalSize
);
302 } while ((UINTN
)MicrocodeEntryPoint
< MicrocodeEnd
);
304 if (PatchCount
!= 0) {
307 "%a: 0x%x microcode patches will be loaded into memory, with size 0x%x.\n",
313 ShadowMicrocodePatchWorker (CpuMpData
, PatchInfoBuffer
, PatchCount
, TotalLoadSize
);
317 if (PatchInfoBuffer
!= NULL
) {
318 FreePool (PatchInfoBuffer
);
321 FreePages (MicrocodeCpuIds
, EFI_SIZE_TO_PAGES (CpuMpData
->CpuCount
* sizeof (EDKII_PEI_MICROCODE_CPU_ID
)));
325 Shadow the required microcode patches data into memory.
327 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
330 ShadowMicrocodeUpdatePatch (
331 IN OUT CPU_MP_DATA
*CpuMpData
336 Status
= PlatformShadowMicrocode (CpuMpData
);
337 if (EFI_ERROR (Status
)) {
338 ShadowMicrocodePatchByPcd (CpuMpData
);
343 Get the cached microcode patch base address and size from the microcode patch
344 information cache HOB.
346 @param[out] Address Base address of the microcode patches data.
347 It will be updated if the microcode patch
348 information cache HOB is found.
349 @param[out] RegionSize Size of the microcode patches data.
350 It will be updated if the microcode patch
351 information cache HOB is found.
353 @retval TRUE The microcode patch information cache HOB is found.
354 @retval FALSE The microcode patch information cache HOB is not found.
358 GetMicrocodePatchInfoFromHob (
363 EFI_HOB_GUID_TYPE
*GuidHob
;
364 EDKII_MICROCODE_PATCH_HOB
*MicrocodePathHob
;
366 GuidHob
= GetFirstGuidHob (&gEdkiiMicrocodePatchHobGuid
);
367 if (GuidHob
== NULL
) {
368 DEBUG ((DEBUG_INFO
, "%a: Microcode patch cache HOB is not found.\n", __FUNCTION__
));
372 MicrocodePathHob
= GET_GUID_HOB_DATA (GuidHob
);
374 *Address
= MicrocodePathHob
->MicrocodePatchAddress
;
375 *RegionSize
= MicrocodePathHob
->MicrocodePatchRegionSize
;
379 "%a: MicrocodeBase = 0x%lx, MicrocodeSize = 0x%lx\n",