VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c@ 101291

Last change on this file since 101291 was 101291, checked in by vboxsync, 14 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 28.7 KB
Line 
1/** @file
2 MP initialize support functions for PEI phase.
3
4 Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "MpLib.h"
10#include <Library/PeiServicesLib.h>
11#include <Guid/S3SmmInitDone.h>
12#include <Ppi/ShadowMicrocode.h>
13
14STATIC UINT64 mSevEsPeiWakeupBuffer = BASE_1MB;
15
16/**
17 S3 SMM Init Done notification function.
18
19 @param PeiServices Indirect reference to the PEI Services Table.
20 @param NotifyDesc Address of the notification descriptor data structure.
21 @param InvokePpi Address of the PPI that was invoked.
22
23 @retval EFI_SUCCESS The function completes successfully.
24
25**/
26EFI_STATUS
27EFIAPI
28NotifyOnS3SmmInitDonePpi (
29 IN EFI_PEI_SERVICES **PeiServices,
30 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
31 IN VOID *InvokePpi
32 );
33
34//
35// Global function
36//
37EFI_PEI_NOTIFY_DESCRIPTOR mS3SmmInitDoneNotifyDesc = {
38 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
39 &gEdkiiS3SmmInitDoneGuid,
40 NotifyOnS3SmmInitDonePpi
41};
42
43/**
44 S3 SMM Init Done notification function.
45
46 @param PeiServices Indirect reference to the PEI Services Table.
47 @param NotifyDesc Address of the notification descriptor data structure.
48 @param InvokePpi Address of the PPI that was invoked.
49
50 @retval EFI_SUCCESS The function completes successfully.
51
52**/
53EFI_STATUS
54EFIAPI
55NotifyOnS3SmmInitDonePpi (
56 IN EFI_PEI_SERVICES **PeiServices,
57 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
58 IN VOID *InvokePpi
59 )
60{
61 CPU_MP_DATA *CpuMpData;
62
63 CpuMpData = GetCpuMpData ();
64
65 //
66 // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode.
67 // So in this notify function, code need to check the current loop
68 // mode, if it is not HLT mode, code need to change loop mode back
69 // to the original mode.
70 //
71 if (CpuMpData->ApLoopMode != ApInHltLoop) {
72 CpuMpData->WakeUpByInitSipiSipi = TRUE;
73 }
74
75 return EFI_SUCCESS;
76}
77
78/**
79 Enable Debug Agent to support source debugging on AP function.
80
81**/
82VOID
83EnableDebugAgent (
84 VOID
85 )
86{
87}
88
89/**
90 Get pointer to CPU MP Data structure.
91 For BSP, the pointer is retrieved from HOB.
92 For AP, the structure is stored in the top of each AP's stack.
93
94 @return The pointer to CPU MP Data structure.
95**/
96CPU_MP_DATA *
97GetCpuMpData (
98 VOID
99 )
100{
101 CPU_MP_DATA *CpuMpData;
102 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
103 UINTN ApTopOfStack;
104 AP_STACK_DATA *ApStackData;
105
106 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
107 if (ApicBaseMsr.Bits.BSP == 1) {
108 CpuMpData = GetCpuMpDataFromGuidedHob ();
109 ASSERT (CpuMpData != NULL);
110 } else {
111 ApTopOfStack = ALIGN_VALUE ((UINTN)&ApTopOfStack, (UINTN)PcdGet32 (PcdCpuApStackSize));
112 ApStackData = (AP_STACK_DATA *)((UINTN)ApTopOfStack- sizeof (AP_STACK_DATA));
113 CpuMpData = (CPU_MP_DATA *)ApStackData->MpData;
114 }
115
116 return CpuMpData;
117}
118
119/**
120 Save the pointer to CPU MP Data structure.
121
122 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
123**/
124VOID
125SaveCpuMpData (
126 IN CPU_MP_DATA *CpuMpData
127 )
128{
129 UINT64 Data64;
130 UINTN Index;
131 CPU_INFO_IN_HOB *CpuInfoInHob;
132 MP_HAND_OFF *MpHandOff;
133 UINTN MpHandOffSize;
134
135 //
136 // When APs are in a state that can be waken up by a store operation to a memory address,
137 // report the MP_HAND_OFF data for DXE to use.
138 //
139 CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
140 MpHandOffSize = sizeof (MP_HAND_OFF) + sizeof (PROCESSOR_HAND_OFF) * CpuMpData->CpuCount;
141 MpHandOff = (MP_HAND_OFF *)BuildGuidHob (&mMpHandOffGuid, MpHandOffSize);
142 ASSERT (MpHandOff != NULL);
143 ZeroMem (MpHandOff, MpHandOffSize);
144 MpHandOff->ProcessorIndex = 0;
145
146 MpHandOff->CpuCount = CpuMpData->CpuCount;
147 if (CpuMpData->ApLoopMode != ApInHltLoop) {
148 MpHandOff->StartupSignalValue = MP_HAND_OFF_SIGNAL;
149 MpHandOff->WaitLoopExecutionMode = sizeof (VOID *);
150 }
151
152 for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
153 MpHandOff->Info[Index].ApicId = CpuInfoInHob[Index].ApicId;
154 MpHandOff->Info[Index].Health = CpuInfoInHob[Index].Health;
155 if (CpuMpData->ApLoopMode != ApInHltLoop) {
156 MpHandOff->Info[Index].StartupSignalAddress = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal;
157 MpHandOff->Info[Index].StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction;
158 }
159 }
160
161 //
162 // Build location of CPU MP DATA buffer in HOB
163 //
164 Data64 = (UINT64)(UINTN)CpuMpData;
165 BuildGuidDataHob (
166 &mCpuInitMpLibHobGuid,
167 (VOID *)&Data64,
168 sizeof (UINT64)
169 );
170}
171
172/**
173 Check if AP wakeup buffer is overlapped with existing allocated buffer.
174
175 @param[in] WakeupBufferStart AP wakeup buffer start address.
176 @param[in] WakeupBufferEnd AP wakeup buffer end address.
177
178 @retval TRUE There is overlap.
179 @retval FALSE There is no overlap.
180**/
181BOOLEAN
182CheckOverlapWithAllocatedBuffer (
183 IN UINT64 WakeupBufferStart,
184 IN UINT64 WakeupBufferEnd
185 )
186{
187 EFI_PEI_HOB_POINTERS Hob;
188 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
189 BOOLEAN Overlapped;
190 UINT64 MemoryStart;
191 UINT64 MemoryEnd;
192
193 Overlapped = FALSE;
194 //
195 // Get the HOB list for processing
196 //
197 Hob.Raw = GetHobList ();
198 //
199 // Collect memory ranges
200 //
201 while (!END_OF_HOB_LIST (Hob)) {
202 if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
203 MemoryHob = Hob.MemoryAllocation;
204 MemoryStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;
205 MemoryEnd = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;
206 if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {
207 Overlapped = TRUE;
208 break;
209 }
210 }
211
212 Hob.Raw = GET_NEXT_HOB (Hob);
213 }
214
215 return Overlapped;
216}
217
218/**
219 Get available system memory below 1MB by specified size.
220
221 @param[in] WakeupBufferSize Wakeup buffer size required
222
223 @retval other Return wakeup buffer address below 1MB.
224 @retval -1 Cannot find free memory below 1MB.
225**/
226UINTN
227GetWakeupBuffer (
228 IN UINTN WakeupBufferSize
229 )
230{
231 EFI_PEI_HOB_POINTERS Hob;
232 UINT64 WakeupBufferStart;
233 UINT64 WakeupBufferEnd;
234
235 WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);
236
237 //
238 // Get the HOB list for processing
239 //
240 Hob.Raw = GetHobList ();
241
242 //
243 // Collect memory ranges
244 //
245 while (!END_OF_HOB_LIST (Hob)) {
246 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
247 if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&
248 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
249 ((Hob.ResourceDescriptor->ResourceAttribute &
250 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |
251 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |
252 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
253 )) == 0)
254 )
255 {
256 //
257 // Need memory under 1MB to be collected here
258 //
259 WakeupBufferEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;
260 if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) &&
261 (WakeupBufferEnd > mSevEsPeiWakeupBuffer))
262 {
263 //
264 // SEV-ES Wakeup buffer should be under 1MB and under any previous one
265 //
266 WakeupBufferEnd = mSevEsPeiWakeupBuffer;
267 } else if (WakeupBufferEnd > BASE_1MB) {
268 //
269 // Wakeup buffer should be under 1MB
270 //
271 WakeupBufferEnd = BASE_1MB;
272 }
273
274 while (WakeupBufferEnd > WakeupBufferSize) {
275 //
276 // Wakeup buffer should be aligned on 4KB
277 //
278 WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);
279 if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {
280 break;
281 }
282
283 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {
284 //
285 // If this range is overlapped with existing allocated buffer, skip it
286 // and find the next range
287 //
288 WakeupBufferEnd -= WakeupBufferSize;
289 continue;
290 }
291
292 DEBUG ((
293 DEBUG_INFO,
294 "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
295 WakeupBufferStart,
296 WakeupBufferSize
297 ));
298
299 if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) {
300 //
301 // Next SEV-ES wakeup buffer allocation must be below this
302 // allocation
303 //
304 mSevEsPeiWakeupBuffer = WakeupBufferStart;
305 }
306
307 return (UINTN)WakeupBufferStart;
308 }
309 }
310 }
311
312 //
313 // Find the next HOB
314 //
315 Hob.Raw = GET_NEXT_HOB (Hob);
316 }
317
318 return (UINTN)-1;
319}
320
321/**
322 Get available EfiBootServicesCode memory below 4GB by specified size.
323
324 This buffer is required to safely transfer AP from real address mode to
325 protected mode or long mode, due to the fact that the buffer returned by
326 GetWakeupBuffer() may be marked as non-executable.
327
328 @param[in] BufferSize Wakeup transition buffer size.
329
330 @retval other Return wakeup transition buffer address below 4GB.
331 @retval 0 Cannot find free memory below 4GB.
332**/
333UINTN
334AllocateCodeBuffer (
335 IN UINTN BufferSize
336 )
337{
338 EFI_STATUS Status;
339 EFI_PHYSICAL_ADDRESS Address;
340
341 Status = PeiServicesAllocatePages (EfiBootServicesCode, EFI_SIZE_TO_PAGES (BufferSize), &Address);
342 if (EFI_ERROR (Status)) {
343 Address = 0;
344 }
345
346 return (UINTN)Address;
347}
348
349/**
350 Return the address of the SEV-ES AP jump table.
351
352 This buffer is required in order for an SEV-ES guest to transition from
353 UEFI into an OS.
354
355 @return Return SEV-ES AP jump table buffer
356**/
357UINTN
358GetSevEsAPMemory (
359 VOID
360 )
361{
362 //
363 // PEI phase doesn't need to do such transition. So simply return 0.
364 //
365 return 0;
366}
367
368/**
369 Checks APs status and updates APs status if needed.
370
371**/
372VOID
373CheckAndUpdateApsStatus (
374 VOID
375 )
376{
377}
378
379/**
380 Build the microcode patch HOB that contains the base address and size of the
381 microcode patch stored in the memory.
382
383 @param[in] CpuMpData Pointer to the CPU_MP_DATA structure.
384
385**/
386VOID
387BuildMicrocodeCacheHob (
388 IN CPU_MP_DATA *CpuMpData
389 )
390{
391 EDKII_MICROCODE_PATCH_HOB *MicrocodeHob;
392 UINTN HobDataLength;
393 UINT32 Index;
394
395 HobDataLength = sizeof (EDKII_MICROCODE_PATCH_HOB) +
396 sizeof (UINT64) * CpuMpData->CpuCount;
397
398 MicrocodeHob = AllocatePool (HobDataLength);
399 if (MicrocodeHob == NULL) {
400 ASSERT (FALSE);
401 return;
402 }
403
404 //
405 // Store the information of the memory region that holds the microcode patches.
406 //
407 MicrocodeHob->MicrocodePatchAddress = CpuMpData->MicrocodePatchAddress;
408 MicrocodeHob->MicrocodePatchRegionSize = CpuMpData->MicrocodePatchRegionSize;
409
410 //
411 // Store the detected microcode patch for each processor as well.
412 //
413 MicrocodeHob->ProcessorCount = CpuMpData->CpuCount;
414 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
415 if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {
416 MicrocodeHob->ProcessorSpecificPatchOffset[Index] =
417 CpuMpData->CpuData[Index].MicrocodeEntryAddr - CpuMpData->MicrocodePatchAddress;
418 } else {
419 MicrocodeHob->ProcessorSpecificPatchOffset[Index] = MAX_UINT64;
420 }
421 }
422
423 BuildGuidDataHob (
424 &gEdkiiMicrocodePatchHobGuid,
425 MicrocodeHob,
426 HobDataLength
427 );
428
429 return;
430}
431
432/**
433 Initialize global data for MP support.
434
435 @param[in] CpuMpData The pointer to CPU MP Data structure.
436**/
437VOID
438InitMpGlobalData (
439 IN CPU_MP_DATA *CpuMpData
440 )
441{
442 EFI_STATUS Status;
443
444 BuildMicrocodeCacheHob (CpuMpData);
445 SaveCpuMpData (CpuMpData);
446
447 ///
448 /// Install Notify
449 ///
450 Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);
451 ASSERT_EFI_ERROR (Status);
452}
453
454/**
455 This service executes a caller provided function on all enabled APs.
456
457 @param[in] Procedure A pointer to the function to be run on
458 enabled APs of the system. See type
459 EFI_AP_PROCEDURE.
460 @param[in] SingleThread If TRUE, then all the enabled APs execute
461 the function specified by Procedure one by
462 one, in ascending order of processor handle
463 number. If FALSE, then all the enabled APs
464 execute the function specified by Procedure
465 simultaneously.
466 @param[in] WaitEvent The event created by the caller with CreateEvent()
467 service. If it is NULL, then execute in
468 blocking mode. BSP waits until all APs finish
469 or TimeoutInMicroSeconds expires. If it's
470 not NULL, then execute in non-blocking mode.
471 BSP requests the function specified by
472 Procedure to be started on all the enabled
473 APs, and go on executing immediately. If
474 all return from Procedure, or TimeoutInMicroSeconds
475 expires, this event is signaled. The BSP
476 can use the CheckEvent() or WaitForEvent()
477 services to check the state of event. Type
478 EFI_EVENT is defined in CreateEvent() in
479 the Unified Extensible Firmware Interface
480 Specification.
481 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
482 APs to return from Procedure, either for
483 blocking or non-blocking mode. Zero means
484 infinity. If the timeout expires before
485 all APs return from Procedure, then Procedure
486 on the failed APs is terminated. All enabled
487 APs are available for next function assigned
488 by MpInitLibStartupAllAPs() or
489 MPInitLibStartupThisAP().
490 If the timeout expires in blocking mode,
491 BSP returns EFI_TIMEOUT. If the timeout
492 expires in non-blocking mode, WaitEvent
493 is signaled with SignalEvent().
494 @param[in] ProcedureArgument The parameter passed into Procedure for
495 all APs.
496 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
497 if all APs finish successfully, then its
498 content is set to NULL. If not all APs
499 finish before timeout expires, then its
500 content is set to address of the buffer
501 holding handle numbers of the failed APs.
502 The buffer is allocated by MP Initialization
503 library, and it's the caller's responsibility to
504 free the buffer with FreePool() service.
505 In blocking mode, it is ready for consumption
506 when the call returns. In non-blocking mode,
507 it is ready when WaitEvent is signaled. The
508 list of failed CPU is terminated by
509 END_OF_CPU_LIST.
510
511 @retval EFI_SUCCESS In blocking mode, all APs have finished before
512 the timeout expired.
513 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
514 to all enabled APs.
515 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
516 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
517 signaled.
518 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
519 supported.
520 @retval EFI_DEVICE_ERROR Caller processor is AP.
521 @retval EFI_NOT_STARTED No enabled APs exist in the system.
522 @retval EFI_NOT_READY Any enabled APs are busy.
523 @retval EFI_NOT_READY MP Initialize Library is not initialized.
524 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
525 all enabled APs have finished.
526 @retval EFI_INVALID_PARAMETER Procedure is NULL.
527
528**/
529EFI_STATUS
530EFIAPI
531MpInitLibStartupAllAPs (
532 IN EFI_AP_PROCEDURE Procedure,
533 IN BOOLEAN SingleThread,
534 IN EFI_EVENT WaitEvent OPTIONAL,
535 IN UINTN TimeoutInMicroseconds,
536 IN VOID *ProcedureArgument OPTIONAL,
537 OUT UINTN **FailedCpuList OPTIONAL
538 )
539{
540 if (WaitEvent != NULL) {
541 return EFI_UNSUPPORTED;
542 }
543
544 return StartupAllCPUsWorker (
545 Procedure,
546 SingleThread,
547 TRUE,
548 NULL,
549 TimeoutInMicroseconds,
550 ProcedureArgument,
551 FailedCpuList
552 );
553}
554
555/**
556 This service lets the caller get one enabled AP to execute a caller-provided
557 function.
558
559 @param[in] Procedure A pointer to the function to be run on the
560 designated AP of the system. See type
561 EFI_AP_PROCEDURE.
562 @param[in] ProcessorNumber The handle number of the AP. The range is
563 from 0 to the total number of logical
564 processors minus 1. The total number of
565 logical processors can be retrieved by
566 MpInitLibGetNumberOfProcessors().
567 @param[in] WaitEvent The event created by the caller with CreateEvent()
568 service. If it is NULL, then execute in
569 blocking mode. BSP waits until this AP finish
570 or TimeoutInMicroSeconds expires. If it's
571 not NULL, then execute in non-blocking mode.
572 BSP requests the function specified by
573 Procedure to be started on this AP,
574 and go on executing immediately. If this AP
575 return from Procedure or TimeoutInMicroSeconds
576 expires, this event is signaled. The BSP
577 can use the CheckEvent() or WaitForEvent()
578 services to check the state of event. Type
579 EFI_EVENT is defined in CreateEvent() in
580 the Unified Extensible Firmware Interface
581 Specification.
582 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
583 this AP to finish this Procedure, either for
584 blocking or non-blocking mode. Zero means
585 infinity. If the timeout expires before
586 this AP returns from Procedure, then Procedure
587 on the AP is terminated. The
588 AP is available for next function assigned
589 by MpInitLibStartupAllAPs() or
590 MpInitLibStartupThisAP().
591 If the timeout expires in blocking mode,
592 BSP returns EFI_TIMEOUT. If the timeout
593 expires in non-blocking mode, WaitEvent
594 is signaled with SignalEvent().
595 @param[in] ProcedureArgument The parameter passed into Procedure on the
596 specified AP.
597 @param[out] Finished If NULL, this parameter is ignored. In
598 blocking mode, this parameter is ignored.
599 In non-blocking mode, if AP returns from
600 Procedure before the timeout expires, its
601 content is set to TRUE. Otherwise, the
602 value is set to FALSE. The caller can
603 determine if the AP returned from Procedure
604 by evaluating this value.
605
606 @retval EFI_SUCCESS In blocking mode, specified AP finished before
607 the timeout expires.
608 @retval EFI_SUCCESS In non-blocking mode, the function has been
609 dispatched to specified AP.
610 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
611 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
612 signaled.
613 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
614 supported.
615 @retval EFI_DEVICE_ERROR The calling processor is an AP.
616 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
617 the specified AP has finished.
618 @retval EFI_NOT_READY The specified AP is busy.
619 @retval EFI_NOT_READY MP Initialize Library is not initialized.
620 @retval EFI_NOT_FOUND The processor with the handle specified by
621 ProcessorNumber does not exist.
622 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
623 @retval EFI_INVALID_PARAMETER Procedure is NULL.
624
625**/
626EFI_STATUS
627EFIAPI
628MpInitLibStartupThisAP (
629 IN EFI_AP_PROCEDURE Procedure,
630 IN UINTN ProcessorNumber,
631 IN EFI_EVENT WaitEvent OPTIONAL,
632 IN UINTN TimeoutInMicroseconds,
633 IN VOID *ProcedureArgument OPTIONAL,
634 OUT BOOLEAN *Finished OPTIONAL
635 )
636{
637 if (WaitEvent != NULL) {
638 return EFI_UNSUPPORTED;
639 }
640
641 return StartupThisAPWorker (
642 Procedure,
643 ProcessorNumber,
644 NULL,
645 TimeoutInMicroseconds,
646 ProcedureArgument,
647 Finished
648 );
649}
650
651/**
652 This service switches the requested AP to be the BSP from that point onward.
653 This service changes the BSP for all purposes. This call can only be performed
654 by the current BSP.
655
656 @param[in] ProcessorNumber The handle number of AP that is to become the new
657 BSP. The range is from 0 to the total number of
658 logical processors minus 1. The total number of
659 logical processors can be retrieved by
660 MpInitLibGetNumberOfProcessors().
661 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
662 enabled AP. Otherwise, it will be disabled.
663
664 @retval EFI_SUCCESS BSP successfully switched.
665 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
666 this service returning.
667 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
668 @retval EFI_DEVICE_ERROR The calling processor is an AP.
669 @retval EFI_NOT_FOUND The processor with the handle specified by
670 ProcessorNumber does not exist.
671 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
672 a disabled AP.
673 @retval EFI_NOT_READY The specified AP is busy.
674 @retval EFI_NOT_READY MP Initialize Library is not initialized.
675
676**/
677EFI_STATUS
678EFIAPI
679MpInitLibSwitchBSP (
680 IN UINTN ProcessorNumber,
681 IN BOOLEAN EnableOldBSP
682 )
683{
684 return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);
685}
686
687/**
688 This service lets the caller enable or disable an AP from this point onward.
689 This service may only be called from the BSP.
690
691 @param[in] ProcessorNumber The handle number of AP.
692 The range is from 0 to the total number of
693 logical processors minus 1. The total number of
694 logical processors can be retrieved by
695 MpInitLibGetNumberOfProcessors().
696 @param[in] EnableAP Specifies the new state for the processor for
697 enabled, FALSE for disabled.
698 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
699 the new health status of the AP. This flag
700 corresponds to StatusFlag defined in
701 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
702 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
703 bits are ignored. If it is NULL, this parameter
704 is ignored.
705
706 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
707 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
708 prior to this service returning.
709 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
710 @retval EFI_DEVICE_ERROR The calling processor is an AP.
711 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
712 does not exist.
713 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
714 @retval EFI_NOT_READY MP Initialize Library is not initialized.
715
716**/
717EFI_STATUS
718EFIAPI
719MpInitLibEnableDisableAP (
720 IN UINTN ProcessorNumber,
721 IN BOOLEAN EnableAP,
722 IN UINT32 *HealthFlag OPTIONAL
723 )
724{
725 return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
726}
727
728/**
729 This funtion will try to invoke platform specific microcode shadow logic to
730 relocate microcode update patches into memory.
731
732 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
733
734 @retval EFI_SUCCESS Shadow microcode success.
735 @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
736 @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
737 PPI/Protocol.
738**/
739EFI_STATUS
740PlatformShadowMicrocode (
741 IN OUT CPU_MP_DATA *CpuMpData
742 )
743{
744 EFI_STATUS Status;
745 EDKII_PEI_SHADOW_MICROCODE_PPI *ShadowMicrocodePpi;
746 UINTN CpuCount;
747 EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId;
748 UINTN Index;
749 UINTN BufferSize;
750 VOID *Buffer;
751
752 Status = PeiServicesLocatePpi (
753 &gEdkiiPeiShadowMicrocodePpiGuid,
754 0,
755 NULL,
756 (VOID **)&ShadowMicrocodePpi
757 );
758 if (EFI_ERROR (Status)) {
759 return EFI_UNSUPPORTED;
760 }
761
762 CpuCount = CpuMpData->CpuCount;
763 MicrocodeCpuId = (EDKII_PEI_MICROCODE_CPU_ID *)AllocateZeroPool (sizeof (EDKII_PEI_MICROCODE_CPU_ID) * CpuCount);
764 if (MicrocodeCpuId == NULL) {
765 return EFI_OUT_OF_RESOURCES;
766 }
767
768 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
769 MicrocodeCpuId[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;
770 MicrocodeCpuId[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;
771 }
772
773 Status = ShadowMicrocodePpi->ShadowMicrocode (
774 ShadowMicrocodePpi,
775 CpuCount,
776 MicrocodeCpuId,
777 &BufferSize,
778 &Buffer
779 );
780 FreePool (MicrocodeCpuId);
781 if (EFI_ERROR (Status)) {
782 return EFI_NOT_FOUND;
783 }
784
785 CpuMpData->MicrocodePatchAddress = (UINTN)Buffer;
786 CpuMpData->MicrocodePatchRegionSize = BufferSize;
787
788 DEBUG ((
789 DEBUG_INFO,
790 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
791 __func__,
792 CpuMpData->MicrocodePatchAddress,
793 CpuMpData->MicrocodePatchRegionSize
794 ));
795
796 return EFI_SUCCESS;
797}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette