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 Sort the APIC ID of all processors.
222 This function sorts the APIC ID of all processors so that processor number is
223 assigned in the ascending order of APIC ID which eases MP debugging.
225 @param[in] CpuMpData Pointer to PEI CPU MP Data
229 IN CPU_MP_DATA
*CpuMpData
238 CPU_INFO_IN_HOB
*CpuInfoInHob
;
240 ApCount
= CpuMpData
->CpuCount
- 1;
243 for (Index1
= 0; Index1
< ApCount
; Index1
++) {
246 // Sort key is the hardware default APIC ID
248 ApicId
= CpuMpData
->CpuData
[Index1
].ApicId
;
249 for (Index2
= Index1
+ 1; Index2
<= ApCount
; Index2
++) {
250 if (ApicId
> CpuMpData
->CpuData
[Index2
].ApicId
) {
252 ApicId
= CpuMpData
->CpuData
[Index2
].ApicId
;
255 if (Index3
!= Index1
) {
256 CopyMem (&CpuData
, &CpuMpData
->CpuData
[Index3
], sizeof (CPU_AP_DATA
));
258 &CpuMpData
->CpuData
[Index3
],
259 &CpuMpData
->CpuData
[Index1
],
262 CopyMem (&CpuMpData
->CpuData
[Index1
], &CpuData
, sizeof (CPU_AP_DATA
));
267 // Get the processor number for the BSP
269 ApicId
= GetInitialApicId ();
270 for (Index1
= 0; Index1
< CpuMpData
->CpuCount
; Index1
++) {
271 if (CpuMpData
->CpuData
[Index1
].ApicId
== ApicId
) {
272 CpuMpData
->BspNumber
= (UINT32
) Index1
;
277 CpuInfoInHob
= (CPU_INFO_IN_HOB
*) (UINTN
) CpuMpData
->CpuInfoInHob
;
278 for (Index1
= 0; Index1
< CpuMpData
->CpuCount
; Index1
++) {
279 CpuInfoInHob
[Index1
].InitialApicId
= CpuMpData
->CpuData
[Index1
].InitialApicId
;
280 CpuInfoInHob
[Index1
].ApicId
= CpuMpData
->CpuData
[Index1
].ApicId
;
281 CpuInfoInHob
[Index1
].Health
= CpuMpData
->CpuData
[Index1
].Health
;
287 Enable x2APIC mode on APs.
289 @param[in, out] Buffer Pointer to private data buffer.
297 SetApicMode (LOCAL_APIC_MODE_X2APIC
);
303 @param[in, out] Buffer Pointer to private data buffer.
311 CPU_MP_DATA
*CpuMpData
;
313 CpuMpData
= (CPU_MP_DATA
*) Buffer
;
315 // Sync BSP's MTRR table to AP
317 MtrrSetAllMtrrs (&CpuMpData
->MtrrTable
);
319 // Load microcode on AP
321 MicrocodeDetect (CpuMpData
);
325 Find the current Processor number by APIC ID.
327 @param[in] CpuMpData Pointer to PEI CPU MP Data
328 @param[in] ProcessorNumber Return the pocessor number found
330 @retval EFI_SUCCESS ProcessorNumber is found and returned.
331 @retval EFI_NOT_FOUND ProcessorNumber is not found.
335 IN CPU_MP_DATA
*CpuMpData
,
336 OUT UINTN
*ProcessorNumber
339 UINTN TotalProcessorNumber
;
342 TotalProcessorNumber
= CpuMpData
->CpuCount
;
343 for (Index
= 0; Index
< TotalProcessorNumber
; Index
++) {
344 if (CpuMpData
->CpuData
[Index
].ApicId
== GetApicId ()) {
345 *ProcessorNumber
= Index
;
349 return EFI_NOT_FOUND
;
353 This function will get CPU count in the system.
355 @param[in] CpuMpData Pointer to PEI CPU MP Data
357 @return CPU count detected
360 CollectProcessorCount (
361 IN CPU_MP_DATA
*CpuMpData
365 // Send 1st broadcast IPI to APs to wakeup APs
367 CpuMpData
->InitFlag
= ApInitConfig
;
368 CpuMpData
->X2ApicEnable
= FALSE
;
369 WakeUpAP (CpuMpData
, TRUE
, 0, NULL
, NULL
);
371 // Wait for AP task to complete and then exit.
373 MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds
));
374 CpuMpData
->InitFlag
= ApInitDone
;
375 ASSERT (CpuMpData
->CpuCount
<= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
));
377 // Wait for all APs finished the initialization
379 while (CpuMpData
->FinishedCount
< (CpuMpData
->CpuCount
- 1)) {
383 if (CpuMpData
->X2ApicEnable
) {
384 DEBUG ((DEBUG_INFO
, "Force x2APIC mode!\n"));
386 // Wakeup all APs to enable x2APIC mode
388 WakeUpAP (CpuMpData
, TRUE
, 0, ApFuncEnableX2Apic
, NULL
);
390 // Wait for all known APs finished
392 while (CpuMpData
->FinishedCount
< (CpuMpData
->CpuCount
- 1)) {
396 // Enable x2APIC on BSP
398 SetApicMode (LOCAL_APIC_MODE_X2APIC
);
400 DEBUG ((DEBUG_INFO
, "APIC MODE is %d\n", GetApicMode ()));
402 // Sort BSP/Aps by CPU APIC ID in ascending order
404 SortApicId (CpuMpData
);
406 DEBUG ((DEBUG_INFO
, "MpInitLib: Find %d processors in system.\n", CpuMpData
->CpuCount
));
408 return CpuMpData
->CpuCount
;
412 Initialize CPU AP Data when AP is wakeup at the first time.
414 @param[in, out] CpuMpData Pointer to PEI CPU MP Data
415 @param[in] ProcessorNumber The handle number of processor
416 @param[in] BistData Processor BIST data
421 IN OUT CPU_MP_DATA
*CpuMpData
,
422 IN UINTN ProcessorNumber
,
426 CpuMpData
->CpuData
[ProcessorNumber
].Waiting
= FALSE
;
427 CpuMpData
->CpuData
[ProcessorNumber
].Health
= BistData
;
428 CpuMpData
->CpuData
[ProcessorNumber
].CpuHealthy
= (BistData
== 0) ? TRUE
: FALSE
;
429 CpuMpData
->CpuData
[ProcessorNumber
].ApicId
= GetApicId ();
430 CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
= GetInitialApicId ();
431 if (CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
>= 0xFF) {
433 // Set x2APIC mode if there are any logical processor reporting
434 // an Initial APIC ID of 255 or greater.
436 AcquireSpinLock(&CpuMpData
->MpLock
);
437 CpuMpData
->X2ApicEnable
= TRUE
;
438 ReleaseSpinLock(&CpuMpData
->MpLock
);
441 InitializeSpinLock(&CpuMpData
->CpuData
[ProcessorNumber
].ApLock
);
442 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateIdle
);
446 This function will be called from AP reset code if BSP uses WakeUpAP.
448 @param[in] ExchangeInfo Pointer to the MP exchange info buffer
449 @param[in] NumApsExecuting Number of current executing AP
454 IN MP_CPU_EXCHANGE_INFO
*ExchangeInfo
,
455 IN UINTN NumApsExecuting
458 CPU_MP_DATA
*CpuMpData
;
459 UINTN ProcessorNumber
;
460 EFI_AP_PROCEDURE Procedure
;
463 volatile UINT32
*ApStartupSignalBuffer
;
466 // AP finished assembly code and begin to execute C code
468 CpuMpData
= ExchangeInfo
->CpuMpData
;
470 ProgramVirtualWireMode ();
473 if (CpuMpData
->InitFlag
== ApInitConfig
) {
477 InterlockedIncrement ((UINT32
*) &CpuMpData
->CpuCount
);
478 ProcessorNumber
= NumApsExecuting
;
480 // This is first time AP wakeup, get BIST information from AP stack
482 BistData
= *(UINT32
*) (CpuMpData
->Buffer
+ ProcessorNumber
* CpuMpData
->CpuApStackSize
- sizeof (UINTN
));
484 // Do some AP initialize sync
486 ApInitializeSync (CpuMpData
);
488 // Sync BSP's Control registers to APs
490 RestoreVolatileRegisters (&CpuMpData
->CpuData
[0].VolatileRegisters
, FALSE
);
491 InitializeApData (CpuMpData
, ProcessorNumber
, BistData
);
492 ApStartupSignalBuffer
= CpuMpData
->CpuData
[ProcessorNumber
].StartupApSignal
;
495 // Execute AP function if AP is ready
497 GetProcessorNumber (CpuMpData
, &ProcessorNumber
);
499 // Clear AP start-up signal when AP waken up
501 ApStartupSignalBuffer
= CpuMpData
->CpuData
[ProcessorNumber
].StartupApSignal
;
502 InterlockedCompareExchange32 (
503 (UINT32
*) ApStartupSignalBuffer
,
507 if (CpuMpData
->ApLoopMode
== ApInHltLoop
) {
509 // Restore AP's volatile registers saved
511 RestoreVolatileRegisters (&CpuMpData
->CpuData
[ProcessorNumber
].VolatileRegisters
, TRUE
);
514 if (GetApState (&CpuMpData
->CpuData
[ProcessorNumber
]) == CpuStateReady
) {
515 Procedure
= (EFI_AP_PROCEDURE
)CpuMpData
->CpuData
[ProcessorNumber
].ApFunction
;
516 Parameter
= (VOID
*) CpuMpData
->CpuData
[ProcessorNumber
].ApFunctionArgument
;
517 if (Procedure
!= NULL
) {
518 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateBusy
);
520 // Invoke AP function here
522 Procedure (Parameter
);
524 // Re-get the CPU APICID and Initial APICID
526 CpuMpData
->CpuData
[ProcessorNumber
].ApicId
= GetApicId ();
527 CpuMpData
->CpuData
[ProcessorNumber
].InitialApicId
= GetInitialApicId ();
529 SetApState (&CpuMpData
->CpuData
[ProcessorNumber
], CpuStateFinished
);
534 // AP finished executing C code
536 InterlockedIncrement ((UINT32
*) &CpuMpData
->FinishedCount
);
539 // Place AP is specified loop mode
541 if (CpuMpData
->ApLoopMode
== ApInHltLoop
) {
543 // Save AP volatile registers
545 SaveVolatileRegisters (&CpuMpData
->CpuData
[ProcessorNumber
].VolatileRegisters
);
547 // Place AP in HLT-loop
550 DisableInterrupts ();
556 DisableInterrupts ();
557 if (CpuMpData
->ApLoopMode
== ApInMwaitLoop
) {
559 // Place AP in MWAIT-loop
561 AsmMonitor ((UINTN
) ApStartupSignalBuffer
, 0, 0);
562 if (*ApStartupSignalBuffer
!= WAKEUP_AP_SIGNAL
) {
564 // Check AP start-up signal again.
565 // If AP start-up signal is not set, place AP into
566 // the specified C-state
568 AsmMwait (CpuMpData
->ApTargetCState
<< 4, 0);
570 } else if (CpuMpData
->ApLoopMode
== ApInRunLoop
) {
572 // Place AP in Run-loop
580 // If AP start-up signal is written, AP is waken up
581 // otherwise place AP in loop again
583 if (*ApStartupSignalBuffer
== WAKEUP_AP_SIGNAL
) {
591 Wait for AP wakeup and write AP start-up signal till AP is waken up.
593 @param[in] ApStartupSignalBuffer Pointer to AP wakeup signal
597 IN
volatile UINT32
*ApStartupSignalBuffer
601 // If AP is waken up, StartupApSignal should be cleared.
602 // Otherwise, write StartupApSignal again till AP waken up.
604 while (InterlockedCompareExchange32 (
605 (UINT32
*) ApStartupSignalBuffer
,
614 This function will fill the exchange info structure.
616 @param[in] CpuMpData Pointer to CPU MP Data
620 FillExchangeInfoData (
621 IN CPU_MP_DATA
*CpuMpData
624 volatile MP_CPU_EXCHANGE_INFO
*ExchangeInfo
;
626 ExchangeInfo
= CpuMpData
->MpCpuExchangeInfo
;
627 ExchangeInfo
->Lock
= 0;
628 ExchangeInfo
->StackStart
= CpuMpData
->Buffer
;
629 ExchangeInfo
->StackSize
= CpuMpData
->CpuApStackSize
;
630 ExchangeInfo
->BufferStart
= CpuMpData
->WakeupBuffer
;
631 ExchangeInfo
->ModeOffset
= CpuMpData
->AddressMap
.ModeEntryOffset
;
633 ExchangeInfo
->CodeSegment
= AsmReadCs ();
634 ExchangeInfo
->DataSegment
= AsmReadDs ();
636 ExchangeInfo
->Cr3
= AsmReadCr3 ();
638 ExchangeInfo
->CFunction
= (UINTN
) ApWakeupFunction
;
639 ExchangeInfo
->NumApsExecuting
= 0;
640 ExchangeInfo
->CpuMpData
= CpuMpData
;
642 ExchangeInfo
->EnableExecuteDisable
= IsBspExecuteDisableEnabled ();
645 // Get the BSP's data of GDT and IDT
647 AsmReadGdtr ((IA32_DESCRIPTOR
*) &ExchangeInfo
->GdtrProfile
);
648 AsmReadIdtr ((IA32_DESCRIPTOR
*) &ExchangeInfo
->IdtrProfile
);
652 This function will be called by BSP to wakeup AP.
654 @param[in] CpuMpData Pointer to CPU MP Data
655 @param[in] Broadcast TRUE: Send broadcast IPI to all APs
656 FALSE: Send IPI to AP by ApicId
657 @param[in] ProcessorNumber The handle number of specified processor
658 @param[in] Procedure The function to be invoked by AP
659 @param[in] ProcedureArgument The argument to be passed into AP function
663 IN CPU_MP_DATA
*CpuMpData
,
664 IN BOOLEAN Broadcast
,
665 IN UINTN ProcessorNumber
,
666 IN EFI_AP_PROCEDURE Procedure
, OPTIONAL
667 IN VOID
*ProcedureArgument OPTIONAL
670 volatile MP_CPU_EXCHANGE_INFO
*ExchangeInfo
;
672 CPU_AP_DATA
*CpuData
;
673 BOOLEAN ResetVectorRequired
;
675 CpuMpData
->FinishedCount
= 0;
676 ResetVectorRequired
= FALSE
;
678 if (CpuMpData
->ApLoopMode
== ApInHltLoop
||
679 CpuMpData
->InitFlag
!= ApInitDone
) {
680 ResetVectorRequired
= TRUE
;
681 AllocateResetVector (CpuMpData
);
682 FillExchangeInfoData (CpuMpData
);
683 } else if (CpuMpData
->ApLoopMode
== ApInMwaitLoop
) {
685 // Get AP target C-state each time when waking up AP,
686 // for it maybe updated by platform again
688 CpuMpData
->ApTargetCState
= PcdGet8 (PcdCpuApTargetCstate
);
691 ExchangeInfo
= CpuMpData
->MpCpuExchangeInfo
;
694 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
695 if (Index
!= CpuMpData
->BspNumber
) {
696 CpuData
= &CpuMpData
->CpuData
[Index
];
697 CpuData
->ApFunction
= (UINTN
) Procedure
;
698 CpuData
->ApFunctionArgument
= (UINTN
) ProcedureArgument
;
699 SetApState (CpuData
, CpuStateReady
);
700 if (CpuMpData
->InitFlag
!= ApInitConfig
) {
701 *(UINT32
*) CpuData
->StartupApSignal
= WAKEUP_AP_SIGNAL
;
705 if (ResetVectorRequired
) {
709 SendInitSipiSipiAllExcludingSelf ((UINT32
) ExchangeInfo
->BufferStart
);
711 if (CpuMpData
->InitFlag
!= ApInitConfig
) {
713 // Wait all APs waken up if this is not the 1st broadcast of SIPI
715 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
716 CpuData
= &CpuMpData
->CpuData
[Index
];
717 if (Index
!= CpuMpData
->BspNumber
) {
718 WaitApWakeup (CpuData
->StartupApSignal
);
723 CpuData
= &CpuMpData
->CpuData
[ProcessorNumber
];
724 CpuData
->ApFunction
= (UINTN
) Procedure
;
725 CpuData
->ApFunctionArgument
= (UINTN
) ProcedureArgument
;
726 SetApState (CpuData
, CpuStateReady
);
728 // Wakeup specified AP
730 ASSERT (CpuMpData
->InitFlag
!= ApInitConfig
);
731 *(UINT32
*) CpuData
->StartupApSignal
= WAKEUP_AP_SIGNAL
;
732 if (ResetVectorRequired
) {
735 (UINT32
) ExchangeInfo
->BufferStart
739 // Wait specified AP waken up
741 WaitApWakeup (CpuData
->StartupApSignal
);
744 if (ResetVectorRequired
) {
745 FreeResetVector (CpuMpData
);
750 MP Initialize Library initialization.
752 This service will allocate AP reset vector and wakeup all APs to do APs
755 This service must be invoked before all other MP Initialize Library
758 @retval EFI_SUCCESS MP initialization succeeds.
759 @retval Others MP initialization fails.
764 MpInitLibInitialize (
768 CPU_MP_DATA
*OldCpuMpData
;
769 CPU_INFO_IN_HOB
*CpuInfoInHob
;
770 UINT32 MaxLogicalProcessorNumber
;
772 MP_ASSEMBLY_ADDRESS_MAP AddressMap
;
774 UINT32 MonitorFilterSize
;
777 CPU_MP_DATA
*CpuMpData
;
779 UINT8
*MonitorBuffer
;
781 UINTN ApResetVectorSize
;
782 UINTN BackupBufferAddr
;
784 OldCpuMpData
= GetCpuMpDataFromGuidedHob ();
785 if (OldCpuMpData
== NULL
) {
786 MaxLogicalProcessorNumber
= PcdGet32(PcdCpuMaxLogicalProcessorNumber
);
788 MaxLogicalProcessorNumber
= OldCpuMpData
->CpuCount
;
791 AsmGetAddressMap (&AddressMap
);
792 ApResetVectorSize
= AddressMap
.RendezvousFunnelSize
+ sizeof (MP_CPU_EXCHANGE_INFO
);
793 ApStackSize
= PcdGet32(PcdCpuApStackSize
);
794 ApLoopMode
= GetApLoopMode (&MonitorFilterSize
);
796 BufferSize
= ApStackSize
* MaxLogicalProcessorNumber
;
797 BufferSize
+= MonitorFilterSize
* MaxLogicalProcessorNumber
;
798 BufferSize
+= sizeof (CPU_MP_DATA
);
799 BufferSize
+= ApResetVectorSize
;
800 BufferSize
+= (sizeof (CPU_AP_DATA
) + sizeof (CPU_INFO_IN_HOB
))* MaxLogicalProcessorNumber
;
801 MpBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (BufferSize
));
802 ASSERT (MpBuffer
!= NULL
);
803 ZeroMem (MpBuffer
, BufferSize
);
804 Buffer
= (UINTN
) MpBuffer
;
806 MonitorBuffer
= (UINT8
*) (Buffer
+ ApStackSize
* MaxLogicalProcessorNumber
);
807 BackupBufferAddr
= (UINTN
) MonitorBuffer
+ MonitorFilterSize
* MaxLogicalProcessorNumber
;
808 CpuMpData
= (CPU_MP_DATA
*) (BackupBufferAddr
+ ApResetVectorSize
);
809 CpuMpData
->Buffer
= Buffer
;
810 CpuMpData
->CpuApStackSize
= ApStackSize
;
811 CpuMpData
->BackupBuffer
= BackupBufferAddr
;
812 CpuMpData
->BackupBufferSize
= ApResetVectorSize
;
813 CpuMpData
->EndOfPeiFlag
= FALSE
;
814 CpuMpData
->WakeupBuffer
= (UINTN
) -1;
815 CpuMpData
->CpuCount
= 1;
816 CpuMpData
->BspNumber
= 0;
817 CpuMpData
->WaitEvent
= NULL
;
818 CpuMpData
->CpuData
= (CPU_AP_DATA
*) (CpuMpData
+ 1);
819 CpuMpData
->CpuInfoInHob
= (UINT64
) (UINTN
) (CpuMpData
->CpuData
+ MaxLogicalProcessorNumber
);
820 InitializeSpinLock(&CpuMpData
->MpLock
);
822 // Save BSP's Control registers to APs
824 SaveVolatileRegisters (&CpuMpData
->CpuData
[0].VolatileRegisters
);
826 // Set BSP basic information
828 InitializeApData (CpuMpData
, 0, 0);
830 // Save assembly code information
832 CopyMem (&CpuMpData
->AddressMap
, &AddressMap
, sizeof (MP_ASSEMBLY_ADDRESS_MAP
));
834 // Finally set AP loop mode
836 CpuMpData
->ApLoopMode
= ApLoopMode
;
837 DEBUG ((DEBUG_INFO
, "AP Loop Mode is %d\n", CpuMpData
->ApLoopMode
));
839 // Set up APs wakeup signal buffer
841 for (Index
= 0; Index
< MaxLogicalProcessorNumber
; Index
++) {
842 CpuMpData
->CpuData
[Index
].StartupApSignal
=
843 (UINT32
*)(MonitorBuffer
+ MonitorFilterSize
* Index
);
846 // Load Microcode on BSP
848 MicrocodeDetect (CpuMpData
);
850 // Store BSP's MTRR setting
852 MtrrGetAllMtrrs (&CpuMpData
->MtrrTable
);
854 if (OldCpuMpData
== NULL
) {
856 // Wakeup all APs and calculate the processor count in system
858 CollectProcessorCount (CpuMpData
);
861 // APs have been wakeup before, just get the CPU Information
864 CpuMpData
->CpuCount
= OldCpuMpData
->CpuCount
;
865 CpuMpData
->BspNumber
= OldCpuMpData
->BspNumber
;
866 CpuMpData
->InitFlag
= ApInitReconfig
;
867 CpuInfoInHob
= (CPU_INFO_IN_HOB
*) (UINTN
) OldCpuMpData
->CpuInfoInHob
;
868 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
869 InitializeSpinLock(&CpuMpData
->CpuData
[Index
].ApLock
);
870 CpuMpData
->CpuData
[Index
].ApicId
= CpuInfoInHob
[Index
].ApicId
;
871 CpuMpData
->CpuData
[Index
].InitialApicId
= CpuInfoInHob
[Index
].InitialApicId
;
872 if (CpuMpData
->CpuData
[Index
].InitialApicId
>= 255) {
873 CpuMpData
->X2ApicEnable
= TRUE
;
875 CpuMpData
->CpuData
[Index
].Health
= CpuInfoInHob
[Index
].Health
;
876 CpuMpData
->CpuData
[Index
].CpuHealthy
= (CpuMpData
->CpuData
[Index
].Health
== 0)? TRUE
:FALSE
;
877 CpuMpData
->CpuData
[Index
].ApFunction
= 0;
879 &CpuMpData
->CpuData
[Index
].VolatileRegisters
,
880 &CpuMpData
->CpuData
[0].VolatileRegisters
,
881 sizeof (CPU_VOLATILE_REGISTERS
)
885 // Wakeup APs to do some AP initialize sync
887 WakeUpAP (CpuMpData
, TRUE
, 0, ApInitializeSync
, CpuMpData
);
889 // Wait for all APs finished initialization
891 while (CpuMpData
->FinishedCount
< (CpuMpData
->CpuCount
- 1)) {
894 CpuMpData
->InitFlag
= ApInitDone
;
895 for (Index
= 0; Index
< CpuMpData
->CpuCount
; Index
++) {
896 SetApState (&CpuMpData
->CpuData
[Index
], CpuStateIdle
);
901 // Initialize global data for MP support
903 InitMpGlobalData (CpuMpData
);
909 Gets detailed MP-related information on the requested processor at the
910 instant this call is made. This service may only be called from the BSP.
912 @param[in] ProcessorNumber The handle number of processor.
913 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
914 the requested processor is deposited.
915 @param[out] HealthData Return processor health data.
917 @retval EFI_SUCCESS Processor information was returned.
918 @retval EFI_DEVICE_ERROR The calling processor is an AP.
919 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
920 @retval EFI_NOT_FOUND The processor with the handle specified by
921 ProcessorNumber does not exist in the platform.
922 @retval EFI_NOT_READY MP Initialize Library is not initialized.
927 MpInitLibGetProcessorInfo (
928 IN UINTN ProcessorNumber
,
929 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
,
930 OUT EFI_HEALTH_FLAGS
*HealthData OPTIONAL
933 return EFI_UNSUPPORTED
;
936 This return the handle number for the calling processor. This service may be
937 called from the BSP and APs.
939 @param[out] ProcessorNumber Pointer to the handle number of AP.
940 The range is from 0 to the total number of
941 logical processors minus 1. The total number of
942 logical processors can be retrieved by
943 MpInitLibGetNumberOfProcessors().
945 @retval EFI_SUCCESS The current processor handle number was returned
947 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
948 @retval EFI_NOT_READY MP Initialize Library is not initialized.
954 OUT UINTN
*ProcessorNumber
957 return EFI_UNSUPPORTED
;
960 Retrieves the number of logical processor in the platform and the number of
961 those logical processors that are enabled on this boot. This service may only
962 be called from the BSP.
964 @param[out] NumberOfProcessors Pointer to the total number of logical
965 processors in the system, including the BSP
967 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
968 processors that exist in system, including
971 @retval EFI_SUCCESS The number of logical processors and enabled
972 logical processors was retrieved.
973 @retval EFI_DEVICE_ERROR The calling processor is an AP.
974 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
976 @retval EFI_NOT_READY MP Initialize Library is not initialized.
981 MpInitLibGetNumberOfProcessors (
982 OUT UINTN
*NumberOfProcessors
, OPTIONAL
983 OUT UINTN
*NumberOfEnabledProcessors OPTIONAL
986 return EFI_UNSUPPORTED
;
990 Get pointer to CPU MP Data structure from GUIDed HOB.
992 @return The pointer to CPU MP Data structure.
995 GetCpuMpDataFromGuidedHob (
999 EFI_HOB_GUID_TYPE
*GuidHob
;
1001 CPU_MP_DATA
*CpuMpData
;
1004 GuidHob
= GetFirstGuidHob (&mCpuInitMpLibHobGuid
);
1005 if (GuidHob
!= NULL
) {
1006 DataInHob
= GET_GUID_HOB_DATA (GuidHob
);
1007 CpuMpData
= (CPU_MP_DATA
*) (*(UINTN
*) DataInHob
);