]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / CpuMpPei.c
1 /** @file
2 CPU PEI Module installs CPU Multiple Processor PPI.
3
4 Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "CpuMpPei.h"
10
11 extern EDKII_PEI_MP_SERVICES2_PPI mMpServices2Ppi;
12
13 //
14 // CPU MP PPI to be installed
15 //
16 EFI_PEI_MP_SERVICES_PPI mMpServicesPpi = {
17 PeiGetNumberOfProcessors,
18 PeiGetProcessorInfo,
19 PeiStartupAllAPs,
20 PeiStartupThisAP,
21 PeiSwitchBSP,
22 PeiEnableDisableAP,
23 PeiWhoAmI,
24 };
25
26 EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiList[] = {
27 {
28 EFI_PEI_PPI_DESCRIPTOR_PPI,
29 &gEdkiiPeiMpServices2PpiGuid,
30 &mMpServices2Ppi
31 },
32 {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34 &gEfiPeiMpServicesPpiGuid,
35 &mMpServicesPpi
36 }
37 };
38
39 /**
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.
43
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
47 this call is made.
48
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.
52
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.
58
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.
66
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.
72 **/
73 EFI_STATUS
74 EFIAPI
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
80 )
81 {
82 if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
83 return EFI_INVALID_PARAMETER;
84 }
85
86 return MpInitLibGetNumberOfProcessors (
87 NumberOfProcessors,
88 NumberOfEnabledProcessors
89 );
90 }
91
92 /**
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.
95
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.
100
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
103 by this service.
104
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.
111
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.
117 **/
118 EFI_STATUS
119 EFIAPI
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
125 )
126 {
127 return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);
128 }
129
130 /**
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.
135
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.
139
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.
143
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
149 terminated.
150
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
157 specified.
158
159 In blocking execution mode, BSP waits until all APs finish or
160 TimeoutInMicroSeconds expires.
161
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
166 the system.
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
171 simultaneously.
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
181 EFI_TIMEOUT.
182 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
183
184 @retval EFI_SUCCESS In blocking mode, all APs have finished before the
185 timeout expired.
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.
192 **/
193 EFI_STATUS
194 EFIAPI
195 PeiStartupAllAPs (
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
202 )
203 {
204 return MpInitLibStartupAllAPs (
205 Procedure,
206 SingleThread,
207 NULL,
208 TimeoutInMicroSeconds,
209 ProcedureArgument,
210 NULL
211 );
212 }
213
214 /**
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.
218
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.
223
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().
228
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
233 the system.
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
247 EFI_TIMEOUT.
248 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
249
250 @retval EFI_SUCCESS In blocking mode, specified AP finished before the
251 timeout expires.
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.
259 **/
260 EFI_STATUS
261 EFIAPI
262 PeiStartupThisAP (
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
269 )
270 {
271 return MpInitLibStartupThisAP (
272 Procedure,
273 ProcessorNumber,
274 NULL,
275 TimeoutInMicroseconds,
276 ProcedureArgument,
277 NULL
278 );
279 }
280
281 /**
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
284 by the current BSP.
285
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
289 off.
290
291 If the BSP cannot be switched prior to the return from this service, then
292 EFI_UNSUPPORTED must be returned.
293
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.
303
304 @retval EFI_SUCCESS BSP successfully switched.
305 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
306 service returning.
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
312 AP.
313 @retval EFI_NOT_READY The specified AP is busy.
314 **/
315 EFI_STATUS
316 EFIAPI
317 PeiSwitchBSP (
318 IN CONST EFI_PEI_SERVICES **PeiServices,
319 IN EFI_PEI_MP_SERVICES_PPI *This,
320 IN UINTN ProcessorNumber,
321 IN BOOLEAN EnableOldBSP
322 )
323 {
324 return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);
325 }
326
327 /**
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.
330
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.
337
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.
340
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,
349 FALSE for disabled.
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
355 ignored.
356
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
363 does not exist.
364 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
365 **/
366 EFI_STATUS
367 EFIAPI
368 PeiEnableDisableAP (
369 IN CONST EFI_PEI_SERVICES **PeiServices,
370 IN EFI_PEI_MP_SERVICES_PPI *This,
371 IN UINTN ProcessorNumber,
372 IN BOOLEAN EnableAP,
373 IN UINT32 *HealthFlag OPTIONAL
374 )
375 {
376 return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);
377 }
378
379 /**
380 This return the handle number for the calling processor. This service may be
381 called from the BSP and APs.
382
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.
390
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().
398
399 @retval EFI_SUCCESS The current processor handle number was returned in
400 ProcessorNumber.
401 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
402 **/
403 EFI_STATUS
404 EFIAPI
405 PeiWhoAmI (
406 IN CONST EFI_PEI_SERVICES **PeiServices,
407 IN EFI_PEI_MP_SERVICES_PPI *This,
408 OUT UINTN *ProcessorNumber
409 )
410 {
411 return MpInitLibWhoAmI (ProcessorNumber);
412 }
413
414 //
415 // Structure for InitializeSeparateExceptionStacks
416 //
417 typedef struct {
418 VOID *Buffer;
419 UINTN BufferSize;
420 EFI_STATUS Status;
421 } EXCEPTION_STACK_SWITCH_CONTEXT;
422
423 /**
424 Initializes CPU exceptions handlers for the sake of stack switch requirement.
425
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.
428
429 @param[in,out] Buffer The pointer to private data buffer.
430
431 **/
432 VOID
433 EFIAPI
434 InitializeExceptionStackSwitchHandlers (
435 IN OUT VOID *Buffer
436 )
437 {
438 EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
439 UINTN Index;
440
441 MpInitLibWhoAmI (&Index);
442 SwitchStackData = (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer;
443
444 //
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.
447 //
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);
450 }
451 }
452
453 /**
454 Initializes MP exceptions handlers for the sake of stack switch requirement.
455
456 This function will allocate required resources required to setup stack switch
457 and pass them through SwitchStackData to each logic processor.
458
459 **/
460 VOID
461 InitializeMpExceptionStackSwitchHandlers (
462 VOID
463 )
464 {
465 UINTN Index;
466 UINTN NumberOfProcessors;
467 EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
468 UINTN BufferSize;
469 EFI_STATUS Status;
470 UINT8 *Buffer;
471
472 if (!PcdGetBool (PcdCpuStackGuard)) {
473 return;
474 }
475
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) {
481 //
482 // Because the procedure may runs multiple times, use the status EFI_NOT_STARTED
483 // to indicate the procedure haven't been run yet.
484 //
485 SwitchStackData[Index].Status = EFI_NOT_STARTED;
486 }
487
488 Status = MpInitLibStartupAllCPUs (
489 InitializeExceptionStackSwitchHandlers,
490 0,
491 SwitchStackData
492 );
493 ASSERT_EFI_ERROR (Status);
494
495 BufferSize = 0;
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;
500 } else {
501 ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);
502 ASSERT (SwitchStackData[Index].BufferSize == 0);
503 }
504 }
505
506 if (BufferSize != 0) {
507 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
508 ASSERT (Buffer != NULL);
509 BufferSize = 0;
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;
514 DEBUG ((
515 DEBUG_INFO,
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
520 ));
521 }
522 }
523
524 Status = MpInitLibStartupAllCPUs (
525 InitializeExceptionStackSwitchHandlers,
526 0,
527 SwitchStackData
528 );
529 ASSERT_EFI_ERROR (Status);
530 for (Index = 0; Index < NumberOfProcessors; ++Index) {
531 ASSERT (SwitchStackData[Index].Status == EFI_SUCCESS);
532 }
533 }
534
535 FreePages (SwitchStackData, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT)));
536 }
537
538 /**
539 Initializes MP and exceptions handlers.
540
541 @param PeiServices The pointer to the PEI Services Table.
542
543 @retval EFI_SUCCESS MP was successfully initialized.
544 @retval others Error occurred in MP initialization.
545
546 **/
547 EFI_STATUS
548 InitializeCpuMpWorker (
549 IN CONST EFI_PEI_SERVICES **PeiServices
550 )
551 {
552 EFI_STATUS Status;
553 EFI_VECTOR_HANDOFF_INFO *VectorInfo;
554 EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
555
556 //
557 // Get Vector Hand-off Info PPI
558 //
559 VectorInfo = NULL;
560 Status = PeiServicesLocatePpi (
561 &gEfiVectorHandoffInfoPpiGuid,
562 0,
563 NULL,
564 (VOID **)&VectorHandoffInfoPpi
565 );
566 if (Status == EFI_SUCCESS) {
567 VectorInfo = VectorHandoffInfoPpi->Info;
568 }
569
570 //
571 // Initialize default handlers
572 //
573 Status = InitializeCpuExceptionHandlers (VectorInfo);
574 if (EFI_ERROR (Status)) {
575 return Status;
576 }
577
578 Status = MpInitLibInitialize ();
579 if (EFI_ERROR (Status)) {
580 return Status;
581 }
582
583 //
584 // Special initialization for the sake of Stack Guard
585 //
586 InitializeMpExceptionStackSwitchHandlers ();
587
588 //
589 // Update and publish CPU BIST information
590 //
591 CollectBistDataFromPpi (PeiServices);
592
593 //
594 // Install CPU MP PPI
595 //
596 Status = PeiServicesInstallPpi (mPeiCpuMpPpiList);
597 ASSERT_EFI_ERROR (Status);
598
599 return Status;
600 }
601
602 /**
603 The Entry point of the MP CPU PEIM.
604
605 This function will wakeup APs and collect CPU AP count and install the
606 Mp Service Ppi.
607
608 @param FileHandle Handle of the file being invoked.
609 @param PeiServices Describes the list of possible PEI Services.
610
611 @retval EFI_SUCCESS MpServicePpi is installed successfully.
612
613 **/
614 EFI_STATUS
615 EFIAPI
616 CpuMpPeimInit (
617 IN EFI_PEI_FILE_HANDLE FileHandle,
618 IN CONST EFI_PEI_SERVICES **PeiServices
619 )
620 {
621 EFI_STATUS Status;
622
623 //
624 // For the sake of special initialization needing to be done right after
625 // memory discovery.
626 //
627 Status = PeiServicesNotifyPpi (&mPostMemNotifyList[0]);
628 ASSERT_EFI_ERROR (Status);
629
630 return Status;
631 }