2 CPU MP Initialize Library common functions.
4 Copyright (c) 2016, 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.
17 EFI_GUID mCpuInitMpLibHobGuid
= CPU_INIT_MP_LIB_HOB_GUID
;
20 The function will check if BSP Execute Disable is enabled.
21 DxeIpl may have enabled Execute Disable for BSP,
22 APs need to get the status and sync up the settings.
24 @retval TRUE BSP Execute Disable is enabled.
25 @retval FALSE BSP Execute Disable is not enabled.
28 IsBspExecuteDisableEnabled (
33 CPUID_EXTENDED_CPU_SIG_EDX Edx
;
34 MSR_IA32_EFER_REGISTER EferMsr
;
38 AsmCpuid (CPUID_EXTENDED_FUNCTION
, &Eax
, NULL
, NULL
, NULL
);
39 if (Eax
>= CPUID_EXTENDED_CPU_SIG
) {
40 AsmCpuid (CPUID_EXTENDED_CPU_SIG
, NULL
, NULL
, NULL
, &Edx
.Uint32
);
43 // Bit 20: Execute Disable Bit available.
45 if (Edx
.Bits
.NX
!= 0) {
46 EferMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_EFER
);
49 // Bit 11: Execute Disable Bit enable.
51 if (EferMsr
.Bits
.NXE
!= 0) {
61 Get the Application Processors state.
63 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
69 IN CPU_AP_DATA
*CpuData
72 return CpuData
->State
;
76 Set the Application Processors state.
78 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
79 @param[in] State The AP status
83 IN CPU_AP_DATA
*CpuData
,
87 AcquireSpinLock (&CpuData
->ApLock
);
88 CpuData
->State
= State
;
89 ReleaseSpinLock (&CpuData
->ApLock
);
93 Save the volatile registers required to be restored following INIT IPI.
95 @param[out] VolatileRegisters Returns buffer saved the volatile resisters
98 SaveVolatileRegisters (
99 OUT CPU_VOLATILE_REGISTERS
*VolatileRegisters
102 CPUID_VERSION_INFO_EDX VersionInfoEdx
;
104 VolatileRegisters
->Cr0
= AsmReadCr0 ();
105 VolatileRegisters
->Cr3
= AsmReadCr3 ();
106 VolatileRegisters
->Cr4
= AsmReadCr4 ();
108 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &VersionInfoEdx
.Uint32
);
109 if (VersionInfoEdx
.Bits
.DE
!= 0) {
111 // If processor supports Debugging Extensions feature
112 // by CPUID.[EAX=01H]:EDX.BIT2
114 VolatileRegisters
->Dr0
= AsmReadDr0 ();
115 VolatileRegisters
->Dr1
= AsmReadDr1 ();
116 VolatileRegisters
->Dr2
= AsmReadDr2 ();
117 VolatileRegisters
->Dr3
= AsmReadDr3 ();
118 VolatileRegisters
->Dr6
= AsmReadDr6 ();
119 VolatileRegisters
->Dr7
= AsmReadDr7 ();
124 Restore the volatile registers following INIT IPI.
126 @param[in] VolatileRegisters Pointer to volatile resisters
127 @param[in] IsRestoreDr TRUE: Restore DRx if supported
128 FALSE: Do not restore DRx
131 RestoreVolatileRegisters (
132 IN CPU_VOLATILE_REGISTERS
*VolatileRegisters
,
133 IN BOOLEAN IsRestoreDr
136 CPUID_VERSION_INFO_EDX VersionInfoEdx
;
138 AsmWriteCr0 (VolatileRegisters
->Cr0
);
139 AsmWriteCr3 (VolatileRegisters
->Cr3
);
140 AsmWriteCr4 (VolatileRegisters
->Cr4
);
143 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &VersionInfoEdx
.Uint32
);
144 if (VersionInfoEdx
.Bits
.DE
!= 0) {
146 // If processor supports Debugging Extensions feature
147 // by CPUID.[EAX=01H]:EDX.BIT2
149 AsmWriteDr0 (VolatileRegisters
->Dr0
);
150 AsmWriteDr1 (VolatileRegisters
->Dr1
);
151 AsmWriteDr2 (VolatileRegisters
->Dr2
);
152 AsmWriteDr3 (VolatileRegisters
->Dr3
);
153 AsmWriteDr6 (VolatileRegisters
->Dr6
);
154 AsmWriteDr7 (VolatileRegisters
->Dr7
);
160 Detect whether Mwait-monitor feature is supported.
162 @retval TRUE Mwait-monitor feature is supported.
163 @retval FALSE Mwait-monitor feature is not supported.
170 CPUID_VERSION_INFO_ECX VersionInfoEcx
;
172 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, &VersionInfoEcx
.Uint32
, NULL
);
173 return (VersionInfoEcx
.Bits
.MONITOR
== 1) ? TRUE
: FALSE
;
179 @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.
181 @return The AP loop mode.
185 OUT UINT32
*MonitorFilterSize
189 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx
;
191 ASSERT (MonitorFilterSize
!= NULL
);
193 ApLoopMode
= PcdGet8 (PcdCpuApLoopMode
);
194 ASSERT (ApLoopMode
>= ApInHltLoop
&& ApLoopMode
<= ApInRunLoop
);
195 if (ApLoopMode
== ApInMwaitLoop
) {
196 if (!IsMwaitSupport ()) {
198 // If processor does not support MONITOR/MWAIT feature,
199 // force AP in Hlt-loop mode
201 ApLoopMode
= ApInHltLoop
;
205 if (ApLoopMode
!= ApInMwaitLoop
) {
206 *MonitorFilterSize
= sizeof (UINT32
);
209 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
210 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
212 AsmCpuid (CPUID_MONITOR_MWAIT
, NULL
, &MonitorMwaitEbx
.Uint32
, NULL
, NULL
);
213 *MonitorFilterSize
= MonitorMwaitEbx
.Bits
.LargestMonitorLineSize
;
220 Enable x2APIC mode on APs.
222 @param[in, out] Buffer Pointer to private data buffer.
230 SetApicMode (LOCAL_APIC_MODE_X2APIC
);
236 @param[in, out] Buffer Pointer to private data buffer.
244 CPU_MP_DATA
*CpuMpData
;
246 CpuMpData
= (CPU_MP_DATA
*) Buffer
;
248 // Sync BSP's MTRR table to AP
250 MtrrSetAllMtrrs (&CpuMpData
->MtrrTable
);
252 // Load microcode on AP
254 MicrocodeDetect (CpuMpData
);
258 Find the current Processor number by APIC ID.
260 @param[in] CpuMpData Pointer to PEI CPU MP Data
261 @param[in] ProcessorNumber Return the pocessor number found
263 @retval EFI_SUCCESS ProcessorNumber is found and returned.
264 @retval EFI_NOT_FOUND ProcessorNumber is not found.
268 IN CPU_MP_DATA
*CpuMpData
,
269 OUT UINTN
*ProcessorNumber
272 UINTN TotalProcessorNumber
;
275 TotalProcessorNumber
= CpuMpData
->CpuCount
;
276 for (Index
= 0; Index
< TotalProcessorNumber
; Index
++) {
277 if (CpuMpData
->CpuData
[Index
].ApicId
== GetApicId ()) {
278 *ProcessorNumber
= Index
;
282 return EFI_NOT_FOUND
;
286 This function will get CPU count in the system.
288 @param[in] CpuMpData Pointer to PEI CPU MP Data
290 @return CPU count detected
293 CollectProcessorCount (
294 IN CPU_MP_DATA
*CpuMpData
298 // Send 1st broadcast IPI to APs to wakeup APs
300 CpuMpData
->InitFlag
= ApInitConfig
;
301 CpuMpData
->X2ApicEnable
= FALSE
;
302 WakeUpAP (CpuMpData
, TRUE
, 0, NULL
, NULL
);
304 // Wait for AP task to complete and then exit.
306 MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds
));
307 CpuMpData
->InitFlag
= ApInitDone
;
308 ASSERT (CpuMpData
->CpuCount
<= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
));
310 // Wait for all APs finished the initialization
312 while (CpuMpData
->FinishedCount
< (CpuMpData
->CpuCount
- 1)) {
316 if (CpuMpData
->X2ApicEnable
) {
317 DEBUG ((DEBUG_INFO
, "Force x2APIC mode!\n"));
319 // Wakeup all APs to enable x2APIC mode
321 WakeUpAP (CpuMpData
, TRUE
, 0, ApFuncEnableX2Apic
, NULL
);
323 // Wait for all known APs finished
325 while (CpuMpData
->FinishedCount
< (CpuMpData
->CpuCount
- 1)) {
329 // Enable x2APIC on BSP
331 SetApicMode (LOCAL_APIC_MODE_X2APIC
);
333 DEBUG ((DEBUG_INFO
, "APIC MODE is %d\n", GetApicMode ()));
334 DEBUG ((DEBUG_INFO
, "MpInitLib: Find %d processors in system.\n", CpuMpData
->CpuCount
));
336 return CpuMpData
->CpuCount
;
340 Initialize CPU AP Data when AP is wakeup at the first time.
342 @param[in, out] CpuMpData Pointer to PEI CPU MP Data
343 @param[in] ProcessorNumber The handle number of processor
344 @param[in] BistData Processor BIST data
349 IN OUT CPU_MP_DATA
*CpuMpData
,
350 IN UINTN ProcessorNumber
,
354 CpuMpData
->CpuData
[ProcessorNumber
].Waiting
= FALSE
;
355 CpuMpData
->CpuData
[ProcessorNumber
].Health
= BistData
;
356 CpuMpData
->CpuData
[ProcessorNumber
].CpuHealthy
= (BistData
== 0) ? TRUE
: FALSE
;
357 CpuMpData
->CpuData
[ProcessorNumber
].ApicId
= GetApicId ();
358 CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
= GetInitialApicId ();
359 if (CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
>= 0xFF) {
361 // Set x2APIC mode if there are any logical processor reporting
362 // an Initial APIC ID of 255 or greater.
364 AcquireSpinLock(&CpuMpData
->MpLock
);
365 CpuMpData
->X2ApicEnable
= TRUE
;
366 ReleaseSpinLock(&CpuMpData
->MpLock
);
369 InitializeSpinLock(&CpuMpData
->CpuData
[ProcessorNumber
].ApLock
);
370 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateIdle
);
374 This function will be called from AP reset code if BSP uses WakeUpAP.
376 @param[in] ExchangeInfo Pointer to the MP exchange info buffer
377 @param[in] NumApsExecuting Number of current executing AP
382 IN MP_CPU_EXCHANGE_INFO
*ExchangeInfo
,
383 IN UINTN NumApsExecuting
386 CPU_MP_DATA
*CpuMpData
;
387 UINTN ProcessorNumber
;
388 EFI_AP_PROCEDURE Procedure
;
391 volatile UINT32
*ApStartupSignalBuffer
;
394 // AP finished assembly code and begin to execute C code
396 CpuMpData
= ExchangeInfo
->CpuMpData
;
398 ProgramVirtualWireMode ();
401 if (CpuMpData
->InitFlag
== ApInitConfig
) {
405 InterlockedIncrement ((UINT32
*) &CpuMpData
->CpuCount
);
406 ProcessorNumber
= NumApsExecuting
;
408 // This is first time AP wakeup, get BIST information from AP stack
410 BistData
= *(UINT32
*) (CpuMpData
->Buffer
+ ProcessorNumber
* CpuMpData
->CpuApStackSize
- sizeof (UINTN
));
412 // Do some AP initialize sync
414 ApInitializeSync (CpuMpData
);
416 // Sync BSP's Control registers to APs
418 RestoreVolatileRegisters (&CpuMpData
->CpuData
[0].VolatileRegisters
, FALSE
);
419 InitializeApData (CpuMpData
, ProcessorNumber
, BistData
);
420 ApStartupSignalBuffer
= CpuMpData
->CpuData
[ProcessorNumber
].StartupApSignal
;
423 // Execute AP function if AP is ready
425 GetProcessorNumber (CpuMpData
, &ProcessorNumber
);
427 // Clear AP start-up signal when AP waken up
429 ApStartupSignalBuffer
= CpuMpData
->CpuData
[ProcessorNumber
].StartupApSignal
;
430 InterlockedCompareExchange32 (
431 (UINT32
*) ApStartupSignalBuffer
,
435 if (CpuMpData
->ApLoopMode
== ApInHltLoop
) {
437 // Restore AP's volatile registers saved
439 RestoreVolatileRegisters (&CpuMpData
->CpuData
[ProcessorNumber
].VolatileRegisters
, TRUE
);
442 if (GetApState (&CpuMpData
->CpuData
[ProcessorNumber
]) == CpuStateReady
) {
443 Procedure
= (EFI_AP_PROCEDURE
)CpuMpData
->CpuData
[ProcessorNumber
].ApFunction
;
444 Parameter
= (VOID
*) CpuMpData
->CpuData
[ProcessorNumber
].ApFunctionArgument
;
445 if (Procedure
!= NULL
) {
446 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateBusy
);
448 // Invoke AP function here
450 Procedure (Parameter
);
452 // Re-get the CPU APICID and Initial APICID
454 CpuMpData
->CpuData
[ProcessorNumber
].ApicId
= GetApicId ();
455 CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
= GetInitialApicId ();
457 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateFinished
);
462 // AP finished executing C code
464 InterlockedIncrement ((UINT32
*) &CpuMpData
->FinishedCount
);
467 // Place AP is specified loop mode
469 if (CpuMpData
->ApLoopMode
== ApInHltLoop
) {
471 // Save AP volatile registers
473 SaveVolatileRegisters (&CpuMpData
->CpuData
[ProcessorNumber
].VolatileRegisters
);
475 // Place AP in HLT-loop
478 DisableInterrupts ();
484 DisableInterrupts ();
485 if (CpuMpData
->ApLoopMode
== ApInMwaitLoop
) {
487 // Place AP in MWAIT-loop
489 AsmMonitor ((UINTN
) ApStartupSignalBuffer
, 0, 0);
490 if (*ApStartupSignalBuffer
!= WAKEUP_AP_SIGNAL
) {
492 // Check AP start-up signal again.
493 // If AP start-up signal is not set, place AP into
494 // the specified C-state
496 AsmMwait (CpuMpData
->ApTargetCState
<< 4, 0);
498 } else if (CpuMpData
->ApLoopMode
== ApInRunLoop
) {
500 // Place AP in Run-loop
508 // If AP start-up signal is written, AP is waken up
509 // otherwise place AP in loop again
511 if (*ApStartupSignalBuffer
== WAKEUP_AP_SIGNAL
) {
519 Wait for AP wakeup and write AP start-up signal till AP is waken up.
521 @param[in] ApStartupSignalBuffer Pointer to AP wakeup signal
525 IN
volatile UINT32
*ApStartupSignalBuffer
529 // If AP is waken up, StartupApSignal should be cleared.
530 // Otherwise, write StartupApSignal again till AP waken up.
532 while (InterlockedCompareExchange32 (
533 (UINT32
*) ApStartupSignalBuffer
,
542 This function will fill the exchange info structure.
544 @param[in] CpuMpData Pointer to CPU MP Data
548 FillExchangeInfoData (
549 IN CPU_MP_DATA
*CpuMpData
552 volatile MP_CPU_EXCHANGE_INFO
*ExchangeInfo
;
554 ExchangeInfo
= CpuMpData
->MpCpuExchangeInfo
;
555 ExchangeInfo
->Lock
= 0;
556 ExchangeInfo
->StackStart
= CpuMpData
->Buffer
;
557 ExchangeInfo
->StackSize
= CpuMpData
->CpuApStackSize
;
558 ExchangeInfo
->BufferStart
= CpuMpData
->WakeupBuffer
;
559 ExchangeInfo
->ModeOffset
= CpuMpData
->AddressMap
.ModeEntryOffset
;
561 ExchangeInfo
->CodeSegment
= AsmReadCs ();
562 ExchangeInfo
->DataSegment
= AsmReadDs ();
564 ExchangeInfo
->Cr3
= AsmReadCr3 ();
566 ExchangeInfo
->CFunction
= (UINTN
) ApWakeupFunction
;
567 ExchangeInfo
->NumApsExecuting
= 0;
568 ExchangeInfo
->CpuMpData
= CpuMpData
;
570 ExchangeInfo
->EnableExecuteDisable
= IsBspExecuteDisableEnabled ();
573 // Get the BSP's data of GDT and IDT
575 AsmReadGdtr ((IA32_DESCRIPTOR
*) &ExchangeInfo
->GdtrProfile
);
576 AsmReadIdtr ((IA32_DESCRIPTOR
*) &ExchangeInfo
->IdtrProfile
);
580 This function will be called by BSP to wakeup AP.
582 @param[in] CpuMpData Pointer to CPU MP Data
583 @param[in] Broadcast TRUE: Send broadcast IPI to all APs
584 FALSE: Send IPI to AP by ApicId
585 @param[in] ProcessorNumber The handle number of specified processor
586 @param[in] Procedure The function to be invoked by AP
587 @param[in] ProcedureArgument The argument to be passed into AP function
591 IN CPU_MP_DATA
*CpuMpData
,
592 IN BOOLEAN Broadcast
,
593 IN UINTN ProcessorNumber
,
594 IN EFI_AP_PROCEDURE Procedure
, OPTIONAL
595 IN VOID
*ProcedureArgument OPTIONAL
598 volatile MP_CPU_EXCHANGE_INFO
*ExchangeInfo
;
600 CPU_AP_DATA
*CpuData
;
601 BOOLEAN ResetVectorRequired
;
603 CpuMpData
->FinishedCount
= 0;
604 ResetVectorRequired
= FALSE
;
606 if (CpuMpData
->ApLoopMode
== ApInHltLoop
||
607 CpuMpData
->InitFlag
!= ApInitDone
) {
608 ResetVectorRequired
= TRUE
;
609 AllocateResetVector (CpuMpData
);
610 FillExchangeInfoData (CpuMpData
);
611 } else if (CpuMpData
->ApLoopMode
== ApInMwaitLoop
) {
613 // Get AP target C-state each time when waking up AP,
614 // for it maybe updated by platform again
616 CpuMpData
->ApTargetCState
= PcdGet8 (PcdCpuApTargetCstate
);
619 ExchangeInfo
= CpuMpData
->MpCpuExchangeInfo
;
622 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
623 if (Index
!= CpuMpData
->BspNumber
) {
624 CpuData
= &CpuMpData
->CpuData
[Index
];
625 CpuData
->ApFunction
= (UINTN
) Procedure
;
626 CpuData
->ApFunctionArgument
= (UINTN
) ProcedureArgument
;
627 SetApState (CpuData
, CpuStateReady
);
628 if (CpuMpData
->InitFlag
!= ApInitConfig
) {
629 *(UINT32
*) CpuData
->StartupApSignal
= WAKEUP_AP_SIGNAL
;
633 if (ResetVectorRequired
) {
637 SendInitSipiSipiAllExcludingSelf ((UINT32
) ExchangeInfo
->BufferStart
);
639 if (CpuMpData
->InitFlag
!= ApInitConfig
) {
641 // Wait all APs waken up if this is not the 1st broadcast of SIPI
643 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
644 CpuData
= &CpuMpData
->CpuData
[Index
];
645 if (Index
!= CpuMpData
->BspNumber
) {
646 WaitApWakeup (CpuData
->StartupApSignal
);
651 CpuData
= &CpuMpData
->CpuData
[ProcessorNumber
];
652 CpuData
->ApFunction
= (UINTN
) Procedure
;
653 CpuData
->ApFunctionArgument
= (UINTN
) ProcedureArgument
;
654 SetApState (CpuData
, CpuStateReady
);
656 // Wakeup specified AP
658 ASSERT (CpuMpData
->InitFlag
!= ApInitConfig
);
659 *(UINT32
*) CpuData
->StartupApSignal
= WAKEUP_AP_SIGNAL
;
660 if (ResetVectorRequired
) {
663 (UINT32
) ExchangeInfo
->BufferStart
667 // Wait specified AP waken up
669 WaitApWakeup (CpuData
->StartupApSignal
);
672 if (ResetVectorRequired
) {
673 FreeResetVector (CpuMpData
);
678 MP Initialize Library initialization.
680 This service will allocate AP reset vector and wakeup all APs to do APs
683 This service must be invoked before all other MP Initialize Library
686 @retval EFI_SUCCESS MP initialization succeeds.
687 @retval Others MP initialization fails.
692 MpInitLibInitialize (
696 UINT32 MaxLogicalProcessorNumber
;
698 MP_ASSEMBLY_ADDRESS_MAP AddressMap
;
700 UINT32 MonitorFilterSize
;
703 CPU_MP_DATA
*CpuMpData
;
705 UINT8
*MonitorBuffer
;
707 UINTN ApResetVectorSize
;
708 UINTN BackupBufferAddr
;
709 MaxLogicalProcessorNumber
= PcdGet32(PcdCpuMaxLogicalProcessorNumber
);
711 AsmGetAddressMap (&AddressMap
);
712 ApResetVectorSize
= AddressMap
.RendezvousFunnelSize
+ sizeof (MP_CPU_EXCHANGE_INFO
);
713 ApStackSize
= PcdGet32(PcdCpuApStackSize
);
714 ApLoopMode
= GetApLoopMode (&MonitorFilterSize
);
716 BufferSize
= ApStackSize
* MaxLogicalProcessorNumber
;
717 BufferSize
+= MonitorFilterSize
* MaxLogicalProcessorNumber
;
718 BufferSize
+= sizeof (CPU_MP_DATA
);
719 BufferSize
+= ApResetVectorSize
;
720 BufferSize
+= (sizeof (CPU_AP_DATA
) + sizeof (CPU_INFO_IN_HOB
))* MaxLogicalProcessorNumber
;
721 MpBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (BufferSize
));
722 ASSERT (MpBuffer
!= NULL
);
723 ZeroMem (MpBuffer
, BufferSize
);
724 Buffer
= (UINTN
) MpBuffer
;
726 MonitorBuffer
= (UINT8
*) (Buffer
+ ApStackSize
* MaxLogicalProcessorNumber
);
727 BackupBufferAddr
= (UINTN
) MonitorBuffer
+ MonitorFilterSize
* MaxLogicalProcessorNumber
;
728 CpuMpData
= (CPU_MP_DATA
*) (BackupBufferAddr
+ ApResetVectorSize
);
729 CpuMpData
->Buffer
= Buffer
;
730 CpuMpData
->CpuApStackSize
= ApStackSize
;
731 CpuMpData
->BackupBuffer
= BackupBufferAddr
;
732 CpuMpData
->BackupBufferSize
= ApResetVectorSize
;
733 CpuMpData
->EndOfPeiFlag
= FALSE
;
734 CpuMpData
->WakeupBuffer
= (UINTN
) -1;
735 CpuMpData
->CpuCount
= 1;
736 CpuMpData
->BspNumber
= 0;
737 CpuMpData
->WaitEvent
= NULL
;
738 CpuMpData
->CpuData
= (CPU_AP_DATA
*) (CpuMpData
+ 1);
739 CpuMpData
->CpuInfoInHob
= (UINT64
) (UINTN
) (CpuMpData
->CpuData
+ MaxLogicalProcessorNumber
);
740 InitializeSpinLock(&CpuMpData
->MpLock
);
742 // Save BSP's Control registers to APs
744 SaveVolatileRegisters (&CpuMpData
->CpuData
[0].VolatileRegisters
);
746 // Set BSP basic information
748 InitializeApData (CpuMpData
, 0, 0);
750 // Save assembly code information
752 CopyMem (&CpuMpData
->AddressMap
, &AddressMap
, sizeof (MP_ASSEMBLY_ADDRESS_MAP
));
754 // Finally set AP loop mode
756 CpuMpData
->ApLoopMode
= ApLoopMode
;
757 DEBUG ((DEBUG_INFO
, "AP Loop Mode is %d\n", CpuMpData
->ApLoopMode
));
759 // Set up APs wakeup signal buffer
761 for (Index
= 0; Index
< MaxLogicalProcessorNumber
; Index
++) {
762 CpuMpData
->CpuData
[Index
].StartupApSignal
=
763 (UINT32
*)(MonitorBuffer
+ MonitorFilterSize
* Index
);
766 // Load Microcode on BSP
768 MicrocodeDetect (CpuMpData
);
770 // Store BSP's MTRR setting
772 MtrrGetAllMtrrs (&CpuMpData
->MtrrTable
);
776 // Wakeup all APs and calculate the processor count in system
778 CollectProcessorCount (CpuMpData
);
780 // Initialize global data for MP support
782 InitMpGlobalData (CpuMpData
);
788 Gets detailed MP-related information on the requested processor at the
789 instant this call is made. This service may only be called from the BSP.
791 @param[in] ProcessorNumber The handle number of processor.
792 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
793 the requested processor is deposited.
794 @param[out] HealthData Return processor health data.
796 @retval EFI_SUCCESS Processor information was returned.
797 @retval EFI_DEVICE_ERROR The calling processor is an AP.
798 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
799 @retval EFI_NOT_FOUND The processor with the handle specified by
800 ProcessorNumber does not exist in the platform.
801 @retval EFI_NOT_READY MP Initialize Library is not initialized.
806 MpInitLibGetProcessorInfo (
807 IN UINTN ProcessorNumber
,
808 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
,
809 OUT EFI_HEALTH_FLAGS
*HealthData OPTIONAL
812 return EFI_UNSUPPORTED
;
815 This return the handle number for the calling processor. This service may be
816 called from the BSP and APs.
818 @param[out] ProcessorNumber Pointer to the handle number of AP.
819 The range is from 0 to the total number of
820 logical processors minus 1. The total number of
821 logical processors can be retrieved by
822 MpInitLibGetNumberOfProcessors().
824 @retval EFI_SUCCESS The current processor handle number was returned
826 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
827 @retval EFI_NOT_READY MP Initialize Library is not initialized.
833 OUT UINTN
*ProcessorNumber
836 return EFI_UNSUPPORTED
;
839 Retrieves the number of logical processor in the platform and the number of
840 those logical processors that are enabled on this boot. This service may only
841 be called from the BSP.
843 @param[out] NumberOfProcessors Pointer to the total number of logical
844 processors in the system, including the BSP
846 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
847 processors that exist in system, including
850 @retval EFI_SUCCESS The number of logical processors and enabled
851 logical processors was retrieved.
852 @retval EFI_DEVICE_ERROR The calling processor is an AP.
853 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
855 @retval EFI_NOT_READY MP Initialize Library is not initialized.
860 MpInitLibGetNumberOfProcessors (
861 OUT UINTN
*NumberOfProcessors
, OPTIONAL
862 OUT UINTN
*NumberOfEnabledProcessors OPTIONAL
865 return EFI_UNSUPPORTED
;
868 Get pointer to CPU MP Data structure from GUIDed HOB.
870 @return The pointer to CPU MP Data structure.
873 GetCpuMpDataFromGuidedHob (
877 EFI_HOB_GUID_TYPE
*GuidHob
;
879 CPU_MP_DATA
*CpuMpData
;
882 GuidHob
= GetFirstGuidHob (&mCpuInitMpLibHobGuid
);
883 if (GuidHob
!= NULL
) {
884 DataInHob
= GET_GUID_HOB_DATA (GuidHob
);
885 CpuMpData
= (CPU_MP_DATA
*) (*(UINTN
*) DataInHob
);