2 MP initialize support functions for PEI phase.
4 Copyright (c) 2016 - 2018, 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.
30 For BSP, the pointer is retrieved from HOB.
31 For AP, the structure is just after IDT.
33 @return The pointer to CPU MP Data structure.
40 CPU_MP_DATA
*CpuMpData
;
41 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr
;
44 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE
);
45 if (ApicBaseMsr
.Bits
.BSP
== 1) {
46 CpuMpData
= GetCpuMpDataFromGuidedHob ();
47 ASSERT (CpuMpData
!= NULL
);
50 CpuMpData
= (CPU_MP_DATA
*) (Idtr
.Base
+ Idtr
.Limit
+ 1);
56 Save the pointer to CPU MP Data structure.
58 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
62 IN CPU_MP_DATA
*CpuMpData
67 // Build location of CPU MP DATA buffer in HOB
69 Data64
= (UINT64
) (UINTN
) CpuMpData
;
71 &mCpuInitMpLibHobGuid
,
78 Check if AP wakeup buffer is overlapped with existing allocated buffer.
80 @param[in] WakeupBufferStart AP wakeup buffer start address.
81 @param[in] WakeupBufferEnd AP wakeup buffer end address.
83 @retval TRUE There is overlap.
84 @retval FALSE There is no overlap.
87 CheckOverlapWithAllocatedBuffer (
88 IN UINT64 WakeupBufferStart
,
89 IN UINT64 WakeupBufferEnd
92 EFI_PEI_HOB_POINTERS Hob
;
93 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
100 // Get the HOB list for processing
102 Hob
.Raw
= GetHobList ();
104 // Collect memory ranges
106 while (!END_OF_HOB_LIST (Hob
)) {
107 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
108 MemoryHob
= Hob
.MemoryAllocation
;
109 MemoryStart
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
110 MemoryEnd
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
;
111 if (!((WakeupBufferStart
>= MemoryEnd
) || (WakeupBufferEnd
<= MemoryStart
))) {
116 Hob
.Raw
= GET_NEXT_HOB (Hob
);
122 Get available system memory below 1MB by specified size.
124 @param[in] WakeupBufferSize Wakeup buffer size required
126 @retval other Return wakeup buffer address below 1MB.
127 @retval -1 Cannot find free memory below 1MB.
131 IN UINTN WakeupBufferSize
134 EFI_PEI_HOB_POINTERS Hob
;
135 UINT64 WakeupBufferStart
;
136 UINT64 WakeupBufferEnd
;
138 WakeupBufferSize
= (WakeupBufferSize
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
141 // Get the HOB list for processing
143 Hob
.Raw
= GetHobList ();
146 // Collect memory ranges
148 while (!END_OF_HOB_LIST (Hob
)) {
149 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
150 if ((Hob
.ResourceDescriptor
->PhysicalStart
< BASE_1MB
) &&
151 (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
152 ((Hob
.ResourceDescriptor
->ResourceAttribute
&
153 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
|
154 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
|
155 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
159 // Need memory under 1MB to be collected here
161 WakeupBufferEnd
= Hob
.ResourceDescriptor
->PhysicalStart
+ Hob
.ResourceDescriptor
->ResourceLength
;
162 if (WakeupBufferEnd
> BASE_1MB
) {
164 // Wakeup buffer should be under 1MB
166 WakeupBufferEnd
= BASE_1MB
;
168 while (WakeupBufferEnd
> WakeupBufferSize
) {
170 // Wakeup buffer should be aligned on 4KB
172 WakeupBufferStart
= (WakeupBufferEnd
- WakeupBufferSize
) & ~(SIZE_4KB
- 1);
173 if (WakeupBufferStart
< Hob
.ResourceDescriptor
->PhysicalStart
) {
176 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart
, WakeupBufferEnd
)) {
178 // If this range is overlapped with existing allocated buffer, skip it
179 // and find the next range
181 WakeupBufferEnd
-= WakeupBufferSize
;
184 DEBUG ((DEBUG_INFO
, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
185 WakeupBufferStart
, WakeupBufferSize
));
186 return (UINTN
)WakeupBufferStart
;
193 Hob
.Raw
= GET_NEXT_HOB (Hob
);
200 Get available EfiBootServicesCode memory below 4GB by specified size.
202 This buffer is required to safely transfer AP from real address mode to
203 protected mode or long mode, due to the fact that the buffer returned by
204 GetWakeupBuffer() may be marked as non-executable.
206 @param[in] BufferSize Wakeup transition buffer size.
208 @retval other Return wakeup transition buffer address below 4GB.
209 @retval 0 Cannot find free memory below 4GB.
212 GetModeTransitionBuffer (
217 // PEI phase doesn't need to do such transition. So simply return 0.
223 Checks APs status and updates APs status if needed.
227 CheckAndUpdateApsStatus (
234 Initialize global data for MP support.
236 @param[in] CpuMpData The pointer to CPU MP Data structure.
240 IN CPU_MP_DATA
*CpuMpData
243 SaveCpuMpData (CpuMpData
);
247 This service executes a caller provided function on all enabled APs.
249 @param[in] Procedure A pointer to the function to be run on
250 enabled APs of the system. See type
252 @param[in] SingleThread If TRUE, then all the enabled APs execute
253 the function specified by Procedure one by
254 one, in ascending order of processor handle
255 number. If FALSE, then all the enabled APs
256 execute the function specified by Procedure
258 @param[in] WaitEvent The event created by the caller with CreateEvent()
259 service. If it is NULL, then execute in
260 blocking mode. BSP waits until all APs finish
261 or TimeoutInMicroSeconds expires. If it's
262 not NULL, then execute in non-blocking mode.
263 BSP requests the function specified by
264 Procedure to be started on all the enabled
265 APs, and go on executing immediately. If
266 all return from Procedure, or TimeoutInMicroSeconds
267 expires, this event is signaled. The BSP
268 can use the CheckEvent() or WaitForEvent()
269 services to check the state of event. Type
270 EFI_EVENT is defined in CreateEvent() in
271 the Unified Extensible Firmware Interface
273 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
274 APs to return from Procedure, either for
275 blocking or non-blocking mode. Zero means
276 infinity. If the timeout expires before
277 all APs return from Procedure, then Procedure
278 on the failed APs is terminated. All enabled
279 APs are available for next function assigned
280 by MpInitLibStartupAllAPs() or
281 MPInitLibStartupThisAP().
282 If the timeout expires in blocking mode,
283 BSP returns EFI_TIMEOUT. If the timeout
284 expires in non-blocking mode, WaitEvent
285 is signaled with SignalEvent().
286 @param[in] ProcedureArgument The parameter passed into Procedure for
288 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
289 if all APs finish successfully, then its
290 content is set to NULL. If not all APs
291 finish before timeout expires, then its
292 content is set to address of the buffer
293 holding handle numbers of the failed APs.
294 The buffer is allocated by MP Initialization
295 library, and it's the caller's responsibility to
296 free the buffer with FreePool() service.
297 In blocking mode, it is ready for consumption
298 when the call returns. In non-blocking mode,
299 it is ready when WaitEvent is signaled. The
300 list of failed CPU is terminated by
303 @retval EFI_SUCCESS In blocking mode, all APs have finished before
305 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
307 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
308 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
310 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
312 @retval EFI_DEVICE_ERROR Caller processor is AP.
313 @retval EFI_NOT_STARTED No enabled APs exist in the system.
314 @retval EFI_NOT_READY Any enabled APs are busy.
315 @retval EFI_NOT_READY MP Initialize Library is not initialized.
316 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
317 all enabled APs have finished.
318 @retval EFI_INVALID_PARAMETER Procedure is NULL.
323 MpInitLibStartupAllAPs (
324 IN EFI_AP_PROCEDURE Procedure
,
325 IN BOOLEAN SingleThread
,
326 IN EFI_EVENT WaitEvent OPTIONAL
,
327 IN UINTN TimeoutInMicroseconds
,
328 IN VOID
*ProcedureArgument OPTIONAL
,
329 OUT UINTN
**FailedCpuList OPTIONAL
332 if (WaitEvent
!= NULL
) {
333 return EFI_UNSUPPORTED
;
336 return StartupAllAPsWorker (
340 TimeoutInMicroseconds
,
347 This service lets the caller get one enabled AP to execute a caller-provided
350 @param[in] Procedure A pointer to the function to be run on the
351 designated AP of the system. See type
353 @param[in] ProcessorNumber The handle number of the AP. The range is
354 from 0 to the total number of logical
355 processors minus 1. The total number of
356 logical processors can be retrieved by
357 MpInitLibGetNumberOfProcessors().
358 @param[in] WaitEvent The event created by the caller with CreateEvent()
359 service. If it is NULL, then execute in
360 blocking mode. BSP waits until this AP finish
361 or TimeoutInMicroSeconds expires. If it's
362 not NULL, then execute in non-blocking mode.
363 BSP requests the function specified by
364 Procedure to be started on this AP,
365 and go on executing immediately. If this AP
366 return from Procedure or TimeoutInMicroSeconds
367 expires, this event is signaled. The BSP
368 can use the CheckEvent() or WaitForEvent()
369 services to check the state of event. Type
370 EFI_EVENT is defined in CreateEvent() in
371 the Unified Extensible Firmware Interface
373 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
374 this AP to finish this Procedure, either for
375 blocking or non-blocking mode. Zero means
376 infinity. If the timeout expires before
377 this AP returns from Procedure, then Procedure
378 on the AP is terminated. The
379 AP is available for next function assigned
380 by MpInitLibStartupAllAPs() or
381 MpInitLibStartupThisAP().
382 If the timeout expires in blocking mode,
383 BSP returns EFI_TIMEOUT. If the timeout
384 expires in non-blocking mode, WaitEvent
385 is signaled with SignalEvent().
386 @param[in] ProcedureArgument The parameter passed into Procedure on the
388 @param[out] Finished If NULL, this parameter is ignored. In
389 blocking mode, this parameter is ignored.
390 In non-blocking mode, if AP returns from
391 Procedure before the timeout expires, its
392 content is set to TRUE. Otherwise, the
393 value is set to FALSE. The caller can
394 determine if the AP returned from Procedure
395 by evaluating this value.
397 @retval EFI_SUCCESS In blocking mode, specified AP finished before
399 @retval EFI_SUCCESS In non-blocking mode, the function has been
400 dispatched to specified AP.
401 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
402 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
404 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
406 @retval EFI_DEVICE_ERROR The calling processor is an AP.
407 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
408 the specified AP has finished.
409 @retval EFI_NOT_READY The specified AP is busy.
410 @retval EFI_NOT_READY MP Initialize Library is not initialized.
411 @retval EFI_NOT_FOUND The processor with the handle specified by
412 ProcessorNumber does not exist.
413 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
414 @retval EFI_INVALID_PARAMETER Procedure is NULL.
419 MpInitLibStartupThisAP (
420 IN EFI_AP_PROCEDURE Procedure
,
421 IN UINTN ProcessorNumber
,
422 IN EFI_EVENT WaitEvent OPTIONAL
,
423 IN UINTN TimeoutInMicroseconds
,
424 IN VOID
*ProcedureArgument OPTIONAL
,
425 OUT BOOLEAN
*Finished OPTIONAL
428 if (WaitEvent
!= NULL
) {
429 return EFI_UNSUPPORTED
;
432 return StartupThisAPWorker (
436 TimeoutInMicroseconds
,
443 This service switches the requested AP to be the BSP from that point onward.
444 This service changes the BSP for all purposes. This call can only be performed
447 @param[in] ProcessorNumber The handle number of AP that is to become the new
448 BSP. The range is from 0 to the total number of
449 logical processors minus 1. The total number of
450 logical processors can be retrieved by
451 MpInitLibGetNumberOfProcessors().
452 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
453 enabled AP. Otherwise, it will be disabled.
455 @retval EFI_SUCCESS BSP successfully switched.
456 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
457 this service returning.
458 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
459 @retval EFI_DEVICE_ERROR The calling processor is an AP.
460 @retval EFI_NOT_FOUND The processor with the handle specified by
461 ProcessorNumber does not exist.
462 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
464 @retval EFI_NOT_READY The specified AP is busy.
465 @retval EFI_NOT_READY MP Initialize Library is not initialized.
471 IN UINTN ProcessorNumber
,
472 IN BOOLEAN EnableOldBSP
475 return SwitchBSPWorker (ProcessorNumber
, EnableOldBSP
);
479 This service lets the caller enable or disable an AP from this point onward.
480 This service may only be called from the BSP.
482 @param[in] ProcessorNumber The handle number of AP.
483 The range is from 0 to the total number of
484 logical processors minus 1. The total number of
485 logical processors can be retrieved by
486 MpInitLibGetNumberOfProcessors().
487 @param[in] EnableAP Specifies the new state for the processor for
488 enabled, FALSE for disabled.
489 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
490 the new health status of the AP. This flag
491 corresponds to StatusFlag defined in
492 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
493 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
494 bits are ignored. If it is NULL, this parameter
497 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
498 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
499 prior to this service returning.
500 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
501 @retval EFI_DEVICE_ERROR The calling processor is an AP.
502 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
504 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
505 @retval EFI_NOT_READY MP Initialize Library is not initialized.
510 MpInitLibEnableDisableAP (
511 IN UINTN ProcessorNumber
,
513 IN UINT32
*HealthFlag OPTIONAL
516 return EnableDisableApWorker (ProcessorNumber
, EnableAP
, HealthFlag
);