2 MP initialize support functions for PEI phase.
4 Copyright (c) 2016 - 2017, 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.
18 Enable Debug Agent to support source debugging on AP function.
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 Check if AP wakeup buffer is overlapped with existing allocated buffer.
70 @param[in] WakeupBufferStart AP wakeup buffer start address.
71 @param[in] WakeupBufferEnd AP wakeup buffer end address.
73 @retval TRUE There is overlap.
74 @retval FALSE There is no overlap.
77 CheckOverlapWithAllocatedBuffer (
78 IN UINTN WakeupBufferStart
,
79 IN UINTN WakeupBufferEnd
82 EFI_PEI_HOB_POINTERS Hob
;
83 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
90 // Get the HOB list for processing
92 Hob
.Raw
= GetHobList ();
94 // Collect memory ranges
96 while (!END_OF_HOB_LIST (Hob
)) {
97 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
98 MemoryHob
= Hob
.MemoryAllocation
;
99 MemoryStart
= (UINTN
) MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
100 MemoryEnd
= (UINTN
) (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+
101 MemoryHob
->AllocDescriptor
.MemoryLength
);
102 if (!((WakeupBufferStart
>= MemoryEnd
) || (WakeupBufferEnd
<= MemoryStart
))) {
107 Hob
.Raw
= GET_NEXT_HOB (Hob
);
113 Get available system memory below 1MB by specified size.
115 @param[in] WakeupBufferSize Wakeup buffer size required
117 @retval other Return wakeup buffer address below 1MB.
118 @retval -1 Cannot find free memory below 1MB.
122 IN UINTN WakeupBufferSize
125 EFI_PEI_HOB_POINTERS Hob
;
126 UINTN WakeupBufferStart
;
127 UINTN WakeupBufferEnd
;
129 WakeupBufferSize
= (WakeupBufferSize
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
132 // Get the HOB list for processing
134 Hob
.Raw
= GetHobList ();
137 // Collect memory ranges
139 while (!END_OF_HOB_LIST (Hob
)) {
140 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
141 if ((Hob
.ResourceDescriptor
->PhysicalStart
< BASE_1MB
) &&
142 (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
143 ((Hob
.ResourceDescriptor
->ResourceAttribute
&
144 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
|
145 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
|
146 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
150 // Need memory under 1MB to be collected here
152 WakeupBufferEnd
= (UINTN
) (Hob
.ResourceDescriptor
->PhysicalStart
+ Hob
.ResourceDescriptor
->ResourceLength
);
153 if (WakeupBufferEnd
> BASE_1MB
) {
155 // Wakeup buffer should be under 1MB
157 WakeupBufferEnd
= BASE_1MB
;
159 while (WakeupBufferEnd
> WakeupBufferSize
) {
161 // Wakeup buffer should be aligned on 4KB
163 WakeupBufferStart
= (WakeupBufferEnd
- WakeupBufferSize
) & ~(SIZE_4KB
- 1);
164 if (WakeupBufferStart
< Hob
.ResourceDescriptor
->PhysicalStart
) {
167 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart
, WakeupBufferEnd
)) {
169 // If this range is overlapped with existing allocated buffer, skip it
170 // and find the next range
172 WakeupBufferEnd
-= WakeupBufferSize
;
175 DEBUG ((DEBUG_INFO
, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
176 WakeupBufferStart
, WakeupBufferSize
));
177 return WakeupBufferStart
;
184 Hob
.Raw
= GET_NEXT_HOB (Hob
);
191 Get available EfiBootServicesCode memory below 4GB by specified size.
193 This buffer is required to safely transfer AP from real address mode to
194 protected mode or long mode, due to the fact that the buffer returned by
195 GetWakeupBuffer() may be marked as non-executable.
197 @param[in] BufferSize Wakeup transition buffer size.
199 @retval other Return wakeup transition buffer address below 4GB.
200 @retval 0 Cannot find free memory below 4GB.
203 GetModeTransitionBuffer (
208 // PEI phase doesn't need to do such transition. So simply return 0.
214 Checks APs status and updates APs status if needed.
218 CheckAndUpdateApsStatus (
225 Initialize global data for MP support.
227 @param[in] CpuMpData The pointer to CPU MP Data structure.
231 IN CPU_MP_DATA
*CpuMpData
234 SaveCpuMpData (CpuMpData
);
238 This service executes a caller provided function on all enabled APs.
240 @param[in] Procedure A pointer to the function to be run on
241 enabled APs of the system. See type
243 @param[in] SingleThread If TRUE, then all the enabled APs execute
244 the function specified by Procedure one by
245 one, in ascending order of processor handle
246 number. If FALSE, then all the enabled APs
247 execute the function specified by Procedure
249 @param[in] WaitEvent The event created by the caller with CreateEvent()
250 service. If it is NULL, then execute in
251 blocking mode. BSP waits until all APs finish
252 or TimeoutInMicroSeconds expires. If it's
253 not NULL, then execute in non-blocking mode.
254 BSP requests the function specified by
255 Procedure to be started on all the enabled
256 APs, and go on executing immediately. If
257 all return from Procedure, or TimeoutInMicroSeconds
258 expires, this event is signaled. The BSP
259 can use the CheckEvent() or WaitForEvent()
260 services to check the state of event. Type
261 EFI_EVENT is defined in CreateEvent() in
262 the Unified Extensible Firmware Interface
264 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
265 APs to return from Procedure, either for
266 blocking or non-blocking mode. Zero means
267 infinity. If the timeout expires before
268 all APs return from Procedure, then Procedure
269 on the failed APs is terminated. All enabled
270 APs are available for next function assigned
271 by MpInitLibStartupAllAPs() or
272 MPInitLibStartupThisAP().
273 If the timeout expires in blocking mode,
274 BSP returns EFI_TIMEOUT. If the timeout
275 expires in non-blocking mode, WaitEvent
276 is signaled with SignalEvent().
277 @param[in] ProcedureArgument The parameter passed into Procedure for
279 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
280 if all APs finish successfully, then its
281 content is set to NULL. If not all APs
282 finish before timeout expires, then its
283 content is set to address of the buffer
284 holding handle numbers of the failed APs.
285 The buffer is allocated by MP Initialization
286 library, and it's the caller's responsibility to
287 free the buffer with FreePool() service.
288 In blocking mode, it is ready for consumption
289 when the call returns. In non-blocking mode,
290 it is ready when WaitEvent is signaled. The
291 list of failed CPU is terminated by
294 @retval EFI_SUCCESS In blocking mode, all APs have finished before
296 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
298 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
299 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
301 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
303 @retval EFI_DEVICE_ERROR Caller processor is AP.
304 @retval EFI_NOT_STARTED No enabled APs exist in the system.
305 @retval EFI_NOT_READY Any enabled APs are busy.
306 @retval EFI_NOT_READY MP Initialize Library is not initialized.
307 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
308 all enabled APs have finished.
309 @retval EFI_INVALID_PARAMETER Procedure is NULL.
314 MpInitLibStartupAllAPs (
315 IN EFI_AP_PROCEDURE Procedure
,
316 IN BOOLEAN SingleThread
,
317 IN EFI_EVENT WaitEvent OPTIONAL
,
318 IN UINTN TimeoutInMicroseconds
,
319 IN VOID
*ProcedureArgument OPTIONAL
,
320 OUT UINTN
**FailedCpuList OPTIONAL
323 if (WaitEvent
!= NULL
) {
324 return EFI_UNSUPPORTED
;
327 return StartupAllAPsWorker (
331 TimeoutInMicroseconds
,
338 This service lets the caller get one enabled AP to execute a caller-provided
341 @param[in] Procedure A pointer to the function to be run on the
342 designated AP of the system. See type
344 @param[in] ProcessorNumber The handle number of the AP. The range is
345 from 0 to the total number of logical
346 processors minus 1. The total number of
347 logical processors can be retrieved by
348 MpInitLibGetNumberOfProcessors().
349 @param[in] WaitEvent The event created by the caller with CreateEvent()
350 service. If it is NULL, then execute in
351 blocking mode. BSP waits until this AP finish
352 or TimeoutInMicroSeconds expires. If it's
353 not NULL, then execute in non-blocking mode.
354 BSP requests the function specified by
355 Procedure to be started on this AP,
356 and go on executing immediately. If this AP
357 return from Procedure or TimeoutInMicroSeconds
358 expires, this event is signaled. The BSP
359 can use the CheckEvent() or WaitForEvent()
360 services to check the state of event. Type
361 EFI_EVENT is defined in CreateEvent() in
362 the Unified Extensible Firmware Interface
364 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
365 this AP to finish this Procedure, either for
366 blocking or non-blocking mode. Zero means
367 infinity. If the timeout expires before
368 this AP returns from Procedure, then Procedure
369 on the AP is terminated. The
370 AP is available for next function assigned
371 by MpInitLibStartupAllAPs() or
372 MpInitLibStartupThisAP().
373 If the timeout expires in blocking mode,
374 BSP returns EFI_TIMEOUT. If the timeout
375 expires in non-blocking mode, WaitEvent
376 is signaled with SignalEvent().
377 @param[in] ProcedureArgument The parameter passed into Procedure on the
379 @param[out] Finished If NULL, this parameter is ignored. In
380 blocking mode, this parameter is ignored.
381 In non-blocking mode, if AP returns from
382 Procedure before the timeout expires, its
383 content is set to TRUE. Otherwise, the
384 value is set to FALSE. The caller can
385 determine if the AP returned from Procedure
386 by evaluating this value.
388 @retval EFI_SUCCESS In blocking mode, specified AP finished before
390 @retval EFI_SUCCESS In non-blocking mode, the function has been
391 dispatched to specified AP.
392 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
393 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
395 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
397 @retval EFI_DEVICE_ERROR The calling processor is an AP.
398 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
399 the specified AP has finished.
400 @retval EFI_NOT_READY The specified AP is busy.
401 @retval EFI_NOT_READY MP Initialize Library is not initialized.
402 @retval EFI_NOT_FOUND The processor with the handle specified by
403 ProcessorNumber does not exist.
404 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
405 @retval EFI_INVALID_PARAMETER Procedure is NULL.
410 MpInitLibStartupThisAP (
411 IN EFI_AP_PROCEDURE Procedure
,
412 IN UINTN ProcessorNumber
,
413 IN EFI_EVENT WaitEvent OPTIONAL
,
414 IN UINTN TimeoutInMicroseconds
,
415 IN VOID
*ProcedureArgument OPTIONAL
,
416 OUT BOOLEAN
*Finished OPTIONAL
419 if (WaitEvent
!= NULL
) {
420 return EFI_UNSUPPORTED
;
423 return StartupThisAPWorker (
427 TimeoutInMicroseconds
,
434 This service switches the requested AP to be the BSP from that point onward.
435 This service changes the BSP for all purposes. This call can only be performed
438 @param[in] ProcessorNumber The handle number of AP that is to become the new
439 BSP. The range is from 0 to the total number of
440 logical processors minus 1. The total number of
441 logical processors can be retrieved by
442 MpInitLibGetNumberOfProcessors().
443 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
444 enabled AP. Otherwise, it will be disabled.
446 @retval EFI_SUCCESS BSP successfully switched.
447 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
448 this service returning.
449 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
450 @retval EFI_DEVICE_ERROR The calling processor is an AP.
451 @retval EFI_NOT_FOUND The processor with the handle specified by
452 ProcessorNumber does not exist.
453 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
455 @retval EFI_NOT_READY The specified AP is busy.
456 @retval EFI_NOT_READY MP Initialize Library is not initialized.
462 IN UINTN ProcessorNumber
,
463 IN BOOLEAN EnableOldBSP
466 return SwitchBSPWorker (ProcessorNumber
, EnableOldBSP
);
470 This service lets the caller enable or disable an AP from this point onward.
471 This service may only be called from the BSP.
473 @param[in] ProcessorNumber The handle number of AP.
474 The range is from 0 to the total number of
475 logical processors minus 1. The total number of
476 logical processors can be retrieved by
477 MpInitLibGetNumberOfProcessors().
478 @param[in] EnableAP Specifies the new state for the processor for
479 enabled, FALSE for disabled.
480 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
481 the new health status of the AP. This flag
482 corresponds to StatusFlag defined in
483 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
484 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
485 bits are ignored. If it is NULL, this parameter
488 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
489 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
490 prior to this service returning.
491 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
492 @retval EFI_DEVICE_ERROR The calling processor is an AP.
493 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
495 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
496 @retval EFI_NOT_READY MP Initialize Library is not initialized.
501 MpInitLibEnableDisableAP (
502 IN UINTN ProcessorNumber
,
504 IN UINT32
*HealthFlag OPTIONAL
507 return EnableDisableApWorker (ProcessorNumber
, EnableAP
, HealthFlag
);