2 MP initialize support functions for PEI phase.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Ppi/EndOfPeiPhase.h>
17 #include <Library/PeiServicesLib.h>
20 // Global PEI notify function descriptor on EndofPei event
22 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mMpInitLibNotifyList
= {
23 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
24 &gEfiEndOfPeiSignalPpiGuid
,
29 Get pointer to CPU MP Data structure.
31 @return The pointer to CPU MP Data structure.
38 CPU_MP_DATA
*CpuMpData
;
40 CpuMpData
= GetCpuMpDataFromGuidedHob ();
41 ASSERT (CpuMpData
!= NULL
);
46 Save the pointer to CPU MP Data structure.
48 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
52 IN CPU_MP_DATA
*CpuMpData
57 // Build location of CPU MP DATA buffer in HOB
59 Data64
= (UINT64
) (UINTN
) CpuMpData
;
61 &mCpuInitMpLibHobGuid
,
68 Get available system memory below 1MB by specified size.
70 @param[in] PeiCpuMpData Pointer to PEI CPU MP Data
73 BackupAndPrepareWakeupBuffer(
74 IN CPU_MP_DATA
*CpuMpData
78 (VOID
*) CpuMpData
->BackupBuffer
,
79 (VOID
*) CpuMpData
->WakeupBuffer
,
80 CpuMpData
->BackupBufferSize
83 (VOID
*) CpuMpData
->WakeupBuffer
,
84 (VOID
*) CpuMpData
->AddressMap
.RendezvousFunnelAddress
,
85 CpuMpData
->AddressMap
.RendezvousFunnelSize
90 Restore wakeup buffer data.
92 @param[in] PeiCpuMpData Pointer to PEI CPU MP Data
96 IN CPU_MP_DATA
*CpuMpData
100 (VOID
*) CpuMpData
->WakeupBuffer
,
101 (VOID
*) CpuMpData
->BackupBuffer
,
102 CpuMpData
->BackupBufferSize
107 Notify function on End Of PEI PPI.
109 On S3 boot, this function will restore wakeup buffer data.
110 On normal boot, this function will flag wakeup buffer to be un-used type.
112 @param[in] PeiServices The pointer to the PEI Services Table.
113 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
114 @param[in] Ppi Address of the PPI that was installed.
116 @retval EFI_SUCCESS When everything is OK.
120 CpuMpEndOfPeiCallback (
121 IN EFI_PEI_SERVICES
**PeiServices
,
122 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
127 EFI_BOOT_MODE BootMode
;
128 CPU_MP_DATA
*CpuMpData
;
129 EFI_PEI_HOB_POINTERS Hob
;
130 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
132 DEBUG ((DEBUG_INFO
, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n"));
134 Status
= PeiServicesGetBootMode (&BootMode
);
135 ASSERT_EFI_ERROR (Status
);
137 CpuMpData
= GetCpuMpData ();
138 if (BootMode
!= BOOT_ON_S3_RESUME
) {
140 // Get the HOB list for processing
142 Hob
.Raw
= GetHobList ();
144 // Collect memory ranges
146 while (!END_OF_HOB_LIST (Hob
)) {
147 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
148 MemoryHob
= Hob
.MemoryAllocation
;
149 if (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
== CpuMpData
->WakeupBuffer
) {
151 // Flag this HOB type to un-used
153 GET_HOB_TYPE (Hob
) = EFI_HOB_TYPE_UNUSED
;
157 Hob
.Raw
= GET_NEXT_HOB (Hob
);
160 CpuMpData
->EndOfPeiFlag
= TRUE
;
161 RestoreWakeupBuffer (CpuMpData
);
167 Check if AP wakeup buffer is overlapped with existing allocated buffer.
169 @param[in] WakeupBufferStart AP wakeup buffer start address.
170 @param[in] WakeupBufferEnd AP wakeup buffer end address.
172 @retval TRUE There is overlap.
173 @retval FALSE There is no overlap.
176 CheckOverlapWithAllocatedBuffer (
177 IN UINTN WakeupBufferStart
,
178 IN UINTN WakeupBufferEnd
181 EFI_PEI_HOB_POINTERS Hob
;
182 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
189 // Get the HOB list for processing
191 Hob
.Raw
= GetHobList ();
193 // Collect memory ranges
195 while (!END_OF_HOB_LIST (Hob
)) {
196 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
197 MemoryHob
= Hob
.MemoryAllocation
;
198 MemoryStart
= (UINTN
) MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
199 MemoryEnd
= (UINTN
) (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+
200 MemoryHob
->AllocDescriptor
.MemoryLength
);
201 if (!((WakeupBufferStart
>= MemoryEnd
) || (WakeupBufferEnd
<= MemoryStart
))) {
206 Hob
.Raw
= GET_NEXT_HOB (Hob
);
212 Get available system memory below 1MB by specified size.
214 @param[in] WakeupBufferSize Wakeup buffer size required
216 @retval other Return wakeup buffer address below 1MB.
217 @retval -1 Cannot find free memory below 1MB.
221 IN UINTN WakeupBufferSize
224 EFI_PEI_HOB_POINTERS Hob
;
225 UINTN WakeupBufferStart
;
226 UINTN WakeupBufferEnd
;
228 WakeupBufferSize
= (WakeupBufferSize
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
231 // Get the HOB list for processing
233 Hob
.Raw
= GetHobList ();
236 // Collect memory ranges
238 while (!END_OF_HOB_LIST (Hob
)) {
239 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
240 if ((Hob
.ResourceDescriptor
->PhysicalStart
< BASE_1MB
) &&
241 (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
242 ((Hob
.ResourceDescriptor
->ResourceAttribute
&
243 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
|
244 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
|
245 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
249 // Need memory under 1MB to be collected here
251 WakeupBufferEnd
= (UINTN
) (Hob
.ResourceDescriptor
->PhysicalStart
+ Hob
.ResourceDescriptor
->ResourceLength
);
252 if (WakeupBufferEnd
> BASE_1MB
) {
254 // Wakeup buffer should be under 1MB
256 WakeupBufferEnd
= BASE_1MB
;
258 while (WakeupBufferEnd
> WakeupBufferSize
) {
260 // Wakeup buffer should be aligned on 4KB
262 WakeupBufferStart
= (WakeupBufferEnd
- WakeupBufferSize
) & ~(SIZE_4KB
- 1);
263 if (WakeupBufferStart
< Hob
.ResourceDescriptor
->PhysicalStart
) {
266 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart
, WakeupBufferEnd
)) {
268 // If this range is overlapped with existing allocated buffer, skip it
269 // and find the next range
271 WakeupBufferEnd
-= WakeupBufferSize
;
274 DEBUG ((DEBUG_INFO
, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
275 WakeupBufferStart
, WakeupBufferSize
));
277 // Create a memory allocation HOB.
279 BuildMemoryAllocationHob (
284 return WakeupBufferStart
;
291 Hob
.Raw
= GET_NEXT_HOB (Hob
);
298 Allocate reset vector buffer.
300 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
303 AllocateResetVector (
304 IN OUT CPU_MP_DATA
*CpuMpData
307 UINTN ApResetVectorSize
;
309 if (CpuMpData
->WakeupBuffer
== (UINTN
) -1) {
310 ApResetVectorSize
= CpuMpData
->AddressMap
.RendezvousFunnelSize
+
311 sizeof (MP_CPU_EXCHANGE_INFO
);
313 CpuMpData
->WakeupBuffer
= GetWakeupBuffer (ApResetVectorSize
);
314 CpuMpData
->MpCpuExchangeInfo
= (MP_CPU_EXCHANGE_INFO
*) (UINTN
)
315 (CpuMpData
->WakeupBuffer
+ CpuMpData
->AddressMap
.RendezvousFunnelSize
);
316 BackupAndPrepareWakeupBuffer (CpuMpData
);
319 if (CpuMpData
->EndOfPeiFlag
) {
320 BackupAndPrepareWakeupBuffer (CpuMpData
);
325 Free AP reset vector buffer.
327 @param[in] CpuMpData The pointer to CPU MP Data structure.
331 IN CPU_MP_DATA
*CpuMpData
334 if (CpuMpData
->EndOfPeiFlag
) {
335 RestoreWakeupBuffer (CpuMpData
);
340 Initialize global data for MP support.
342 @param[in] CpuMpData The pointer to CPU MP Data structure.
346 IN CPU_MP_DATA
*CpuMpData
351 SaveCpuMpData (CpuMpData
);
353 // Register an event for EndOfPei
355 Status
= PeiServicesNotifyPpi (&mMpInitLibNotifyList
);
356 ASSERT_EFI_ERROR (Status
);
360 This service executes a caller provided function on all enabled APs.
362 @param[in] Procedure A pointer to the function to be run on
363 enabled APs of the system. See type
365 @param[in] SingleThread If TRUE, then all the enabled APs execute
366 the function specified by Procedure one by
367 one, in ascending order of processor handle
368 number. If FALSE, then all the enabled APs
369 execute the function specified by Procedure
371 @param[in] WaitEvent The event created by the caller with CreateEvent()
372 service. If it is NULL, then execute in
373 blocking mode. BSP waits until all APs finish
374 or TimeoutInMicroSeconds expires. If it's
375 not NULL, then execute in non-blocking mode.
376 BSP requests the function specified by
377 Procedure to be started on all the enabled
378 APs, and go on executing immediately. If
379 all return from Procedure, or TimeoutInMicroSeconds
380 expires, this event is signaled. The BSP
381 can use the CheckEvent() or WaitForEvent()
382 services to check the state of event. Type
383 EFI_EVENT is defined in CreateEvent() in
384 the Unified Extensible Firmware Interface
386 @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for
387 APs to return from Procedure, either for
388 blocking or non-blocking mode. Zero means
389 infinity. If the timeout expires before
390 all APs return from Procedure, then Procedure
391 on the failed APs is terminated. All enabled
392 APs are available for next function assigned
393 by MpInitLibStartupAllAPs() or
394 MPInitLibStartupThisAP().
395 If the timeout expires in blocking mode,
396 BSP returns EFI_TIMEOUT. If the timeout
397 expires in non-blocking mode, WaitEvent
398 is signaled with SignalEvent().
399 @param[in] ProcedureArgument The parameter passed into Procedure for
401 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
402 if all APs finish successfully, then its
403 content is set to NULL. If not all APs
404 finish before timeout expires, then its
405 content is set to address of the buffer
406 holding handle numbers of the failed APs.
407 The buffer is allocated by MP Initialization
408 library, and it's the caller's responsibility to
409 free the buffer with FreePool() service.
410 In blocking mode, it is ready for consumption
411 when the call returns. In non-blocking mode,
412 it is ready when WaitEvent is signaled. The
413 list of failed CPU is terminated by
416 @retval EFI_SUCCESS In blocking mode, all APs have finished before
418 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
420 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
421 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
423 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
425 @retval EFI_DEVICE_ERROR Caller processor is AP.
426 @retval EFI_NOT_STARTED No enabled APs exist in the system.
427 @retval EFI_NOT_READY Any enabled APs are busy.
428 @retval EFI_NOT_READY MP Initialize Library is not initialized.
429 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
430 all enabled APs have finished.
431 @retval EFI_INVALID_PARAMETER Procedure is NULL.
436 MpInitLibStartupAllAPs (
437 IN EFI_AP_PROCEDURE Procedure
,
438 IN BOOLEAN SingleThread
,
439 IN EFI_EVENT WaitEvent OPTIONAL
,
440 IN UINTN TimeoutInMicroseconds
,
441 IN VOID
*ProcedureArgument OPTIONAL
,
442 OUT UINTN
**FailedCpuList OPTIONAL
445 return EFI_UNSUPPORTED
;
449 This service lets the caller get one enabled AP to execute a caller-provided
452 @param[in] Procedure A pointer to the function to be run on the
453 designated AP of the system. See type
455 @param[in] ProcessorNumber The handle number of the AP. The range is
456 from 0 to the total number of logical
457 processors minus 1. The total number of
458 logical processors can be retrieved by
459 MpInitLibGetNumberOfProcessors().
460 @param[in] WaitEvent The event created by the caller with CreateEvent()
461 service. If it is NULL, then execute in
462 blocking mode. BSP waits until this AP finish
463 or TimeoutInMicroSeconds expires. If it's
464 not NULL, then execute in non-blocking mode.
465 BSP requests the function specified by
466 Procedure to be started on this AP,
467 and go on executing immediately. If this AP
468 return from Procedure or TimeoutInMicroSeconds
469 expires, this event is signaled. The BSP
470 can use the CheckEvent() or WaitForEvent()
471 services to check the state of event. Type
472 EFI_EVENT is defined in CreateEvent() in
473 the Unified Extensible Firmware Interface
475 @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for
476 this AP to finish this Procedure, either for
477 blocking or non-blocking mode. Zero means
478 infinity. If the timeout expires before
479 this AP returns from Procedure, then Procedure
480 on the AP is terminated. The
481 AP is available for next function assigned
482 by MpInitLibStartupAllAPs() or
483 MpInitLibStartupThisAP().
484 If the timeout expires in blocking mode,
485 BSP returns EFI_TIMEOUT. If the timeout
486 expires in non-blocking mode, WaitEvent
487 is signaled with SignalEvent().
488 @param[in] ProcedureArgument The parameter passed into Procedure on the
490 @param[out] Finished If NULL, this parameter is ignored. In
491 blocking mode, this parameter is ignored.
492 In non-blocking mode, if AP returns from
493 Procedure before the timeout expires, its
494 content is set to TRUE. Otherwise, the
495 value is set to FALSE. The caller can
496 determine if the AP returned from Procedure
497 by evaluating this value.
499 @retval EFI_SUCCESS In blocking mode, specified AP finished before
501 @retval EFI_SUCCESS In non-blocking mode, the function has been
502 dispatched to specified AP.
503 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
504 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
506 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
508 @retval EFI_DEVICE_ERROR The calling processor is an AP.
509 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
510 the specified AP has finished.
511 @retval EFI_NOT_READY The specified AP is busy.
512 @retval EFI_NOT_READY MP Initialize Library is not initialized.
513 @retval EFI_NOT_FOUND The processor with the handle specified by
514 ProcessorNumber does not exist.
515 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
516 @retval EFI_INVALID_PARAMETER Procedure is NULL.
521 MpInitLibStartupThisAP (
522 IN EFI_AP_PROCEDURE Procedure
,
523 IN UINTN ProcessorNumber
,
524 IN EFI_EVENT WaitEvent OPTIONAL
,
525 IN UINTN TimeoutInMicroseconds
,
526 IN VOID
*ProcedureArgument OPTIONAL
,
527 OUT BOOLEAN
*Finished OPTIONAL
530 return EFI_UNSUPPORTED
;
534 This service switches the requested AP to be the BSP from that point onward.
535 This service changes the BSP for all purposes. This call can only be performed
538 @param[in] ProcessorNumber The handle number of AP that is to become the new
539 BSP. The range is from 0 to the total number of
540 logical processors minus 1. The total number of
541 logical processors can be retrieved by
542 MpInitLibGetNumberOfProcessors().
543 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
544 enabled AP. Otherwise, it will be disabled.
546 @retval EFI_SUCCESS BSP successfully switched.
547 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
548 this service returning.
549 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
550 @retval EFI_DEVICE_ERROR The calling processor is an AP.
551 @retval EFI_NOT_FOUND The processor with the handle specified by
552 ProcessorNumber does not exist.
553 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
555 @retval EFI_NOT_READY The specified AP is busy.
556 @retval EFI_NOT_READY MP Initialize Library is not initialized.
562 IN UINTN ProcessorNumber
,
563 IN BOOLEAN EnableOldBSP
566 return EFI_UNSUPPORTED
;
570 This service lets the caller enable or disable an AP from this point onward.
571 This service may only be called from the BSP.
573 @param[in] ProcessorNumber The handle number of AP.
574 The range is from 0 to the total number of
575 logical processors minus 1. The total number of
576 logical processors can be retrieved by
577 MpInitLibGetNumberOfProcessors().
578 @param[in] EnableAP Specifies the new state for the processor for
579 enabled, FALSE for disabled.
580 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
581 the new health status of the AP. This flag
582 corresponds to StatusFlag defined in
583 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
584 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
585 bits are ignored. If it is NULL, this parameter
588 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
589 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
590 prior to this service returning.
591 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
592 @retval EFI_DEVICE_ERROR The calling processor is an AP.
593 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
595 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
596 @retval EFI_NOT_READY MP Initialize Library is not initialized.
601 MpInitLibEnableDisableAP (
602 IN UINTN ProcessorNumber
,
604 IN UINT32
*HealthFlag OPTIONAL
607 return EFI_UNSUPPORTED
;