X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMpInitLib%2FMpLib.c;h=529df60ce6f680c69a871485379512956233eb46;hb=31a1e4da495ed211d7bdfdfe626a18c594aaa11c;hp=c10dcd3fcb68db0514e738e684cba97d5743fc17;hpb=20ae57745b19538229ba0670c10e08c13f9e2574;p=mirror_edk2.git diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index c10dcd3fcb..529df60ce6 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -57,132 +57,6 @@ IsBspExecuteDisableEnabled ( return Enabled; } -/** - Get CPU Package/Core/Thread location information. - - @param[in] InitialApicId CPU APIC ID - @param[out] Location Pointer to CPU location information -**/ -VOID -ExtractProcessorLocation ( - IN UINT32 InitialApicId, - OUT EFI_CPU_PHYSICAL_LOCATION *Location - ) -{ - BOOLEAN TopologyLeafSupported; - UINTN ThreadBits; - UINTN CoreBits; - CPUID_VERSION_INFO_EBX VersionInfoEbx; - CPUID_VERSION_INFO_EDX VersionInfoEdx; - CPUID_CACHE_PARAMS_EAX CacheParamsEax; - CPUID_EXTENDED_TOPOLOGY_EAX ExtendedTopologyEax; - CPUID_EXTENDED_TOPOLOGY_EBX ExtendedTopologyEbx; - CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx; - UINT32 MaxCpuIdIndex; - UINT32 SubIndex; - UINTN LevelType; - UINT32 MaxLogicProcessorsPerPackage; - UINT32 MaxCoresPerPackage; - - // - // Check if the processor is capable of supporting more than one logical processor. - // - AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32); - if (VersionInfoEdx.Bits.HTT == 0) { - Location->Thread = 0; - Location->Core = 0; - Location->Package = 0; - return; - } - - ThreadBits = 0; - CoreBits = 0; - - // - // Assume three-level mapping of APIC ID: Package:Core:SMT. - // - - TopologyLeafSupported = FALSE; - // - // Get the max index of basic CPUID - // - AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL); - - // - // If the extended topology enumeration leaf is available, it - // is the preferred mechanism for enumerating topology. - // - if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) { - AsmCpuidEx ( - CPUID_EXTENDED_TOPOLOGY, - 0, - &ExtendedTopologyEax.Uint32, - &ExtendedTopologyEbx.Uint32, - &ExtendedTopologyEcx.Uint32, - NULL - ); - // - // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for - // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not - // supported on that processor. - // - if (ExtendedTopologyEbx.Uint32 != 0) { - TopologyLeafSupported = TRUE; - - // - // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract - // the SMT sub-field of x2APIC ID. - // - LevelType = ExtendedTopologyEcx.Bits.LevelType; - ASSERT (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT); - ThreadBits = ExtendedTopologyEax.Bits.ApicIdShift; - - // - // Software must not assume any "level type" encoding - // value to be related to any sub-leaf index, except sub-leaf 0. - // - SubIndex = 1; - do { - AsmCpuidEx ( - CPUID_EXTENDED_TOPOLOGY, - SubIndex, - &ExtendedTopologyEax.Uint32, - NULL, - &ExtendedTopologyEcx.Uint32, - NULL - ); - LevelType = ExtendedTopologyEcx.Bits.LevelType; - if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) { - CoreBits = ExtendedTopologyEax.Bits.ApicIdShift - ThreadBits; - break; - } - SubIndex++; - } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID); - } - } - - if (!TopologyLeafSupported) { - AsmCpuid (CPUID_VERSION_INFO, NULL, &VersionInfoEbx.Uint32, NULL, NULL); - MaxLogicProcessorsPerPackage = VersionInfoEbx.Bits.MaximumAddressableIdsForLogicalProcessors; - if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) { - AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &CacheParamsEax.Uint32, NULL, NULL, NULL); - MaxCoresPerPackage = CacheParamsEax.Bits.MaximumAddressableIdsForLogicalProcessors + 1; - } else { - // - // Must be a single-core processor. - // - MaxCoresPerPackage = 1; - } - - ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1); - CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1); - } - - Location->Thread = InitialApicId & ((1 << ThreadBits) - 1); - Location->Core = (InitialApicId >> ThreadBits) & ((1 << CoreBits) - 1); - Location->Package = (InitialApicId >> (ThreadBits + CoreBits)); -} - /** Worker function for SwitchBSP(). @@ -379,33 +253,33 @@ SortApicId ( UINTN Index2; UINTN Index3; UINT32 ApicId; - CPU_AP_DATA CpuData; + CPU_INFO_IN_HOB CpuInfo; UINT32 ApCount; CPU_INFO_IN_HOB *CpuInfoInHob; ApCount = CpuMpData->CpuCount - 1; - + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; if (ApCount != 0) { for (Index1 = 0; Index1 < ApCount; Index1++) { Index3 = Index1; // // Sort key is the hardware default APIC ID // - ApicId = CpuMpData->CpuData[Index1].ApicId; + ApicId = CpuInfoInHob[Index1].ApicId; for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) { - if (ApicId > CpuMpData->CpuData[Index2].ApicId) { + if (ApicId > CpuInfoInHob[Index2].ApicId) { Index3 = Index2; - ApicId = CpuMpData->CpuData[Index2].ApicId; + ApicId = CpuInfoInHob[Index2].ApicId; } } if (Index3 != Index1) { - CopyMem (&CpuData, &CpuMpData->CpuData[Index3], sizeof (CPU_AP_DATA)); + CopyMem (&CpuInfo, &CpuInfoInHob[Index3], sizeof (CPU_INFO_IN_HOB)); CopyMem ( - &CpuMpData->CpuData[Index3], - &CpuMpData->CpuData[Index1], - sizeof (CPU_AP_DATA) + &CpuInfoInHob[Index3], + &CpuInfoInHob[Index1], + sizeof (CPU_INFO_IN_HOB) ); - CopyMem (&CpuMpData->CpuData[Index1], &CpuData, sizeof (CPU_AP_DATA)); + CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB)); } } @@ -414,18 +288,11 @@ SortApicId ( // ApicId = GetInitialApicId (); for (Index1 = 0; Index1 < CpuMpData->CpuCount; Index1++) { - if (CpuMpData->CpuData[Index1].ApicId == ApicId) { + if (CpuInfoInHob[Index1].ApicId == ApicId) { CpuMpData->BspNumber = (UINT32) Index1; break; } } - - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; - for (Index1 = 0; Index1 < CpuMpData->CpuCount; Index1++) { - CpuInfoInHob[Index1].InitialApicId = CpuMpData->CpuData[Index1].InitialApicId; - CpuInfoInHob[Index1].ApicId = CpuMpData->CpuData[Index1].ApicId; - CpuInfoInHob[Index1].Health = CpuMpData->CpuData[Index1].Health; - } } } @@ -484,10 +351,13 @@ GetProcessorNumber ( { UINTN TotalProcessorNumber; UINTN Index; + CPU_INFO_IN_HOB *CpuInfoInHob; + + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; TotalProcessorNumber = CpuMpData->CpuCount; for (Index = 0; Index < TotalProcessorNumber; Index ++) { - if (CpuMpData->CpuData[Index].ApicId == GetApicId ()) { + if (CpuInfoInHob[Index].ApicId == GetApicId ()) { *ProcessorNumber = Index; return EFI_SUCCESS; } @@ -513,10 +383,6 @@ CollectProcessorCount ( CpuMpData->InitFlag = ApInitConfig; CpuMpData->X2ApicEnable = FALSE; WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL); - // - // Wait for AP task to complete and then exit. - // - MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds)); CpuMpData->InitFlag = ApInitDone; ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); // @@ -569,12 +435,16 @@ InitializeApData ( IN UINT32 BistData ) { + CPU_INFO_IN_HOB *CpuInfoInHob; + + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; + CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId (); + CpuInfoInHob[ProcessorNumber].ApicId = GetApicId (); + CpuInfoInHob[ProcessorNumber].Health = BistData; + CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE; - CpuMpData->CpuData[ProcessorNumber].Health = BistData; CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE; - CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId (); - CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId (); - if (CpuMpData->CpuData[ProcessorNumber].InitialApicId >= 0xFF) { + if (CpuInfoInHob[ProcessorNumber].InitialApicId >= 0xFF) { // // Set x2APIC mode if there are any logical processor reporting // an Initial APIC ID of 255 or greater. @@ -607,6 +477,7 @@ ApWakeupFunction ( VOID *Parameter; UINT32 BistData; volatile UINT32 *ApStartupSignalBuffer; + CPU_INFO_IN_HOB *CpuInfoInHob; // // AP finished assembly code and begin to execute C code @@ -666,6 +537,7 @@ ApWakeupFunction ( // Invoke AP function here // Procedure (Parameter); + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; if (CpuMpData->SwitchBspFlag) { // // Re-get the processor number due to BSP/AP maybe exchange in AP function @@ -677,8 +549,8 @@ ApWakeupFunction ( // // Re-get the CPU APICID and Initial APICID // - CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId (); - CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId (); + CpuInfoInHob[ProcessorNumber].ApicId = GetApicId (); + CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId (); } } SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished); @@ -826,6 +698,7 @@ WakeUpAP ( UINTN Index; CPU_AP_DATA *CpuData; BOOLEAN ResetVectorRequired; + CPU_INFO_IN_HOB *CpuInfoInHob; CpuMpData->FinishedCount = 0; ResetVectorRequired = FALSE; @@ -863,7 +736,12 @@ WakeUpAP ( // SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart); } - if (CpuMpData->InitFlag != ApInitConfig) { + if (CpuMpData->InitFlag == ApInitConfig) { + // + // Wait for all potential APs waken up in one specified period + // + MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds)); + } else { // // Wait all APs waken up if this is not the 1st broadcast of SIPI // @@ -885,8 +763,9 @@ WakeUpAP ( ASSERT (CpuMpData->InitFlag != ApInitConfig); *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL; if (ResetVectorRequired) { + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; SendInitSipiSipi ( - CpuData->ApicId, + CpuInfoInHob[ProcessorNumber].ApicId, (UINT32) ExchangeInfo->BufferStart ); } @@ -1024,7 +903,12 @@ ResetProcessorToIdleState ( CpuMpData = GetCpuMpData (); + CpuMpData->InitFlag = ApInitReconfig; WakeUpAP (CpuMpData, FALSE, ProcessorNumber, NULL, NULL); + while (CpuMpData->FinishedCount < 1) { + CpuPause (); + } + CpuMpData->InitFlag = ApInitDone; SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle); } @@ -1268,6 +1152,7 @@ MpInitLibInitialize ( } else { MaxLogicalProcessorNumber = OldCpuMpData->CpuCount; } + ASSERT (MaxLogicalProcessorNumber != 0); AsmGetAddressMap (&AddressMap); ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO); @@ -1291,7 +1176,7 @@ MpInitLibInitialize ( CpuMpData->CpuApStackSize = ApStackSize; CpuMpData->BackupBuffer = BackupBufferAddr; CpuMpData->BackupBufferSize = ApResetVectorSize; - CpuMpData->EndOfPeiFlag = FALSE; + CpuMpData->SaveRestoreFlag = FALSE; CpuMpData->WakeupBuffer = (UINTN) -1; CpuMpData->CpuCount = 1; CpuMpData->BspNumber = 0; @@ -1334,10 +1219,12 @@ MpInitLibInitialize ( MtrrGetAllMtrrs (&CpuMpData->MtrrTable); if (OldCpuMpData == NULL) { - // - // Wakeup all APs and calculate the processor count in system - // - CollectProcessorCount (CpuMpData); + if (MaxLogicalProcessorNumber > 1) { + // + // Wakeup all APs and calculate the processor count in system + // + CollectProcessorCount (CpuMpData); + } } else { // // APs have been wakeup before, just get the CPU Information @@ -1346,16 +1233,14 @@ MpInitLibInitialize ( CpuMpData->CpuCount = OldCpuMpData->CpuCount; CpuMpData->BspNumber = OldCpuMpData->BspNumber; CpuMpData->InitFlag = ApInitReconfig; - CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) OldCpuMpData->CpuInfoInHob; + CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob; + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; for (Index = 0; Index < CpuMpData->CpuCount; Index++) { InitializeSpinLock(&CpuMpData->CpuData[Index].ApLock); - CpuMpData->CpuData[Index].ApicId = CpuInfoInHob[Index].ApicId; - CpuMpData->CpuData[Index].InitialApicId = CpuInfoInHob[Index].InitialApicId; - if (CpuMpData->CpuData[Index].InitialApicId >= 255) { + if (CpuInfoInHob[Index].InitialApicId >= 255) { CpuMpData->X2ApicEnable = TRUE; } - CpuMpData->CpuData[Index].Health = CpuInfoInHob[Index].Health; - CpuMpData->CpuData[Index].CpuHealthy = (CpuMpData->CpuData[Index].Health == 0)? TRUE:FALSE; + CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0)? TRUE:FALSE; CpuMpData->CpuData[Index].ApFunction = 0; CopyMem ( &CpuMpData->CpuData[Index].VolatileRegisters, @@ -1363,19 +1248,21 @@ MpInitLibInitialize ( sizeof (CPU_VOLATILE_REGISTERS) ); } - // - // Wakeup APs to do some AP initialize sync - // - WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData); - // - // Wait for all APs finished initialization - // - while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { - CpuPause (); - } - CpuMpData->InitFlag = ApInitDone; - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - SetApState (&CpuMpData->CpuData[Index], CpuStateIdle); + if (MaxLogicalProcessorNumber > 1) { + // + // Wakeup APs to do some AP initialize sync + // + WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData); + // + // Wait for all APs finished initialization + // + while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { + CpuPause (); + } + CpuMpData->InitFlag = ApInitDone; + for (Index = 0; Index < CpuMpData->CpuCount; Index++) { + SetApState (&CpuMpData->CpuData[Index], CpuStateIdle); + } } } @@ -1414,8 +1301,10 @@ MpInitLibGetProcessorInfo ( { CPU_MP_DATA *CpuMpData; UINTN CallerNumber; + CPU_INFO_IN_HOB *CpuInfoInHob; CpuMpData = GetCpuMpData (); + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; // // Check whether caller processor is BSP @@ -1433,7 +1322,7 @@ MpInitLibGetProcessorInfo ( return EFI_NOT_FOUND; } - ProcessorInfoBuffer->ProcessorId = (UINT64) CpuMpData->CpuData[ProcessorNumber].ApicId; + ProcessorInfoBuffer->ProcessorId = (UINT64) CpuInfoInHob[ProcessorNumber].ApicId; ProcessorInfoBuffer->StatusFlag = 0; if (ProcessorNumber == CpuMpData->BspNumber) { ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT; @@ -1450,10 +1339,15 @@ MpInitLibGetProcessorInfo ( // // Get processor location information // - ExtractProcessorLocation (CpuMpData->CpuData[ProcessorNumber].ApicId, &ProcessorInfoBuffer->Location); + GetProcessorLocationByApicId ( + CpuInfoInHob[ProcessorNumber].ApicId, + &ProcessorInfoBuffer->Location.Package, + &ProcessorInfoBuffer->Location.Core, + &ProcessorInfoBuffer->Location.Thread + ); if (HealthData != NULL) { - HealthData->Uint32 = CpuMpData->CpuData[ProcessorNumber].Health; + HealthData->Uint32 = CpuInfoInHob[ProcessorNumber].Health; } return EFI_SUCCESS; @@ -1719,6 +1613,164 @@ MpInitLibGetNumberOfProcessors ( } +/** + Worker function to execute a caller provided function on all enabled APs. + + @param[in] Procedure A pointer to the function to be run on + enabled APs of the system. + @param[in] SingleThread If TRUE, then all the enabled APs execute + the function specified by Procedure one by + one, in ascending order of processor handle + number. If FALSE, then all the enabled APs + execute the function specified by Procedure + simultaneously. + @param[in] WaitEvent The event created by the caller with CreateEvent() + service. + @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for + APs to return from Procedure, either for + blocking or non-blocking mode. + @param[in] ProcedureArgument The parameter passed into Procedure for + all APs. + @param[out] FailedCpuList If all APs finish successfully, then its + content is set to NULL. If not all APs + finish before timeout expires, then its + content is set to address of the buffer + holding handle numbers of the failed APs. + + @retval EFI_SUCCESS In blocking mode, all APs have finished before + the timeout expired. + @retval EFI_SUCCESS In non-blocking mode, function has been dispatched + to all enabled APs. + @retval others Failed to Startup all APs. + +**/ +EFI_STATUS +StartupAllAPsWorker ( + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN EFI_EVENT WaitEvent OPTIONAL, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL, + OUT UINTN **FailedCpuList OPTIONAL + ) +{ + EFI_STATUS Status; + CPU_MP_DATA *CpuMpData; + UINTN ProcessorCount; + UINTN ProcessorNumber; + UINTN CallerNumber; + CPU_AP_DATA *CpuData; + BOOLEAN HasEnabledAp; + CPU_STATE ApState; + + CpuMpData = GetCpuMpData (); + + if (FailedCpuList != NULL) { + *FailedCpuList = NULL; + } + + if (CpuMpData->CpuCount == 1) { + return EFI_NOT_STARTED; + } + + if (Procedure == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether caller processor is BSP + // + MpInitLibWhoAmI (&CallerNumber); + if (CallerNumber != CpuMpData->BspNumber) { + return EFI_DEVICE_ERROR; + } + + // + // Update AP state + // + CheckAndUpdateApsStatus (); + + ProcessorCount = CpuMpData->CpuCount; + HasEnabledAp = FALSE; + // + // Check whether all enabled APs are idle. + // If any enabled AP is not idle, return EFI_NOT_READY. + // + for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) { + CpuData = &CpuMpData->CpuData[ProcessorNumber]; + if (ProcessorNumber != CpuMpData->BspNumber) { + ApState = GetApState (CpuData); + if (ApState != CpuStateDisabled) { + HasEnabledAp = TRUE; + if (ApState != CpuStateIdle) { + // + // If any enabled APs are busy, return EFI_NOT_READY. + // + return EFI_NOT_READY; + } + } + } + } + + if (!HasEnabledAp) { + // + // If no enabled AP exists, return EFI_NOT_STARTED. + // + return EFI_NOT_STARTED; + } + + CpuMpData->StartCount = 0; + for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) { + CpuData = &CpuMpData->CpuData[ProcessorNumber]; + CpuData->Waiting = FALSE; + if (ProcessorNumber != CpuMpData->BspNumber) { + if (CpuData->State == CpuStateIdle) { + // + // Mark this processor as responsible for current calling. + // + CpuData->Waiting = TRUE; + CpuMpData->StartCount++; + } + } + } + + CpuMpData->Procedure = Procedure; + CpuMpData->ProcArguments = ProcedureArgument; + CpuMpData->SingleThread = SingleThread; + CpuMpData->FinishedCount = 0; + CpuMpData->RunningCount = 0; + CpuMpData->FailedCpuList = FailedCpuList; + CpuMpData->ExpectedTime = CalculateTimeout ( + TimeoutInMicroseconds, + &CpuMpData->CurrentTime + ); + CpuMpData->TotalTime = 0; + CpuMpData->WaitEvent = WaitEvent; + + if (!SingleThread) { + WakeUpAP (CpuMpData, TRUE, 0, Procedure, ProcedureArgument); + } else { + for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) { + if (ProcessorNumber == CallerNumber) { + continue; + } + if (CpuMpData->CpuData[ProcessorNumber].Waiting) { + WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument); + break; + } + } + } + + Status = EFI_SUCCESS; + if (WaitEvent == NULL) { + do { + Status = CheckAllAPs (); + } while (Status == EFI_NOT_READY); + } + + return Status; +} + /** Worker function to let the caller get one enabled AP to execute a caller-provided function. @@ -1853,3 +1905,42 @@ GetCpuMpDataFromGuidedHob ( } return CpuMpData; } + +/** + Get available system memory below 1MB by specified size. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +BackupAndPrepareWakeupBuffer( + IN CPU_MP_DATA *CpuMpData + ) +{ + CopyMem ( + (VOID *) CpuMpData->BackupBuffer, + (VOID *) CpuMpData->WakeupBuffer, + CpuMpData->BackupBufferSize + ); + CopyMem ( + (VOID *) CpuMpData->WakeupBuffer, + (VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress, + CpuMpData->AddressMap.RendezvousFunnelSize + ); +} + +/** + Restore wakeup buffer data. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +RestoreWakeupBuffer( + IN CPU_MP_DATA *CpuMpData + ) +{ + CopyMem ( + (VOID *) CpuMpData->WakeupBuffer, + (VOID *) CpuMpData->BackupBuffer, + CpuMpData->BackupBufferSize + ); +}