2 CPU PEI Module installs CPU Multiple Processor PPI.
4 Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 extern EDKII_PEI_MP_SERVICES2_PPI mMpServices2Ppi
;
14 // CPU MP PPI to be installed
16 EFI_PEI_MP_SERVICES_PPI mMpServicesPpi
= {
17 PeiGetNumberOfProcessors
,
26 EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiList
[] = {
28 EFI_PEI_PPI_DESCRIPTOR_PPI
,
29 &gEdkiiPeiMpServices2PpiGuid
,
33 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
34 &gEfiPeiMpServicesPpiGuid
,
40 This service retrieves the number of logical processor in the platform
41 and the number of those logical processors that are enabled on this boot.
42 This service may only be called from the BSP.
44 This function is used to retrieve the following information:
45 - The number of logical processors that are present in the system.
46 - The number of enabled logical processors in the system at the instant
49 Because MP Service Ppi provides services to enable and disable processors
50 dynamically, the number of enabled logical processors may vary during the
51 course of a boot session.
53 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
54 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
55 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
56 is returned in NumberOfProcessors, the number of currently enabled processor
57 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
59 @param[in] PeiServices An indirect pointer to the PEI Services Table
60 published by the PEI Foundation.
61 @param[in] This Pointer to this instance of the PPI.
62 @param[out] NumberOfProcessors Pointer to the total number of logical processors in
63 the system, including the BSP and disabled APs.
64 @param[out] NumberOfEnabledProcessors
65 Number of processors in the system that are enabled.
67 @retval EFI_SUCCESS The number of logical processors and enabled
68 logical processors was retrieved.
69 @retval EFI_DEVICE_ERROR The calling processor is an AP.
70 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
71 NumberOfEnabledProcessors is NULL.
75 PeiGetNumberOfProcessors (
76 IN CONST EFI_PEI_SERVICES
**PeiServices
,
77 IN EFI_PEI_MP_SERVICES_PPI
*This
,
78 OUT UINTN
*NumberOfProcessors
,
79 OUT UINTN
*NumberOfEnabledProcessors
82 if ((NumberOfProcessors
== NULL
) || (NumberOfEnabledProcessors
== NULL
)) {
83 return EFI_INVALID_PARAMETER
;
86 return MpInitLibGetNumberOfProcessors (
88 NumberOfEnabledProcessors
93 Gets detailed MP-related information on the requested processor at the
94 instant this call is made. This service may only be called from the BSP.
96 This service retrieves detailed MP-related information about any processor
97 on the platform. Note the following:
98 - The processor information may change during the course of a boot session.
99 - The information presented here is entirely MP related.
101 Information regarding the number of caches and their sizes, frequency of operation,
102 slot numbers is all considered platform-related information and is not provided
105 @param[in] PeiServices An indirect pointer to the PEI Services Table
106 published by the PEI Foundation.
107 @param[in] This Pointer to this instance of the PPI.
108 @param[in] ProcessorNumber Pointer to the total number of logical processors in
109 the system, including the BSP and disabled APs.
110 @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
112 @retval EFI_SUCCESS Processor information was returned.
113 @retval EFI_DEVICE_ERROR The calling processor is an AP.
114 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
115 @retval EFI_NOT_FOUND The processor with the handle specified by
116 ProcessorNumber does not exist in the platform.
120 PeiGetProcessorInfo (
121 IN CONST EFI_PEI_SERVICES
**PeiServices
,
122 IN EFI_PEI_MP_SERVICES_PPI
*This
,
123 IN UINTN ProcessorNumber
,
124 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
127 return MpInitLibGetProcessorInfo (ProcessorNumber
, ProcessorInfoBuffer
, NULL
);
131 This service executes a caller provided function on all enabled APs. APs can
132 run either simultaneously or one at a time in sequence. This service supports
133 both blocking requests only. This service may only
134 be called from the BSP.
136 This function is used to dispatch all the enabled APs to the function specified
137 by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
138 immediately and Procedure is not started on any AP.
140 If SingleThread is TRUE, all the enabled APs execute the function specified by
141 Procedure one by one, in ascending order of processor handle number. Otherwise,
142 all the enabled APs execute the function specified by Procedure simultaneously.
144 If the timeout specified by TimeoutInMicroSeconds expires before all APs return
145 from Procedure, then Procedure on the failed APs is terminated. All enabled APs
146 are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
147 and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
148 content points to the list of processor handle numbers in which Procedure was
151 Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
152 to make sure that the nature of the code that is executed on the BSP and the
153 dispatched APs is well controlled. The MP Services Ppi does not guarantee
154 that the Procedure function is MP-safe. Hence, the tasks that can be run in
155 parallel are limited to certain independent tasks and well-controlled exclusive
156 code. PEI services and Ppis may not be called by APs unless otherwise
159 In blocking execution mode, BSP waits until all APs finish or
160 TimeoutInMicroSeconds expires.
162 @param[in] PeiServices An indirect pointer to the PEI Services Table
163 published by the PEI Foundation.
164 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
165 @param[in] Procedure A pointer to the function to be run on enabled APs of
167 @param[in] SingleThread If TRUE, then all the enabled APs execute the function
168 specified by Procedure one by one, in ascending order
169 of processor handle number. If FALSE, then all the
170 enabled APs execute the function specified by Procedure
172 @param[in] TimeoutInMicroSeconds
173 Indicates the time limit in microseconds for APs to
174 return from Procedure, for blocking mode only. Zero
175 means infinity. If the timeout expires before all APs
176 return from Procedure, then Procedure on the failed APs
177 is terminated. All enabled APs are available for next
178 function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
179 or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
180 timeout expires in blocking mode, BSP returns
182 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
184 @retval EFI_SUCCESS In blocking mode, all APs have finished before the
186 @retval EFI_DEVICE_ERROR Caller processor is AP.
187 @retval EFI_NOT_STARTED No enabled APs exist in the system.
188 @retval EFI_NOT_READY Any enabled APs are busy.
189 @retval EFI_TIMEOUT In blocking mode, the timeout expired before all
190 enabled APs have finished.
191 @retval EFI_INVALID_PARAMETER Procedure is NULL.
196 IN CONST EFI_PEI_SERVICES
**PeiServices
,
197 IN EFI_PEI_MP_SERVICES_PPI
*This
,
198 IN EFI_AP_PROCEDURE Procedure
,
199 IN BOOLEAN SingleThread
,
200 IN UINTN TimeoutInMicroSeconds
,
201 IN VOID
*ProcedureArgument OPTIONAL
204 return MpInitLibStartupAllAPs (
208 TimeoutInMicroSeconds
,
215 This service lets the caller get one enabled AP to execute a caller-provided
216 function. The caller can request the BSP to wait for the completion
217 of the AP. This service may only be called from the BSP.
219 This function is used to dispatch one enabled AP to the function specified by
220 Procedure passing in the argument specified by ProcedureArgument.
221 The execution is in blocking mode. The BSP waits until the AP finishes or
222 TimeoutInMicroSecondss expires.
224 If the timeout specified by TimeoutInMicroseconds expires before the AP returns
225 from Procedure, then execution of Procedure by the AP is terminated. The AP is
226 available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and
227 EFI_PEI_MP_SERVICES_PPI.StartupThisAP().
229 @param[in] PeiServices An indirect pointer to the PEI Services Table
230 published by the PEI Foundation.
231 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
232 @param[in] Procedure A pointer to the function to be run on enabled APs of
234 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
235 total number of logical processors minus 1. The total
236 number of logical processors can be retrieved by
237 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
238 @param[in] TimeoutInMicroseconds
239 Indicates the time limit in microseconds for APs to
240 return from Procedure, for blocking mode only. Zero
241 means infinity. If the timeout expires before all APs
242 return from Procedure, then Procedure on the failed APs
243 is terminated. All enabled APs are available for next
244 function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
245 or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
246 timeout expires in blocking mode, BSP returns
248 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
250 @retval EFI_SUCCESS In blocking mode, specified AP finished before the
252 @retval EFI_DEVICE_ERROR The calling processor is an AP.
253 @retval EFI_TIMEOUT In blocking mode, the timeout expired before the
254 specified AP has finished.
255 @retval EFI_NOT_FOUND The processor with the handle specified by
256 ProcessorNumber does not exist.
257 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
258 @retval EFI_INVALID_PARAMETER Procedure is NULL.
263 IN CONST EFI_PEI_SERVICES
**PeiServices
,
264 IN EFI_PEI_MP_SERVICES_PPI
*This
,
265 IN EFI_AP_PROCEDURE Procedure
,
266 IN UINTN ProcessorNumber
,
267 IN UINTN TimeoutInMicroseconds
,
268 IN VOID
*ProcedureArgument OPTIONAL
271 return MpInitLibStartupThisAP (
275 TimeoutInMicroseconds
,
282 This service switches the requested AP to be the BSP from that point onward.
283 This service changes the BSP for all purposes. This call can only be performed
286 This service switches the requested AP to be the BSP from that point onward.
287 This service changes the BSP for all purposes. The new BSP can take over the
288 execution of the old BSP and continue seamlessly from where the old one left
291 If the BSP cannot be switched prior to the return from this service, then
292 EFI_UNSUPPORTED must be returned.
294 @param[in] PeiServices An indirect pointer to the PEI Services Table
295 published by the PEI Foundation.
296 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
297 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
298 total number of logical processors minus 1. The total
299 number of logical processors can be retrieved by
300 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
301 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled
302 AP. Otherwise, it will be disabled.
304 @retval EFI_SUCCESS BSP successfully switched.
305 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
307 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
308 @retval EFI_DEVICE_ERROR The calling processor is an AP.
309 @retval EFI_NOT_FOUND The processor with the handle specified by
310 ProcessorNumber does not exist.
311 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled
313 @retval EFI_NOT_READY The specified AP is busy.
318 IN CONST EFI_PEI_SERVICES
**PeiServices
,
319 IN EFI_PEI_MP_SERVICES_PPI
*This
,
320 IN UINTN ProcessorNumber
,
321 IN BOOLEAN EnableOldBSP
324 return MpInitLibSwitchBSP (ProcessorNumber
, EnableOldBSP
);
328 This service lets the caller enable or disable an AP from this point onward.
329 This service may only be called from the BSP.
331 This service allows the caller enable or disable an AP from this point onward.
332 The caller can optionally specify the health status of the AP by Health. If
333 an AP is being disabled, then the state of the disabled AP is implementation
334 dependent. If an AP is enabled, then the implementation must guarantee that a
335 complete initialization sequence is performed on the AP, so the AP is in a state
336 that is compatible with an MP operating system.
338 If the enable or disable AP operation cannot be completed prior to the return
339 from this service, then EFI_UNSUPPORTED must be returned.
341 @param[in] PeiServices An indirect pointer to the PEI Services Table
342 published by the PEI Foundation.
343 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
344 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
345 total number of logical processors minus 1. The total
346 number of logical processors can be retrieved by
347 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
348 @param[in] EnableAP Specifies the new state for the processor for enabled,
350 @param[in] HealthFlag If not NULL, a pointer to a value that specifies the
351 new health status of the AP. This flag corresponds to
352 StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo().
353 Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other
354 bits are ignored. If it is NULL, this parameter is
357 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
358 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed prior
359 to this service returning.
360 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
361 @retval EFI_DEVICE_ERROR The calling processor is an AP.
362 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
364 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
369 IN CONST EFI_PEI_SERVICES
**PeiServices
,
370 IN EFI_PEI_MP_SERVICES_PPI
*This
,
371 IN UINTN ProcessorNumber
,
373 IN UINT32
*HealthFlag OPTIONAL
376 return MpInitLibEnableDisableAP (ProcessorNumber
, EnableAP
, HealthFlag
);
380 This return the handle number for the calling processor. This service may be
381 called from the BSP and APs.
383 This service returns the processor handle number for the calling processor.
384 The returned value is in the range from 0 to the total number of logical
385 processors minus 1. The total number of logical processors can be retrieved
386 with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be
387 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
388 is returned. Otherwise, the current processors handle number is returned in
389 ProcessorNumber, and EFI_SUCCESS is returned.
391 @param[in] PeiServices An indirect pointer to the PEI Services Table
392 published by the PEI Foundation.
393 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
394 @param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the
395 total number of logical processors minus 1. The total
396 number of logical processors can be retrieved by
397 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
399 @retval EFI_SUCCESS The current processor handle number was returned in
401 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
406 IN CONST EFI_PEI_SERVICES
**PeiServices
,
407 IN EFI_PEI_MP_SERVICES_PPI
*This
,
408 OUT UINTN
*ProcessorNumber
411 return MpInitLibWhoAmI (ProcessorNumber
);
415 // Structure for InitializeSeparateExceptionStacks
421 } EXCEPTION_STACK_SWITCH_CONTEXT
;
424 Initializes CPU exceptions handlers for the sake of stack switch requirement.
426 This function is a wrapper of InitializeSeparateExceptionStacks. It's mainly
427 for the sake of AP's init because of EFI_AP_PROCEDURE API requirement.
429 @param[in,out] Buffer The pointer to private data buffer.
434 InitializeExceptionStackSwitchHandlers (
438 EXCEPTION_STACK_SWITCH_CONTEXT
*SwitchStackData
;
441 MpInitLibWhoAmI (&Index
);
442 SwitchStackData
= (EXCEPTION_STACK_SWITCH_CONTEXT
*)Buffer
;
445 // This function may be called twice for each Cpu. Only run InitializeSeparateExceptionStacks
446 // if this is the first call or the first call failed because of size too small.
448 if ((SwitchStackData
[Index
].Status
== EFI_NOT_STARTED
) || (SwitchStackData
[Index
].Status
== EFI_BUFFER_TOO_SMALL
)) {
449 SwitchStackData
[Index
].Status
= InitializeSeparateExceptionStacks (SwitchStackData
[Index
].Buffer
, &SwitchStackData
[Index
].BufferSize
);
454 Initializes MP exceptions handlers for the sake of stack switch requirement.
456 This function will allocate required resources required to setup stack switch
457 and pass them through SwitchStackData to each logic processor.
461 InitializeMpExceptionStackSwitchHandlers (
466 UINTN NumberOfProcessors
;
467 EXCEPTION_STACK_SWITCH_CONTEXT
*SwitchStackData
;
472 if (!PcdGetBool (PcdCpuStackGuard
)) {
476 MpInitLibGetNumberOfProcessors (&NumberOfProcessors
, NULL
);
477 SwitchStackData
= AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors
* sizeof (EXCEPTION_STACK_SWITCH_CONTEXT
)));
478 ASSERT (SwitchStackData
!= NULL
);
479 ZeroMem (SwitchStackData
, NumberOfProcessors
* sizeof (EXCEPTION_STACK_SWITCH_CONTEXT
));
480 for (Index
= 0; Index
< NumberOfProcessors
; ++Index
) {
482 // Because the procedure may runs multiple times, use the status EFI_NOT_STARTED
483 // to indicate the procedure haven't been run yet.
485 SwitchStackData
[Index
].Status
= EFI_NOT_STARTED
;
488 Status
= MpInitLibStartupAllCPUs (
489 InitializeExceptionStackSwitchHandlers
,
493 ASSERT_EFI_ERROR (Status
);
496 for (Index
= 0; Index
< NumberOfProcessors
; ++Index
) {
497 if (SwitchStackData
[Index
].Status
== EFI_BUFFER_TOO_SMALL
) {
498 ASSERT (SwitchStackData
[Index
].BufferSize
!= 0);
499 BufferSize
+= SwitchStackData
[Index
].BufferSize
;
501 ASSERT (SwitchStackData
[Index
].Status
== EFI_SUCCESS
);
502 ASSERT (SwitchStackData
[Index
].BufferSize
== 0);
506 if (BufferSize
!= 0) {
507 Buffer
= AllocatePages (EFI_SIZE_TO_PAGES (BufferSize
));
508 ASSERT (Buffer
!= NULL
);
510 for (Index
= 0; Index
< NumberOfProcessors
; ++Index
) {
511 if (SwitchStackData
[Index
].Status
== EFI_BUFFER_TOO_SMALL
) {
512 SwitchStackData
[Index
].Buffer
= (VOID
*)(&Buffer
[BufferSize
]);
513 BufferSize
+= SwitchStackData
[Index
].BufferSize
;
516 "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlers: 0x%lX with size 0x%lX\n",
517 (UINT64
)(UINTN
)Index
,
518 (UINT64
)(UINTN
)SwitchStackData
[Index
].Buffer
,
519 (UINT64
)(UINTN
)SwitchStackData
[Index
].BufferSize
524 Status
= MpInitLibStartupAllCPUs (
525 InitializeExceptionStackSwitchHandlers
,
529 ASSERT_EFI_ERROR (Status
);
530 for (Index
= 0; Index
< NumberOfProcessors
; ++Index
) {
531 ASSERT (SwitchStackData
[Index
].Status
== EFI_SUCCESS
);
535 FreePages (SwitchStackData
, EFI_SIZE_TO_PAGES (NumberOfProcessors
* sizeof (EXCEPTION_STACK_SWITCH_CONTEXT
)));
539 Initializes MP and exceptions handlers.
541 @param PeiServices The pointer to the PEI Services Table.
543 @retval EFI_SUCCESS MP was successfully initialized.
544 @retval others Error occurred in MP initialization.
548 InitializeCpuMpWorker (
549 IN CONST EFI_PEI_SERVICES
**PeiServices
553 EFI_VECTOR_HANDOFF_INFO
*VectorInfo
;
554 EFI_PEI_VECTOR_HANDOFF_INFO_PPI
*VectorHandoffInfoPpi
;
557 // Get Vector Hand-off Info PPI
560 Status
= PeiServicesLocatePpi (
561 &gEfiVectorHandoffInfoPpiGuid
,
564 (VOID
**)&VectorHandoffInfoPpi
566 if (Status
== EFI_SUCCESS
) {
567 VectorInfo
= VectorHandoffInfoPpi
->Info
;
571 // Initialize default handlers
573 Status
= InitializeCpuExceptionHandlers (VectorInfo
);
574 if (EFI_ERROR (Status
)) {
578 Status
= MpInitLibInitialize ();
579 if (EFI_ERROR (Status
)) {
584 // Special initialization for the sake of Stack Guard
586 InitializeMpExceptionStackSwitchHandlers ();
589 // Update and publish CPU BIST information
591 CollectBistDataFromPpi (PeiServices
);
594 // Install CPU MP PPI
596 Status
= PeiServicesInstallPpi (mPeiCpuMpPpiList
);
597 ASSERT_EFI_ERROR (Status
);
603 The Entry point of the MP CPU PEIM.
605 This function will wakeup APs and collect CPU AP count and install the
608 @param FileHandle Handle of the file being invoked.
609 @param PeiServices Describes the list of possible PEI Services.
611 @retval EFI_SUCCESS MpServicePpi is installed successfully.
617 IN EFI_PEI_FILE_HANDLE FileHandle
,
618 IN CONST EFI_PEI_SERVICES
**PeiServices
624 // For the sake of special initialization needing to be done right after
627 Status
= PeiServicesNotifyPpi (&mPostMemNotifyList
[0]);
628 ASSERT_EFI_ERROR (Status
);