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 Checks APs status and updates APs status if needed.
195 CheckAndUpdateApsStatus (
202 Initialize global data for MP support.
204 @param[in] CpuMpData The pointer to CPU MP Data structure.
208 IN CPU_MP_DATA
*CpuMpData
211 SaveCpuMpData (CpuMpData
);
215 This service executes a caller provided function on all enabled APs.
217 @param[in] Procedure A pointer to the function to be run on
218 enabled APs of the system. See type
220 @param[in] SingleThread If TRUE, then all the enabled APs execute
221 the function specified by Procedure one by
222 one, in ascending order of processor handle
223 number. If FALSE, then all the enabled APs
224 execute the function specified by Procedure
226 @param[in] WaitEvent The event created by the caller with CreateEvent()
227 service. If it is NULL, then execute in
228 blocking mode. BSP waits until all APs finish
229 or TimeoutInMicroSeconds expires. If it's
230 not NULL, then execute in non-blocking mode.
231 BSP requests the function specified by
232 Procedure to be started on all the enabled
233 APs, and go on executing immediately. If
234 all return from Procedure, or TimeoutInMicroSeconds
235 expires, this event is signaled. The BSP
236 can use the CheckEvent() or WaitForEvent()
237 services to check the state of event. Type
238 EFI_EVENT is defined in CreateEvent() in
239 the Unified Extensible Firmware Interface
241 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
242 APs to return from Procedure, either for
243 blocking or non-blocking mode. Zero means
244 infinity. If the timeout expires before
245 all APs return from Procedure, then Procedure
246 on the failed APs is terminated. All enabled
247 APs are available for next function assigned
248 by MpInitLibStartupAllAPs() or
249 MPInitLibStartupThisAP().
250 If the timeout expires in blocking mode,
251 BSP returns EFI_TIMEOUT. If the timeout
252 expires in non-blocking mode, WaitEvent
253 is signaled with SignalEvent().
254 @param[in] ProcedureArgument The parameter passed into Procedure for
256 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
257 if all APs finish successfully, then its
258 content is set to NULL. If not all APs
259 finish before timeout expires, then its
260 content is set to address of the buffer
261 holding handle numbers of the failed APs.
262 The buffer is allocated by MP Initialization
263 library, and it's the caller's responsibility to
264 free the buffer with FreePool() service.
265 In blocking mode, it is ready for consumption
266 when the call returns. In non-blocking mode,
267 it is ready when WaitEvent is signaled. The
268 list of failed CPU is terminated by
271 @retval EFI_SUCCESS In blocking mode, all APs have finished before
273 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
275 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
276 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
278 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
280 @retval EFI_DEVICE_ERROR Caller processor is AP.
281 @retval EFI_NOT_STARTED No enabled APs exist in the system.
282 @retval EFI_NOT_READY Any enabled APs are busy.
283 @retval EFI_NOT_READY MP Initialize Library is not initialized.
284 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
285 all enabled APs have finished.
286 @retval EFI_INVALID_PARAMETER Procedure is NULL.
291 MpInitLibStartupAllAPs (
292 IN EFI_AP_PROCEDURE Procedure
,
293 IN BOOLEAN SingleThread
,
294 IN EFI_EVENT WaitEvent OPTIONAL
,
295 IN UINTN TimeoutInMicroseconds
,
296 IN VOID
*ProcedureArgument OPTIONAL
,
297 OUT UINTN
**FailedCpuList OPTIONAL
300 if (WaitEvent
!= NULL
) {
301 return EFI_UNSUPPORTED
;
304 return StartupAllAPsWorker (
308 TimeoutInMicroseconds
,
315 This service lets the caller get one enabled AP to execute a caller-provided
318 @param[in] Procedure A pointer to the function to be run on the
319 designated AP of the system. See type
321 @param[in] ProcessorNumber The handle number of the AP. The range is
322 from 0 to the total number of logical
323 processors minus 1. The total number of
324 logical processors can be retrieved by
325 MpInitLibGetNumberOfProcessors().
326 @param[in] WaitEvent The event created by the caller with CreateEvent()
327 service. If it is NULL, then execute in
328 blocking mode. BSP waits until this AP finish
329 or TimeoutInMicroSeconds expires. If it's
330 not NULL, then execute in non-blocking mode.
331 BSP requests the function specified by
332 Procedure to be started on this AP,
333 and go on executing immediately. If this AP
334 return from Procedure or TimeoutInMicroSeconds
335 expires, this event is signaled. The BSP
336 can use the CheckEvent() or WaitForEvent()
337 services to check the state of event. Type
338 EFI_EVENT is defined in CreateEvent() in
339 the Unified Extensible Firmware Interface
341 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
342 this AP to finish this Procedure, either for
343 blocking or non-blocking mode. Zero means
344 infinity. If the timeout expires before
345 this AP returns from Procedure, then Procedure
346 on the AP is terminated. The
347 AP is available for next function assigned
348 by MpInitLibStartupAllAPs() or
349 MpInitLibStartupThisAP().
350 If the timeout expires in blocking mode,
351 BSP returns EFI_TIMEOUT. If the timeout
352 expires in non-blocking mode, WaitEvent
353 is signaled with SignalEvent().
354 @param[in] ProcedureArgument The parameter passed into Procedure on the
356 @param[out] Finished If NULL, this parameter is ignored. In
357 blocking mode, this parameter is ignored.
358 In non-blocking mode, if AP returns from
359 Procedure before the timeout expires, its
360 content is set to TRUE. Otherwise, the
361 value is set to FALSE. The caller can
362 determine if the AP returned from Procedure
363 by evaluating this value.
365 @retval EFI_SUCCESS In blocking mode, specified AP finished before
367 @retval EFI_SUCCESS In non-blocking mode, the function has been
368 dispatched to specified AP.
369 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
370 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
372 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
374 @retval EFI_DEVICE_ERROR The calling processor is an AP.
375 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
376 the specified AP has finished.
377 @retval EFI_NOT_READY The specified AP is busy.
378 @retval EFI_NOT_READY MP Initialize Library is not initialized.
379 @retval EFI_NOT_FOUND The processor with the handle specified by
380 ProcessorNumber does not exist.
381 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
382 @retval EFI_INVALID_PARAMETER Procedure is NULL.
387 MpInitLibStartupThisAP (
388 IN EFI_AP_PROCEDURE Procedure
,
389 IN UINTN ProcessorNumber
,
390 IN EFI_EVENT WaitEvent OPTIONAL
,
391 IN UINTN TimeoutInMicroseconds
,
392 IN VOID
*ProcedureArgument OPTIONAL
,
393 OUT BOOLEAN
*Finished OPTIONAL
396 if (WaitEvent
!= NULL
) {
397 return EFI_UNSUPPORTED
;
400 return StartupThisAPWorker (
404 TimeoutInMicroseconds
,
411 This service switches the requested AP to be the BSP from that point onward.
412 This service changes the BSP for all purposes. This call can only be performed
415 @param[in] ProcessorNumber The handle number of AP that is to become the new
416 BSP. The range is from 0 to the total number of
417 logical processors minus 1. The total number of
418 logical processors can be retrieved by
419 MpInitLibGetNumberOfProcessors().
420 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
421 enabled AP. Otherwise, it will be disabled.
423 @retval EFI_SUCCESS BSP successfully switched.
424 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
425 this service returning.
426 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
427 @retval EFI_DEVICE_ERROR The calling processor is an AP.
428 @retval EFI_NOT_FOUND The processor with the handle specified by
429 ProcessorNumber does not exist.
430 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
432 @retval EFI_NOT_READY The specified AP is busy.
433 @retval EFI_NOT_READY MP Initialize Library is not initialized.
439 IN UINTN ProcessorNumber
,
440 IN BOOLEAN EnableOldBSP
443 return SwitchBSPWorker (ProcessorNumber
, EnableOldBSP
);
447 This service lets the caller enable or disable an AP from this point onward.
448 This service may only be called from the BSP.
450 @param[in] ProcessorNumber The handle number of AP.
451 The range is from 0 to the total number of
452 logical processors minus 1. The total number of
453 logical processors can be retrieved by
454 MpInitLibGetNumberOfProcessors().
455 @param[in] EnableAP Specifies the new state for the processor for
456 enabled, FALSE for disabled.
457 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
458 the new health status of the AP. This flag
459 corresponds to StatusFlag defined in
460 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
461 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
462 bits are ignored. If it is NULL, this parameter
465 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
466 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
467 prior to this service returning.
468 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
469 @retval EFI_DEVICE_ERROR The calling processor is an AP.
470 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
472 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
473 @retval EFI_NOT_READY MP Initialize Library is not initialized.
478 MpInitLibEnableDisableAP (
479 IN UINTN ProcessorNumber
,
481 IN UINT32
*HealthFlag OPTIONAL
484 return EnableDisableApWorker (ProcessorNumber
, EnableAP
, HealthFlag
);