2 Implementation of Multiple Processor PPI services.
4 Copyright (c) 2015, 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.
15 #include "PeiMpServices.h"
18 // CPU MP PPI to be installed
20 EFI_PEI_MP_SERVICES_PPI mMpServicesPpi
= {
21 PeiGetNumberOfProcessors
,
30 EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc
= {
31 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
32 &gEfiPeiMpServicesPpiGuid
,
37 Get CPU Package/Core/Thread location information.
39 @param InitialApicId CPU APIC ID
40 @param Location Pointer to CPU location information
43 ExtractProcessorLocation (
44 IN UINT32 InitialApicId
,
45 OUT EFI_CPU_PHYSICAL_LOCATION
*Location
48 BOOLEAN TopologyLeafSupported
;
58 UINT32 MaxLogicProcessorsPerPackage
;
59 UINT32 MaxCoresPerPackage
;
62 // Check if the processor is capable of supporting more than one logical processor.
64 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &RegEdx
);
65 if ((RegEdx
& BIT28
) == 0) {
68 Location
->Package
= 0;
76 // Assume three-level mapping of APIC ID: Package:Core:SMT.
79 TopologyLeafSupported
= FALSE
;
81 // Get the max index of basic CPUID
83 AsmCpuid (CPUID_SIGNATURE
, &MaxCpuIdIndex
, NULL
, NULL
, NULL
);
86 // If the extended topology enumeration leaf is available, it
87 // is the preferred mechanism for enumerating topology.
89 if (MaxCpuIdIndex
>= CPUID_EXTENDED_TOPOLOGY
) {
90 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY
, 0, &RegEax
, &RegEbx
, &RegEcx
, NULL
);
92 // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
93 // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
94 // supported on that processor.
97 TopologyLeafSupported
= TRUE
;
100 // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
101 // the SMT sub-field of x2APIC ID.
103 LevelType
= (RegEcx
>> 8) & 0xff;
104 ASSERT (LevelType
== CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT
);
105 ThreadBits
= RegEax
& 0x1f;
108 // Software must not assume any "level type" encoding
109 // value to be related to any sub-leaf index, except sub-leaf 0.
113 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY
, SubIndex
, &RegEax
, NULL
, &RegEcx
, NULL
);
114 LevelType
= (RegEcx
>> 8) & 0xff;
115 if (LevelType
== CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE
) {
116 CoreBits
= (RegEax
& 0x1f) - ThreadBits
;
120 } while (LevelType
!= CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID
);
124 if (!TopologyLeafSupported
) {
125 AsmCpuid (CPUID_VERSION_INFO
, NULL
, &RegEbx
, NULL
, NULL
);
126 MaxLogicProcessorsPerPackage
= (RegEbx
>> 16) & 0xff;
127 if (MaxCpuIdIndex
>= CPUID_CACHE_PARAMS
) {
128 AsmCpuidEx (CPUID_CACHE_PARAMS
, 0, &RegEax
, NULL
, NULL
, NULL
);
129 MaxCoresPerPackage
= (RegEax
>> 26) + 1;
132 // Must be a single-core processor.
134 MaxCoresPerPackage
= 1;
137 ThreadBits
= (UINTN
) (HighBitSet32 (MaxLogicProcessorsPerPackage
/ MaxCoresPerPackage
- 1) + 1);
138 CoreBits
= (UINTN
) (HighBitSet32 (MaxCoresPerPackage
- 1) + 1);
141 Location
->Thread
= InitialApicId
& ~((-1) << ThreadBits
);
142 Location
->Core
= (InitialApicId
>> ThreadBits
) & ~((-1) << CoreBits
);
143 Location
->Package
= (InitialApicId
>> (ThreadBits
+ CoreBits
));
147 Find the current Processor number by APIC ID.
149 @param PeiCpuMpData Pointer to PEI CPU MP Data
150 @param ProcessorNumber Return the pocessor number found
152 @retval EFI_SUCCESS ProcessorNumber is found and returned.
153 @retval EFI_NOT_FOUND ProcessorNumber is not found.
157 IN PEI_CPU_MP_DATA
*PeiCpuMpData
,
158 OUT UINTN
*ProcessorNumber
161 UINTN TotalProcessorNumber
;
164 TotalProcessorNumber
= PeiCpuMpData
->CpuCount
;
165 for (Index
= 0; Index
< TotalProcessorNumber
; Index
++) {
166 if (PeiCpuMpData
->CpuData
[Index
].ApicId
== GetInitialApicId ()) {
167 *ProcessorNumber
= Index
;
171 return EFI_NOT_FOUND
;
175 Worker function for SwitchBSP().
177 Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.
179 @param Buffer Pointer to CPU MP Data
187 PEI_CPU_MP_DATA
*DataInHob
;
189 DataInHob
= (PEI_CPU_MP_DATA
*) Buffer
;
190 AsmExchangeRole (&DataInHob
->APInfo
, &DataInHob
->BSPInfo
);
194 This service retrieves the number of logical processor in the platform
195 and the number of those logical processors that are enabled on this boot.
196 This service may only be called from the BSP.
198 This function is used to retrieve the following information:
199 - The number of logical processors that are present in the system.
200 - The number of enabled logical processors in the system at the instant
203 Because MP Service Ppi provides services to enable and disable processors
204 dynamically, the number of enabled logical processors may vary during the
205 course of a boot session.
207 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
208 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
209 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
210 is returned in NumberOfProcessors, the number of currently enabled processor
211 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
213 @param[in] PeiServices An indirect pointer to the PEI Services Table
214 published by the PEI Foundation.
215 @param[in] This Pointer to this instance of the PPI.
216 @param[out] NumberOfProcessors Pointer to the total number of logical processors in
217 the system, including the BSP and disabled APs.
218 @param[out] NumberOfEnabledProcessors
219 Number of processors in the system that are enabled.
221 @retval EFI_SUCCESS The number of logical processors and enabled
222 logical processors was retrieved.
223 @retval EFI_DEVICE_ERROR The calling processor is an AP.
224 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
225 NumberOfEnabledProcessors is NULL.
229 PeiGetNumberOfProcessors (
230 IN CONST EFI_PEI_SERVICES
**PeiServices
,
231 IN EFI_PEI_MP_SERVICES_PPI
*This
,
232 OUT UINTN
*NumberOfProcessors
,
233 OUT UINTN
*NumberOfEnabledProcessors
236 PEI_CPU_MP_DATA
*PeiCpuMpData
;
238 UINTN ProcessorNumber
;
239 UINTN EnabledProcessorNumber
;
242 PeiCpuMpData
= GetMpHobData ();
243 if (PeiCpuMpData
== NULL
) {
244 return EFI_NOT_FOUND
;
247 if ((NumberOfProcessors
== NULL
) || (NumberOfEnabledProcessors
== NULL
)) {
248 return EFI_INVALID_PARAMETER
;
252 // Check whether caller processor is BSP
254 PeiWhoAmI (PeiServices
, This
, &CallerNumber
);
255 if (CallerNumber
!= PeiCpuMpData
->BspNumber
) {
256 return EFI_DEVICE_ERROR
;
259 ProcessorNumber
= PeiCpuMpData
->CpuCount
;
260 EnabledProcessorNumber
= 0;
261 for (Index
= 0; Index
< ProcessorNumber
; Index
++) {
262 if (PeiCpuMpData
->CpuData
[Index
].State
!= CpuStateDisabled
) {
263 EnabledProcessorNumber
++;
267 *NumberOfProcessors
= ProcessorNumber
;
268 *NumberOfEnabledProcessors
= EnabledProcessorNumber
;
274 Gets detailed MP-related information on the requested processor at the
275 instant this call is made. This service may only be called from the BSP.
277 This service retrieves detailed MP-related information about any processor
278 on the platform. Note the following:
279 - The processor information may change during the course of a boot session.
280 - The information presented here is entirely MP related.
282 Information regarding the number of caches and their sizes, frequency of operation,
283 slot numbers is all considered platform-related information and is not provided
286 @param[in] PeiServices An indirect pointer to the PEI Services Table
287 published by the PEI Foundation.
288 @param[in] This Pointer to this instance of the PPI.
289 @param[in] ProcessorNumber Pointer to the total number of logical processors in
290 the system, including the BSP and disabled APs.
291 @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
293 @retval EFI_SUCCESS Processor information was returned.
294 @retval EFI_DEVICE_ERROR The calling processor is an AP.
295 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
296 @retval EFI_NOT_FOUND The processor with the handle specified by
297 ProcessorNumber does not exist in the platform.
301 PeiGetProcessorInfo (
302 IN CONST EFI_PEI_SERVICES
**PeiServices
,
303 IN EFI_PEI_MP_SERVICES_PPI
*This
,
304 IN UINTN ProcessorNumber
,
305 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
308 PEI_CPU_MP_DATA
*PeiCpuMpData
;
311 PeiCpuMpData
= GetMpHobData ();
312 if (PeiCpuMpData
== NULL
) {
313 return EFI_NOT_FOUND
;
317 // Check whether caller processor is BSP
319 PeiWhoAmI (PeiServices
, This
, &CallerNumber
);
320 if (CallerNumber
!= PeiCpuMpData
->BspNumber
) {
321 return EFI_DEVICE_ERROR
;
324 if (ProcessorInfoBuffer
== NULL
) {
325 return EFI_INVALID_PARAMETER
;
328 if (ProcessorNumber
>= PeiCpuMpData
->CpuCount
) {
329 return EFI_NOT_FOUND
;
332 ProcessorInfoBuffer
->ProcessorId
= (UINT64
) PeiCpuMpData
->CpuData
[ProcessorNumber
].ApicId
;
333 ProcessorInfoBuffer
->StatusFlag
= 0;
334 if (PeiCpuMpData
->CpuData
[ProcessorNumber
].ApicId
== GetInitialApicId()) {
335 ProcessorInfoBuffer
->StatusFlag
|= PROCESSOR_AS_BSP_BIT
;
337 if (PeiCpuMpData
->CpuData
[ProcessorNumber
].Health
.Uint32
== 0) {
338 ProcessorInfoBuffer
->StatusFlag
|= PROCESSOR_HEALTH_STATUS_BIT
;
340 if (PeiCpuMpData
->CpuData
[ProcessorNumber
].State
== CpuStateDisabled
) {
341 ProcessorInfoBuffer
->StatusFlag
&= ~PROCESSOR_ENABLED_BIT
;
343 ProcessorInfoBuffer
->StatusFlag
|= PROCESSOR_ENABLED_BIT
;
347 // Get processor location information
349 ExtractProcessorLocation (PeiCpuMpData
->CpuData
[ProcessorNumber
].ApicId
, &ProcessorInfoBuffer
->Location
);
355 This service executes a caller provided function on all enabled APs. APs can
356 run either simultaneously or one at a time in sequence. This service supports
357 both blocking requests only. This service may only
358 be called from the BSP.
360 This function is used to dispatch all the enabled APs to the function specified
361 by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
362 immediately and Procedure is not started on any AP.
364 If SingleThread is TRUE, all the enabled APs execute the function specified by
365 Procedure one by one, in ascending order of processor handle number. Otherwise,
366 all the enabled APs execute the function specified by Procedure simultaneously.
368 If the timeout specified by TimeoutInMicroSeconds expires before all APs return
369 from Procedure, then Procedure on the failed APs is terminated. All enabled APs
370 are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
371 and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
372 content points to the list of processor handle numbers in which Procedure was
375 Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
376 to make sure that the nature of the code that is executed on the BSP and the
377 dispatched APs is well controlled. The MP Services Ppi does not guarantee
378 that the Procedure function is MP-safe. Hence, the tasks that can be run in
379 parallel are limited to certain independent tasks and well-controlled exclusive
380 code. PEI services and Ppis may not be called by APs unless otherwise
383 In blocking execution mode, BSP waits until all APs finish or
384 TimeoutInMicroSeconds expires.
386 @param[in] PeiServices An indirect pointer to the PEI Services Table
387 published by the PEI Foundation.
388 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
389 @param[in] Procedure A pointer to the function to be run on enabled APs of
391 @param[in] SingleThread If TRUE, then all the enabled APs execute the function
392 specified by Procedure one by one, in ascending order
393 of processor handle number. If FALSE, then all the
394 enabled APs execute the function specified by Procedure
396 @param[in] TimeoutInMicroSeconds
397 Indicates the time limit in microseconds for APs to
398 return from Procedure, for blocking mode only. Zero
399 means infinity. If the timeout expires before all APs
400 return from Procedure, then Procedure on the failed APs
401 is terminated. All enabled APs are available for next
402 function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
403 or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
404 timeout expires in blocking mode, BSP returns
406 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
408 @retval EFI_SUCCESS In blocking mode, all APs have finished before the
410 @retval EFI_DEVICE_ERROR Caller processor is AP.
411 @retval EFI_NOT_STARTED No enabled APs exist in the system.
412 @retval EFI_NOT_READY Any enabled APs are busy.
413 @retval EFI_TIMEOUT In blocking mode, the timeout expired before all
414 enabled APs have finished.
415 @retval EFI_INVALID_PARAMETER Procedure is NULL.
420 IN CONST EFI_PEI_SERVICES
**PeiServices
,
421 IN EFI_PEI_MP_SERVICES_PPI
*This
,
422 IN EFI_AP_PROCEDURE Procedure
,
423 IN BOOLEAN SingleThread
,
424 IN UINTN TimeoutInMicroSeconds
,
425 IN VOID
*ProcedureArgument OPTIONAL
428 PEI_CPU_MP_DATA
*PeiCpuMpData
;
429 UINTN ProcessorNumber
;
432 BOOLEAN HasEnabledAp
;
433 BOOLEAN HasEnabledIdleAp
;
434 volatile UINT32
*FinishedCount
;
436 UINTN WaitCountIndex
;
437 UINTN WaitCountNumber
;
439 PeiCpuMpData
= GetMpHobData ();
440 if (PeiCpuMpData
== NULL
) {
441 return EFI_NOT_FOUND
;
445 // Check whether caller processor is BSP
447 PeiWhoAmI (PeiServices
, This
, &CallerNumber
);
448 if (CallerNumber
!= PeiCpuMpData
->BspNumber
) {
449 return EFI_DEVICE_ERROR
;
452 ProcessorNumber
= PeiCpuMpData
->CpuCount
;
454 HasEnabledAp
= FALSE
;
455 HasEnabledIdleAp
= FALSE
;
456 for (Index
= 0; Index
< ProcessorNumber
; Index
++) {
457 if (Index
== CallerNumber
) {
463 if (PeiCpuMpData
->CpuData
[Index
].State
!= CpuStateDisabled
) {
465 if (PeiCpuMpData
->CpuData
[Index
].State
!= CpuStateBusy
) {
466 HasEnabledIdleAp
= TRUE
;
472 // If no enabled AP exists, return EFI_NOT_STARTED.
474 return EFI_NOT_STARTED
;
476 if (!HasEnabledIdleAp
) {
478 // If any enabled APs are busy, return EFI_NOT_READY.
480 return EFI_NOT_READY
;
483 WaitCountNumber
= TimeoutInMicroSeconds
/ CPU_CHECK_AP_INTERVAL
+ 1;
485 FinishedCount
= &PeiCpuMpData
->FinishedCount
;
487 WakeUpAP (PeiCpuMpData
, TRUE
, 0, Procedure
, ProcedureArgument
);
491 if (TimeoutInMicroSeconds
== 0) {
492 while (*FinishedCount
< ProcessorNumber
- 1) {
495 Status
= EFI_SUCCESS
;
497 Status
= EFI_TIMEOUT
;
498 for (WaitCountIndex
= 0; WaitCountIndex
< WaitCountNumber
; WaitCountIndex
++) {
499 MicroSecondDelay (CPU_CHECK_AP_INTERVAL
);
500 if (*FinishedCount
>= ProcessorNumber
- 1) {
501 Status
= EFI_SUCCESS
;
507 Status
= EFI_SUCCESS
;
508 for (Index
= 0; Index
< ProcessorNumber
; Index
++) {
509 if (Index
== CallerNumber
) {
512 WakeUpAP (PeiCpuMpData
, FALSE
, PeiCpuMpData
->CpuData
[Index
].ApicId
, Procedure
, ProcedureArgument
);
516 if (TimeoutInMicroSeconds
== 0) {
517 while (*FinishedCount
< 1) {
521 for (WaitCountIndex
= 0; WaitCountIndex
< WaitCountNumber
; WaitCountIndex
++) {
522 MicroSecondDelay (CPU_CHECK_AP_INTERVAL
);
523 if (*FinishedCount
>= 1) {
527 if (WaitCountIndex
== WaitCountNumber
) {
528 Status
= EFI_TIMEOUT
;
538 This service lets the caller get one enabled AP to execute a caller-provided
539 function. The caller can request the BSP to wait for the completion
540 of the AP. This service may only be called from the BSP.
542 This function is used to dispatch one enabled AP to the function specified by
543 Procedure passing in the argument specified by ProcedureArgument.
544 The execution is in blocking mode. The BSP waits until the AP finishes or
545 TimeoutInMicroSecondss expires.
547 If the timeout specified by TimeoutInMicroseconds expires before the AP returns
548 from Procedure, then execution of Procedure by the AP is terminated. The AP is
549 available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and
550 EFI_PEI_MP_SERVICES_PPI.StartupThisAP().
552 @param[in] PeiServices An indirect pointer to the PEI Services Table
553 published by the PEI Foundation.
554 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
555 @param[in] Procedure A pointer to the function to be run on enabled APs of
557 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
558 total number of logical processors minus 1. The total
559 number of logical processors can be retrieved by
560 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
561 @param[in] TimeoutInMicroseconds
562 Indicates the time limit in microseconds for APs to
563 return from Procedure, for blocking mode only. Zero
564 means infinity. If the timeout expires before all APs
565 return from Procedure, then Procedure on the failed APs
566 is terminated. All enabled APs are available for next
567 function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
568 or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
569 timeout expires in blocking mode, BSP returns
571 @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
573 @retval EFI_SUCCESS In blocking mode, specified AP finished before the
575 @retval EFI_DEVICE_ERROR The calling processor is an AP.
576 @retval EFI_TIMEOUT In blocking mode, the timeout expired before the
577 specified AP has finished.
578 @retval EFI_NOT_FOUND The processor with the handle specified by
579 ProcessorNumber does not exist.
580 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
581 @retval EFI_INVALID_PARAMETER Procedure is NULL.
586 IN CONST EFI_PEI_SERVICES
**PeiServices
,
587 IN EFI_PEI_MP_SERVICES_PPI
*This
,
588 IN EFI_AP_PROCEDURE Procedure
,
589 IN UINTN ProcessorNumber
,
590 IN UINTN TimeoutInMicroseconds
,
591 IN VOID
*ProcedureArgument OPTIONAL
594 PEI_CPU_MP_DATA
*PeiCpuMpData
;
596 volatile UINT32
*FinishedCount
;
598 UINTN WaitCountIndex
;
599 UINTN WaitCountNumber
;
601 PeiCpuMpData
= GetMpHobData ();
602 if (PeiCpuMpData
== NULL
) {
603 return EFI_NOT_FOUND
;
607 // Check whether caller processor is BSP
609 PeiWhoAmI (PeiServices
, This
, &CallerNumber
);
610 if (CallerNumber
!= PeiCpuMpData
->BspNumber
) {
611 return EFI_DEVICE_ERROR
;
614 if (ProcessorNumber
>= PeiCpuMpData
->CpuCount
) {
615 return EFI_NOT_FOUND
;
618 if (ProcessorNumber
== PeiCpuMpData
->BspNumber
|| Procedure
== NULL
) {
619 return EFI_INVALID_PARAMETER
;
623 // Check whether specified AP is disabled
625 if (PeiCpuMpData
->CpuData
[ProcessorNumber
].State
== CpuStateDisabled
) {
626 return EFI_INVALID_PARAMETER
;
629 WaitCountNumber
= TimeoutInMicroseconds
/ CPU_CHECK_AP_INTERVAL
+ 1;
631 FinishedCount
= &PeiCpuMpData
->FinishedCount
;
633 WakeUpAP (PeiCpuMpData
, FALSE
, PeiCpuMpData
->CpuData
[ProcessorNumber
].ApicId
, Procedure
, ProcedureArgument
);
638 if (TimeoutInMicroseconds
== 0) {
639 while (*FinishedCount
< 1) {
642 Status
= EFI_SUCCESS
;
644 Status
= EFI_TIMEOUT
;
645 for (WaitCountIndex
= 0; WaitCountIndex
< WaitCountNumber
; WaitCountIndex
++) {
646 MicroSecondDelay (CPU_CHECK_AP_INTERVAL
);
647 if (*FinishedCount
>= 1) {
648 Status
= EFI_SUCCESS
;
658 This service switches the requested AP to be the BSP from that point onward.
659 This service changes the BSP for all purposes. This call can only be performed
662 This service switches the requested AP to be the BSP from that point onward.
663 This service changes the BSP for all purposes. The new BSP can take over the
664 execution of the old BSP and continue seamlessly from where the old one left
667 If the BSP cannot be switched prior to the return from this service, then
668 EFI_UNSUPPORTED must be returned.
670 @param[in] PeiServices An indirect pointer to the PEI Services Table
671 published by the PEI Foundation.
672 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
673 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
674 total number of logical processors minus 1. The total
675 number of logical processors can be retrieved by
676 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
677 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled
678 AP. Otherwise, it will be disabled.
680 @retval EFI_SUCCESS BSP successfully switched.
681 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
683 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
684 @retval EFI_SUCCESS The calling processor is an AP.
685 @retval EFI_NOT_FOUND The processor with the handle specified by
686 ProcessorNumber does not exist.
687 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled
689 @retval EFI_NOT_READY The specified AP is busy.
694 IN CONST EFI_PEI_SERVICES
**PeiServices
,
695 IN EFI_PEI_MP_SERVICES_PPI
*This
,
696 IN UINTN ProcessorNumber
,
697 IN BOOLEAN EnableOldBSP
700 PEI_CPU_MP_DATA
*PeiCpuMpData
;
702 MSR_IA32_APIC_BASE ApicBaseMsr
;
704 PeiCpuMpData
= GetMpHobData ();
705 if (PeiCpuMpData
== NULL
) {
706 return EFI_NOT_FOUND
;
710 // Check whether caller processor is BSP
712 PeiWhoAmI (PeiServices
, This
, &CallerNumber
);
713 if (CallerNumber
!= PeiCpuMpData
->BspNumber
) {
717 if (ProcessorNumber
>= PeiCpuMpData
->CpuCount
) {
718 return EFI_NOT_FOUND
;
722 // Check whether specified AP is disabled
724 if (PeiCpuMpData
->CpuData
[ProcessorNumber
].State
== CpuStateDisabled
) {
725 return EFI_INVALID_PARAMETER
;
729 // Check whether ProcessorNumber specifies the current BSP
731 if (ProcessorNumber
== PeiCpuMpData
->BspNumber
) {
732 return EFI_INVALID_PARAMETER
;
736 // Check whether specified AP is busy
738 if (PeiCpuMpData
->CpuData
[ProcessorNumber
].State
== CpuStateBusy
) {
739 return EFI_NOT_READY
;
743 // Clear the BSP bit of MSR_IA32_APIC_BASE
745 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
746 ApicBaseMsr
.Bits
.Bsp
= 0;
747 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
749 PeiCpuMpData
->BSPInfo
.State
= CPU_SWITCH_STATE_IDLE
;
750 PeiCpuMpData
->APInfo
.State
= CPU_SWITCH_STATE_IDLE
;
753 // Need to wakeUp AP (future BSP).
755 WakeUpAP (PeiCpuMpData
, FALSE
, PeiCpuMpData
->CpuData
[ProcessorNumber
].ApicId
, FutureBSPProc
, PeiCpuMpData
);
757 AsmExchangeRole (&PeiCpuMpData
->BSPInfo
, &PeiCpuMpData
->APInfo
);
760 // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
762 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
763 ApicBaseMsr
.Bits
.Bsp
= 1;
764 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
770 This service lets the caller enable or disable an AP from this point onward.
771 This service may only be called from the BSP.
773 This service allows the caller enable or disable an AP from this point onward.
774 The caller can optionally specify the health status of the AP by Health. If
775 an AP is being disabled, then the state of the disabled AP is implementation
776 dependent. If an AP is enabled, then the implementation must guarantee that a
777 complete initialization sequence is performed on the AP, so the AP is in a state
778 that is compatible with an MP operating system.
780 If the enable or disable AP operation cannot be completed prior to the return
781 from this service, then EFI_UNSUPPORTED must be returned.
783 @param[in] PeiServices An indirect pointer to the PEI Services Table
784 published by the PEI Foundation.
785 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
786 @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
787 total number of logical processors minus 1. The total
788 number of logical processors can be retrieved by
789 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
790 @param[in] EnableAP Specifies the new state for the processor for enabled,
792 @param[in] HealthFlag If not NULL, a pointer to a value that specifies the
793 new health status of the AP. This flag corresponds to
794 StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo().
795 Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other
796 bits are ignored. If it is NULL, this parameter is
799 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
800 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed prior
801 to this service returning.
802 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
803 @retval EFI_DEVICE_ERROR The calling processor is an AP.
804 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
806 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
811 IN CONST EFI_PEI_SERVICES
**PeiServices
,
812 IN EFI_PEI_MP_SERVICES_PPI
*This
,
813 IN UINTN ProcessorNumber
,
815 IN UINT32
*HealthFlag OPTIONAL
818 PEI_CPU_MP_DATA
*PeiCpuMpData
;
821 PeiCpuMpData
= GetMpHobData ();
822 if (PeiCpuMpData
== NULL
) {
823 return EFI_NOT_FOUND
;
827 // Check whether caller processor is BSP
829 PeiWhoAmI (PeiServices
, This
, &CallerNumber
);
830 if (CallerNumber
!= PeiCpuMpData
->BspNumber
) {
831 return EFI_DEVICE_ERROR
;
834 if (ProcessorNumber
== PeiCpuMpData
->BspNumber
) {
835 return EFI_INVALID_PARAMETER
;
838 if (ProcessorNumber
>= PeiCpuMpData
->CpuCount
) {
839 return EFI_NOT_FOUND
;
843 PeiCpuMpData
->CpuData
[ProcessorNumber
].State
= CpuStateDisabled
;
845 PeiCpuMpData
->CpuData
[ProcessorNumber
].State
= CpuStateIdle
;
848 if (HealthFlag
!= NULL
) {
849 PeiCpuMpData
->CpuData
[ProcessorNumber
].CpuHealthy
=
850 (BOOLEAN
) ((*HealthFlag
& PROCESSOR_HEALTH_STATUS_BIT
) != 0);
856 This return the handle number for the calling processor. This service may be
857 called from the BSP and APs.
859 This service returns the processor handle number for the calling processor.
860 The returned value is in the range from 0 to the total number of logical
861 processors minus 1. The total number of logical processors can be retrieved
862 with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be
863 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
864 is returned. Otherwise, the current processors handle number is returned in
865 ProcessorNumber, and EFI_SUCCESS is returned.
867 @param[in] PeiServices An indirect pointer to the PEI Services Table
868 published by the PEI Foundation.
869 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
870 @param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the
871 total number of logical processors minus 1. The total
872 number of logical processors can be retrieved by
873 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
875 @retval EFI_SUCCESS The current processor handle number was returned in
877 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
882 IN CONST EFI_PEI_SERVICES
**PeiServices
,
883 IN EFI_PEI_MP_SERVICES_PPI
*This
,
884 OUT UINTN
*ProcessorNumber
887 PEI_CPU_MP_DATA
*PeiCpuMpData
;
889 PeiCpuMpData
= GetMpHobData ();
890 if (PeiCpuMpData
== NULL
) {
891 return EFI_NOT_FOUND
;
894 if (ProcessorNumber
== NULL
) {
895 return EFI_INVALID_PARAMETER
;
898 return GetProcessorNumber (PeiCpuMpData
, ProcessorNumber
);