X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FCpuDxe%2FCpuMp.c;h=de6c6a5c330c97fadc23df164ad0f3af98bfa0e4;hb=a7ef158b07524f9afd0cefa3180aeac0fcb6e436;hp=f3a5a24b0f6639aa9005a74eff9a54990fe532e9;hpb=1aa6bf528926f8f012a0f2a77bdf53374551a9ec;p=mirror_edk2.git diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c index f3a5a24b0f..de6c6a5c33 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.c +++ b/UefiCpuPkg/CpuDxe/CpuMp.c @@ -1,34 +1,16 @@ /** @file - CPU DXE Module. + CPU DXE Module to produce CPU MP Protocol. - Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "CpuDxe.h" #include "CpuMp.h" -UINTN gMaxLogicalProcessorNumber; -UINTN gApStackSize; -UINTN gPollInterval = 100; // 100 microseconds - -MP_SYSTEM_DATA mMpSystemData; EFI_HANDLE mMpServiceHandle = NULL; -EFI_EVENT mExitBootServicesEvent = (EFI_EVENT)NULL; - -VOID *mCommonStack = 0; -VOID *mTopOfApCommonStack = 0; -VOID *mApStackStart = 0; - -volatile BOOLEAN mAPsAlreadyInitFinished = FALSE; -volatile BOOLEAN mStopCheckAllAPsStatus = TRUE; +UINTN mNumberOfProcessors = 1; EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { GetNumberOfProcessors, @@ -40,370 +22,6 @@ EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { WhoAmI }; -/** - Get Mp Service Lock. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified processor - -**/ -VOID -GetMpSpinLock ( - IN CPU_DATA_BLOCK *CpuData - ) -{ - while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) { - CpuPause (); - } - CpuData->LockSelf = GetApicId (); -} - -/** - Release Mp Service Lock. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified processor - -**/ -VOID -ReleaseMpSpinLock ( - IN CPU_DATA_BLOCK *CpuData - ) -{ - ReleaseSpinLock (&CpuData->CpuDataLock); -} - -/** - Check whether caller processor is BSP. - - @retval TRUE the caller is BSP - @retval FALSE the caller is AP - -**/ -BOOLEAN -IsBSP ( - VOID - ) -{ - UINTN CpuIndex; - CPU_DATA_BLOCK *CpuData; - - CpuData = NULL; - - WhoAmI (&mMpServicesTemplate, &CpuIndex); - CpuData = &mMpSystemData.CpuDatas[CpuIndex]; - - return CpuData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT ? TRUE : FALSE; -} - -/** - Get the Application Processors state. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified AP - - @retval CPU_STATE the AP status - -**/ -CPU_STATE -GetApState ( - IN CPU_DATA_BLOCK *CpuData - ) -{ - CPU_STATE State; - - GetMpSpinLock (CpuData); - State = CpuData->State; - ReleaseMpSpinLock (CpuData); - - return State; -} - -/** - Set the Application Processors state. - - @param CpuData The pointer to CPU_DATA_BLOCK of specified AP - @param State The AP status - -**/ -VOID -SetApState ( - IN CPU_DATA_BLOCK *CpuData, - IN CPU_STATE State - ) -{ - GetMpSpinLock (CpuData); - CpuData->State = State; - ReleaseMpSpinLock (CpuData); -} - -/** - Set the Application Processor prepare to run a function specified - by Params. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified AP - @param Procedure A pointer to the function to be run on enabled APs of the system - @param ProcedureArgument Pointer to the optional parameter of the assigned function - -**/ -VOID -SetApProcedure ( - IN CPU_DATA_BLOCK *CpuData, - IN EFI_AP_PROCEDURE Procedure, - IN VOID *ProcedureArgument - ) -{ - GetMpSpinLock (CpuData); - CpuData->Parameter = ProcedureArgument; - CpuData->Procedure = Procedure; - ReleaseMpSpinLock (CpuData); -} - -/** - Check the Application Processors Status whether contains the Flags. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified AP - @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION - - @retval TRUE the AP status includes the StatusFlag - @retval FALSE the AP status excludes the StatusFlag - -**/ -BOOLEAN -TestCpuStatusFlag ( - IN CPU_DATA_BLOCK *CpuData, - IN UINT32 Flags - ) -{ - UINT32 Ret; - - GetMpSpinLock (CpuData); - Ret = CpuData->Info.StatusFlag & Flags; - ReleaseMpSpinLock (CpuData); - - return (BOOLEAN) (Ret != 0); -} - -/** - Bitwise-Or of the Application Processors Status with the Flags. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified AP - @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION - -**/ -VOID -CpuStatusFlagOr ( - IN CPU_DATA_BLOCK *CpuData, - IN UINT32 Flags - ) -{ - GetMpSpinLock (CpuData); - CpuData->Info.StatusFlag |= Flags; - ReleaseMpSpinLock (CpuData); -} - -/** - Bitwise-AndNot of the Application Processors Status with the Flags. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified AP - @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION - -**/ -VOID -CpuStatusFlagAndNot ( - IN CPU_DATA_BLOCK *CpuData, - IN UINT32 Flags - ) -{ - GetMpSpinLock (CpuData); - CpuData->Info.StatusFlag &= ~Flags; - ReleaseMpSpinLock (CpuData); -} - -/** - Searches for the next blocking AP. - - Search for the next AP that is put in blocking state by single-threaded StartupAllAPs(). - - @param NextNumber Pointer to the processor number of the next blocking AP. - - @retval EFI_SUCCESS The next blocking AP has been found. - @retval EFI_NOT_FOUND No blocking AP exists. - -**/ -EFI_STATUS -GetNextBlockedNumber ( - OUT UINTN *NextNumber - ) -{ - UINTN Number; - CPU_STATE CpuState; - CPU_DATA_BLOCK *CpuData; - - for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) { - CpuData = &mMpSystemData.CpuDatas[Number]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - // - // Skip BSP - // - continue; - } - - CpuState = GetApState (CpuData); - if (CpuState == CpuStateBlocked) { - *NextNumber = Number; - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - -/** - Check if the APs state are finished, and update them to idle state - by StartupAllAPs(). - -**/ -VOID -CheckAndUpdateAllAPsToIdleState ( - VOID - ) -{ - UINTN ProcessorNumber; - UINTN NextNumber; - CPU_DATA_BLOCK *CpuData; - EFI_STATUS Status; - CPU_STATE CpuState; - - for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) { - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - // - // Skip BSP - // - continue; - } - - if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - // - // Skip Disabled processors - // - continue; - } - - CpuState = GetApState (CpuData); - if (CpuState == CpuStateFinished) { - mMpSystemData.FinishCount++; - if (mMpSystemData.SingleThread) { - Status = GetNextBlockedNumber (&NextNumber); - if (!EFI_ERROR (Status)) { - SetApState (&mMpSystemData.CpuDatas[NextNumber], CpuStateReady); - SetApProcedure (&mMpSystemData.CpuDatas[NextNumber], - mMpSystemData.Procedure, - mMpSystemData.ProcedureArgument); - // - // If this AP previous state is blocked, we should - // wake up this AP by sent a SIPI. and avoid - // re-involve the sleeping state. we must call - // SetApProcedure() first. - // - ResetProcessorToIdleState (&mMpSystemData.CpuDatas[NextNumber]); - } - } - SetApState (CpuData, CpuStateIdle); - } - } -} - -/** - Check if all APs are in state CpuStateSleeping. - - Return TRUE if all APs are in the CpuStateSleeping state. Do not - check the state of the BSP or any disabled APs. - - @retval TRUE All APs are in CpuStateSleeping state. - @retval FALSE One or more APs are not in CpuStateSleeping state. - -**/ -BOOLEAN -CheckAllAPsSleeping ( - VOID - ) -{ - UINTN ProcessorNumber; - CPU_DATA_BLOCK *CpuData; - - for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) { - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - // - // Skip BSP - // - continue; - } - - if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - // - // Skip Disabled processors - // - continue; - } - - if (GetApState (CpuData) != CpuStateSleeping) { - return FALSE; - } - } - return TRUE; -} - -/** - If the timeout expires before all APs returns from Procedure, - we should forcibly terminate the executing AP and fill FailedList back - by StartupAllAPs(). - -**/ -VOID -ResetAllFailedAPs ( - VOID - ) -{ - CPU_DATA_BLOCK *CpuData; - UINTN Number; - CPU_STATE CpuState; - - if (mMpSystemData.FailedList != NULL) { - *mMpSystemData.FailedList = AllocatePool ((mMpSystemData.StartCount - mMpSystemData.FinishCount + 1) * sizeof(UINTN)); - ASSERT (*mMpSystemData.FailedList != NULL); - } - - for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) { - CpuData = &mMpSystemData.CpuDatas[Number]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - // - // Skip BSP - // - continue; - } - - if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - // - // Skip Disabled processors - // - continue; - } - - CpuState = GetApState (CpuData); - if (CpuState != CpuStateIdle && - CpuState != CpuStateSleeping) { - if (mMpSystemData.FailedList != NULL) { - (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number; - } - ResetProcessorToIdleState (CpuData); - } - } - - if (mMpSystemData.FailedList != NULL) { - (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex] = END_OF_CPU_LIST; - } -} - /** This service retrieves the number of logical processor in the platform and the number of those logical processors that are enabled on this boot. @@ -452,13 +70,10 @@ GetNumberOfProcessors ( return EFI_INVALID_PARAMETER; } - if (!IsBSP ()) { - return EFI_DEVICE_ERROR; - } - - *NumberOfProcessors = mMpSystemData.NumberOfProcessors; - *NumberOfEnabledProcessors = mMpSystemData.NumberOfEnabledProcessors; - return EFI_SUCCESS; + return MpInitLibGetNumberOfProcessors ( + NumberOfProcessors, + NumberOfEnabledProcessors + ); } /** @@ -495,20 +110,7 @@ GetProcessorInfo ( OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer ) { - if (ProcessorInfoBuffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!IsBSP ()) { - return EFI_DEVICE_ERROR; - } - - if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) { - return EFI_NOT_FOUND; - } - - CopyMem (ProcessorInfoBuffer, &mMpSystemData.CpuDatas[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION)); - return EFI_SUCCESS; + return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL); } /** @@ -659,155 +261,14 @@ StartupAllAPs ( OUT UINTN **FailedCpuList OPTIONAL ) { - EFI_STATUS Status; - CPU_DATA_BLOCK *CpuData; - UINTN Number; - CPU_STATE APInitialState; - CPU_STATE CpuState; - - CpuData = NULL; - - if (FailedCpuList != NULL) { - *FailedCpuList = NULL; - } - - if (!IsBSP ()) { - return EFI_DEVICE_ERROR; - } - - if (mMpSystemData.NumberOfProcessors == 1) { - return EFI_NOT_STARTED; - } - - if (Procedure == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // temporarily stop checkAllAPsStatus for avoid resource dead-lock. - // - mStopCheckAllAPsStatus = TRUE; - - for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) { - CpuData = &mMpSystemData.CpuDatas[Number]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - // - // Skip BSP - // - continue; - } - - if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - // - // Skip Disabled processors - // - continue; - } - - CpuState = GetApState (CpuData); - if (CpuState != CpuStateIdle && - CpuState != CpuStateSleeping) { - return EFI_NOT_READY; - } - } - - mMpSystemData.Procedure = Procedure; - mMpSystemData.ProcedureArgument = ProcedureArgument; - mMpSystemData.WaitEvent = WaitEvent; - mMpSystemData.Timeout = TimeoutInMicroseconds; - mMpSystemData.TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0); - mMpSystemData.FinishCount = 0; - mMpSystemData.StartCount = 0; - mMpSystemData.SingleThread = SingleThread; - mMpSystemData.FailedList = FailedCpuList; - mMpSystemData.FailedListIndex = 0; - APInitialState = CpuStateReady; - - for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) { - CpuData = &mMpSystemData.CpuDatas[Number]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - // - // Skip BSP - // - continue; - } - - if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - // - // Skip Disabled processors - // - continue; - } - - // - // Get APs prepared, and put failing APs into FailedCpuList - // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready - // state 1 by 1, until the previous 1 finished its task - // if not "SingleThread", all APs are put to ready state from the beginning - // - CpuState = GetApState (CpuData); - if (CpuState == CpuStateIdle || - CpuState == CpuStateSleeping) { - mMpSystemData.StartCount++; - - SetApState (CpuData, APInitialState); - - if (APInitialState == CpuStateReady) { - SetApProcedure (CpuData, Procedure, ProcedureArgument); - // - // If this AP previous state is Sleeping, we should - // wake up this AP by sent a SIPI. and avoid - // re-involve the sleeping state. we must call - // SetApProcedure() first. - // - if (CpuState == CpuStateSleeping) { - ResetProcessorToIdleState (CpuData); - } - } - - if (SingleThread) { - APInitialState = CpuStateBlocked; - } - } - } - - mStopCheckAllAPsStatus = FALSE; - - if (WaitEvent != NULL) { - // - // non blocking - // - return EFI_SUCCESS; - } - - // - // Blocking temporarily stop CheckAllAPsStatus() - // - mStopCheckAllAPsStatus = TRUE; - - while (TRUE) { - CheckAndUpdateAllAPsToIdleState (); - if (mMpSystemData.FinishCount == mMpSystemData.StartCount) { - Status = EFI_SUCCESS; - goto Done; - } - - // - // task timeout - // - if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) { - ResetAllFailedAPs(); - Status = EFI_TIMEOUT; - goto Done; - } - - gBS->Stall (gPollInterval); - mMpSystemData.Timeout -= gPollInterval; - } - -Done: - - return Status; + return MpInitLibStartupAllAPs ( + Procedure, + SingleThread, + WaitEvent, + TimeoutInMicroseconds, + ProcedureArgument, + FailedCpuList + ); } /** @@ -832,8 +293,8 @@ Done: @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. - @param[in] Procedure A pointer to the function to be run on - enabled APs of the system. See type + @param[in] Procedure A pointer to the function to be run on the + designated AP of the system. See type EFI_AP_PROCEDURE. @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the total number of logical @@ -842,13 +303,13 @@ Done: EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). @param[in] WaitEvent The event created by the caller with CreateEvent() service. If it is NULL, then execute in - blocking mode. BSP waits until all APs finish - or TimeoutInMicroseconds expires. If it's + blocking mode. BSP waits until this AP finish + or TimeoutInMicroSeconds expires. If it's not NULL, then execute in non-blocking mode. BSP requests the function specified by - Procedure to be started on all the enabled - APs, and go on executing immediately. If - all return from Procedure or TimeoutInMicroseconds + Procedure to be started on this AP, + and go on executing immediately. If this AP + return from Procedure or TimeoutInMicroSeconds expires, this event is signaled. The BSP can use the CheckEvent() or WaitForEvent() services to check the state of event. Type @@ -856,20 +317,20 @@ Done: the Unified Extensible Firmware Interface Specification. @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for - APs to return from Procedure, either for + this AP to finish this Procedure, either for blocking or non-blocking mode. Zero means infinity. If the timeout expires before - all APs return from Procedure, then Procedure - on the failed APs is terminated. All enabled - APs are available for next function assigned + this AP returns from Procedure, then Procedure + on the AP is terminated. The + AP is available for next function assigned by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() or EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If the timeout expires in blocking mode, BSP returns EFI_TIMEOUT. If the timeout expires in non-blocking mode, WaitEvent is signaled with SignalEvent(). - @param[in] ProcedureArgument The parameter passed into Procedure for - all APs. + @param[in] ProcedureArgument The parameter passed into Procedure on the + specified AP. @param[out] Finished If NULL, this parameter is ignored. In blocking mode, this parameter is ignored. In non-blocking mode, if AP returns from @@ -908,90 +369,14 @@ StartupThisAP ( OUT BOOLEAN *Finished OPTIONAL ) { - CPU_DATA_BLOCK *CpuData; - CPU_STATE CpuState; - - CpuData = NULL; - - if (Finished != NULL) { - *Finished = FALSE; - } - - if (!IsBSP ()) { - return EFI_DEVICE_ERROR; - } - - if (Procedure == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) { - return EFI_NOT_FOUND; - } - - // - // temporarily stop checkAllAPsStatus for avoid resource dead-lock. - // - mStopCheckAllAPsStatus = TRUE; - - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT) || - !TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - return EFI_INVALID_PARAMETER; - } - - CpuState = GetApState (CpuData); - if (CpuState != CpuStateIdle && - CpuState != CpuStateSleeping) { - return EFI_NOT_READY; - } - - SetApState (CpuData, CpuStateReady); - - SetApProcedure (CpuData, Procedure, ProcedureArgument); - // - // If this AP previous state is Sleeping, we should - // wake up this AP by sent a SIPI. and avoid - // re-involve the sleeping state. we must call - // SetApProcedure() first. - // - if (CpuState == CpuStateSleeping) { - ResetProcessorToIdleState (CpuData); - } - - CpuData->Timeout = TimeoutInMicroseconds; - CpuData->WaitEvent = WaitEvent; - CpuData->TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0); - CpuData->Finished = Finished; - - mStopCheckAllAPsStatus = FALSE; - - if (WaitEvent != NULL) { - // - // Non Blocking - // - return EFI_SUCCESS; - } - - // - // Blocking - // - while (TRUE) { - if (GetApState (CpuData) == CpuStateFinished) { - SetApState (CpuData, CpuStateIdle); - break; - } - - if (CpuData->TimeoutActive && CpuData->Timeout < 0) { - ResetProcessorToIdleState (CpuData); - return EFI_TIMEOUT; - } - - gBS->Stall (gPollInterval); - CpuData->Timeout -= gPollInterval; - } - - return EFI_SUCCESS; + return MpInitLibStartupThisAP ( + Procedure, + ProcessorNumber, + WaitEvent, + TimeoutInMicroseconds, + ProcedureArgument, + Finished + ); } /** @@ -1021,7 +406,7 @@ StartupThisAP ( @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this service returning. @retval EFI_UNSUPPORTED Switching the BSP is not supported. - @retval EFI_SUCCESS The calling processor is an AP. + @retval EFI_DEVICE_ERROR The calling processor is an AP. @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist. @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or @@ -1037,10 +422,7 @@ SwitchBSP ( IN BOOLEAN EnableOldBSP ) { - // - // Current always return unsupported. - // - return EFI_UNSUPPORTED; + return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP); } /** @@ -1059,8 +441,8 @@ SwitchBSP ( from this service, then EFI_UNSUPPORTED must be returned. @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. - @param[in] ProcessorNumber The handle number of AP that is to become the new - BSP. The range is from 0 to the total number of + @param[in] ProcessorNumber The handle number of AP. + The range is from 0 to the total number of logical processors minus 1. The total number of logical processors can be retrieved by EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). @@ -1093,62 +475,7 @@ EnableDisableAP ( IN UINT32 *HealthFlag OPTIONAL ) { - CPU_DATA_BLOCK *CpuData; - BOOLEAN TempStopCheckState; - CPU_STATE CpuState; - - CpuData = NULL; - TempStopCheckState = FALSE; - - if (!IsBSP ()) { - return EFI_DEVICE_ERROR; - } - - if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) { - return EFI_NOT_FOUND; - } - - // - // temporarily stop checkAllAPsStatus for initialize parameters. - // - if (!mStopCheckAllAPsStatus) { - mStopCheckAllAPsStatus = TRUE; - TempStopCheckState = TRUE; - } - - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) { - return EFI_INVALID_PARAMETER; - } - - CpuState = GetApState (CpuData); - if (CpuState != CpuStateIdle && - CpuState != CpuStateSleeping) { - return EFI_UNSUPPORTED; - } - - if (EnableAP) { - if (!(TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT))) { - mMpSystemData.NumberOfEnabledProcessors++; - } - CpuStatusFlagOr (CpuData, PROCESSOR_ENABLED_BIT); - } else { - if (TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) { - mMpSystemData.NumberOfEnabledProcessors--; - } - CpuStatusFlagAndNot (CpuData, PROCESSOR_ENABLED_BIT); - } - - if (HealthFlag != NULL) { - CpuStatusFlagAndNot (CpuData, (UINT32)~PROCESSOR_HEALTH_STATUS_BIT); - CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT)); - } - - if (TempStopCheckState) { - mStopCheckAllAPsStatus = FALSE; - } - - return EFI_SUCCESS; + return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag); } /** @@ -1164,8 +491,8 @@ EnableDisableAP ( ProcessorNumber, and EFI_SUCCESS is returned. @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. - @param[out] ProcessorNumber The handle number of AP that is to become the new - BSP. The range is from 0 to the total number of + @param[out] ProcessorNumber Pointer to the handle number of AP. + The range is from 0 to the total number of logical processors minus 1. The total number of logical processors can be retrieved by EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). @@ -1182,383 +509,7 @@ WhoAmI ( OUT UINTN *ProcessorNumber ) { - UINTN Index; - UINT32 ProcessorId; - - if (ProcessorNumber == NULL) { - return EFI_INVALID_PARAMETER; - } - - ProcessorId = GetApicId (); - for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) { - if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) { - break; - } - } - - *ProcessorNumber = Index; - return EFI_SUCCESS; -} - -/** - Terminate AP's task and set it to idle state. - - This function terminates AP's task due to timeout by sending INIT-SIPI, - and sends it to idle state. - - @param CpuData the pointer to CPU_DATA_BLOCK of specified AP - -**/ -VOID -ResetProcessorToIdleState ( - IN CPU_DATA_BLOCK *CpuData - ) -{ - ResetApStackless ((UINT32)CpuData->Info.ProcessorId); -} - -/** - Application Processors do loop routine - after switch to its own stack. - - @param Context1 A pointer to the context to pass into the function. - @param Context2 A pointer to the context to pass into the function. - -**/ -VOID -ProcessorToIdleState ( - IN VOID *Context1, OPTIONAL - IN VOID *Context2 OPTIONAL - ) -{ - UINTN ProcessorNumber; - CPU_DATA_BLOCK *CpuData; - EFI_AP_PROCEDURE Procedure; - volatile VOID *ProcedureArgument; - - AsmApDoneWithCommonStack (); - - while (!mAPsAlreadyInitFinished) { - CpuPause (); - } - - WhoAmI (&mMpServicesTemplate, &ProcessorNumber); - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - - // - // Avoid forcibly reset AP caused the AP got lock not release. - // - if (CpuData->LockSelf == (INTN) GetApicId ()) { - ReleaseSpinLock (&CpuData->CpuDataLock); - } - - // - // Avoid forcibly reset AP caused the timeout AP State is not - // updated. - // - GetMpSpinLock (CpuData); - if (CpuData->State == CpuStateBusy) { - CpuData->Procedure = NULL; - } - CpuData->State = CpuStateIdle; - ReleaseMpSpinLock (CpuData); - - while (TRUE) { - GetMpSpinLock (CpuData); - ProcedureArgument = CpuData->Parameter; - Procedure = CpuData->Procedure; - ReleaseMpSpinLock (CpuData); - - if (Procedure != NULL) { - SetApState (CpuData, CpuStateBusy); - - Procedure ((VOID*) ProcedureArgument); - - GetMpSpinLock (CpuData); - CpuData->Procedure = NULL; - CpuData->State = CpuStateFinished; - ReleaseMpSpinLock (CpuData); - } else { - // - // if no procedure to execution, we simply put AP - // into sleeping state, and waiting BSP sent SIPI. - // - GetMpSpinLock (CpuData); - if (CpuData->State == CpuStateIdle) { - CpuData->State = CpuStateSleeping; - } - ReleaseMpSpinLock (CpuData); - } - - if (GetApState (CpuData) == CpuStateSleeping) { - CpuSleep (); - } - - CpuPause (); - } - - CpuSleep (); - CpuDeadLoop (); -} - -/** - Checks AP' status periodically. - - This function is triggerred by timer perodically to check the - state of AP forStartupThisAP() executed in non-blocking mode. - - @param Event Event triggered. - @param Context Parameter passed with the event. - -**/ -VOID -EFIAPI -CheckThisAPStatus ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - CPU_DATA_BLOCK *CpuData; - CPU_STATE CpuState; - - CpuData = (CPU_DATA_BLOCK *) Context; - if (CpuData->TimeoutActive) { - CpuData->Timeout -= gPollInterval; - } - - CpuState = GetApState (CpuData); - - if (CpuState == CpuStateFinished) { - if (CpuData->Finished) { - *CpuData->Finished = TRUE; - } - SetApState (CpuData, CpuStateIdle); - goto out; - } - - if (CpuData->TimeoutActive && CpuData->Timeout < 0) { - if (CpuState != CpuStateIdle && - CpuData->Finished) { - *CpuData->Finished = FALSE; - } - ResetProcessorToIdleState (CpuData); - goto out; - } - - return; - -out: - CpuData->TimeoutActive = FALSE; - gBS->SignalEvent (CpuData->WaitEvent); - CpuData->WaitEvent = NULL; -} - -/** - Checks APs' status periodically. - - This function is triggerred by timer perodically to check the - state of APs for StartupAllAPs() executed in non-blocking mode. - - @param Event Event triggered. - @param Context Parameter passed with the event. - -**/ -VOID -EFIAPI -CheckAllAPsStatus ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - CPU_DATA_BLOCK *CpuData; - UINTN Number; - EFI_STATUS Status; - - if (mMpSystemData.TimeoutActive) { - mMpSystemData.Timeout -= gPollInterval; - } - - if (mStopCheckAllAPsStatus) { - return; - } - - // - // avoid next timer enter. - // - Status = gBS->SetTimer ( - mMpSystemData.CheckAllAPsEvent, - TimerCancel, - 0 - ); - ASSERT_EFI_ERROR (Status); - - if (mMpSystemData.WaitEvent != NULL) { - CheckAndUpdateAllAPsToIdleState (); - // - // task timeout - // - if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) { - ResetAllFailedAPs(); - // - // force exit - // - mMpSystemData.FinishCount = mMpSystemData.StartCount; - } - - if (mMpSystemData.FinishCount != mMpSystemData.StartCount) { - goto EXIT; - } - - mMpSystemData.TimeoutActive = FALSE; - gBS->SignalEvent (mMpSystemData.WaitEvent); - mMpSystemData.WaitEvent = NULL; - mStopCheckAllAPsStatus = TRUE; - - goto EXIT; - } - - // - // check each AP status for StartupThisAP - // - for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) { - CpuData = &mMpSystemData.CpuDatas[Number]; - if (CpuData->WaitEvent) { - CheckThisAPStatus (NULL, (VOID *)CpuData); - } - } - -EXIT: - Status = gBS->SetTimer ( - mMpSystemData.CheckAllAPsEvent, - TimerPeriodic, - EFI_TIMER_PERIOD_MICROSECONDS (100) - ); - ASSERT_EFI_ERROR (Status); -} - -/** - Application Processor C code entry point. - -**/ -VOID -EFIAPI -ApEntryPointInC ( - VOID - ) -{ - VOID* TopOfApStack; - UINTN ProcessorNumber; - - if (!mAPsAlreadyInitFinished) { - FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors); - TopOfApStack = (UINT8*)mApStackStart + gApStackSize; - mApStackStart = TopOfApStack; - - // - // Store the Stack address, when reset the AP, We can found the original address. - // - mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = TopOfApStack; - mMpSystemData.NumberOfProcessors++; - mMpSystemData.NumberOfEnabledProcessors++; - } else { - WhoAmI (&mMpServicesTemplate, &ProcessorNumber); - // - // Get the original stack address. - // - TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack; - } - - SwitchStack ( - (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState, - NULL, - NULL, - TopOfApStack); -} - -/** - This function is called by all processors (both BSP and AP) once and collects MP related data. - - @param Bsp TRUE if the CPU is BSP - @param ProcessorNumber The specific processor number - - @retval EFI_SUCCESS Data for the processor collected and filled in - -**/ -EFI_STATUS -FillInProcessorInformation ( - IN BOOLEAN Bsp, - IN UINTN ProcessorNumber - ) -{ - CPU_DATA_BLOCK *CpuData; - UINT32 ProcessorId; - - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - ProcessorId = GetApicId (); - CpuData->Info.ProcessorId = ProcessorId; - CpuData->Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT; - if (Bsp) { - CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT; - } - CpuData->Info.Location.Package = ProcessorId; - CpuData->Info.Location.Core = 0; - CpuData->Info.Location.Thread = 0; - CpuData->State = Bsp ? CpuStateBusy : CpuStateIdle; - - CpuData->Procedure = NULL; - CpuData->Parameter = NULL; - InitializeSpinLock (&CpuData->CpuDataLock); - CpuData->LockSelf = -1; - - return EFI_SUCCESS; -} - -/** - Prepare the System Data. - - @retval EFI_SUCCESS the System Data finished initilization. - -**/ -EFI_STATUS -InitMpSystemData ( - VOID - ) -{ - EFI_STATUS Status; - - ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA)); - - mMpSystemData.NumberOfProcessors = 1; - mMpSystemData.NumberOfEnabledProcessors = 1; - - mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber); - ASSERT(mMpSystemData.CpuDatas != NULL); - - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - CheckAllAPsStatus, - NULL, - &mMpSystemData.CheckAllAPsEvent - ); - ASSERT_EFI_ERROR (Status); - - // - // Set timer to check all APs status. - // - Status = gBS->SetTimer ( - mMpSystemData.CheckAllAPsEvent, - TimerPeriodic, - EFI_TIMER_PERIOD_MICROSECONDS (100) - ); - ASSERT_EFI_ERROR (Status); - - // - // BSP - // - FillInProcessorInformation (TRUE, 0); - - return EFI_SUCCESS; + return MpInitLibWhoAmI (ProcessorNumber);; } /** @@ -1580,8 +531,9 @@ CollectBistDataFromHob ( EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance; EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance; UINTN ProcessorNumber; - UINT32 InitialLocalApicId; - CPU_DATA_BLOCK *CpuData; + EFI_PROCESSOR_INFORMATION ProcessorInfo; + EFI_HEALTH_FLAGS BistData; + UINTN CpuInstanceNumber; SecPlatformInformation2 = NULL; SecPlatformInformation = NULL; @@ -1613,7 +565,7 @@ CollectBistDataFromHob ( BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32; CpuInstance = &BspCpuInstance; } else { - DEBUG ((EFI_D_INFO, "Does not find any HOB stored CPU BIST information!\n")); + DEBUG ((DEBUG_INFO, "Does not find any HOB stored CPU BIST information!\n")); // // Does not find any HOB stored BIST information // @@ -1621,127 +573,266 @@ CollectBistDataFromHob ( } } - while ((NumberOfData--) > 0) { - for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) { - CpuData = &mMpSystemData.CpuDatas[ProcessorNumber]; - InitialLocalApicId = (UINT32) CpuData->Info.ProcessorId; - if (InitialLocalApicId == CpuInstance[NumberOfData].CpuLocation) { + for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) { + MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData); + for (CpuInstanceNumber = 0; CpuInstanceNumber < NumberOfData; CpuInstanceNumber++) { + if (ProcessorInfo.ProcessorId == CpuInstance[CpuInstanceNumber].CpuLocation) { // // Update CPU health status for MP Services Protocol according to BIST data. // - if (CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags.Uint32 != 0) { - CpuData->Info.StatusFlag &= ~PROCESSOR_HEALTH_STATUS_BIT; - // - // Report Status Code that self test is failed - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MAJOR, - (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST) - ); - } + BistData = CpuInstance[CpuInstanceNumber].InfoRecord.IA32HealthFlags; } } + if (BistData.Uint32 != 0) { + // + // Report Status Code that self test is failed + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MAJOR, + (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST) + ); + } } } /** - Callback function for ExitBootServices. + Get GDT register value. + + This function is mainly for AP purpose because AP may have different GDT + table than BSP. - @param Event Event whose notification function is being invoked. - @param Context The pointer to the notification function's context, - which is implementation-dependent. + @param[in,out] Buffer The pointer to private data buffer. **/ VOID EFIAPI -ExitBootServicesCallback ( - IN EFI_EVENT Event, - IN VOID *Context +GetGdtr ( + IN OUT VOID *Buffer ) { + AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer); +} + +/** + Initializes CPU exceptions handlers for the sake of stack switch requirement. + + This function is a wrapper of InitializeCpuExceptionHandlersEx. It's mainly + for the sake of AP's init because of EFI_AP_PROCEDURE API requirement. + + @param[in,out] Buffer The pointer to private data buffer. + +**/ +VOID +EFIAPI +InitializeExceptionStackSwitchHandlers ( + IN OUT VOID *Buffer + ) +{ + CPU_EXCEPTION_INIT_DATA *EssData; + IA32_DESCRIPTOR Idtr; + EFI_STATUS Status; + + EssData = Buffer; // - // Avoid APs access invalid buff datas which allocated by BootServices, - // so we send INIT IPI to APs to let them wait for SIPI state. + // We don't plan to replace IDT table with a new one, but we should not assume + // the AP's IDT is the same as BSP's IDT either. // - SendInitIpiAllExcludingSelf (); + AsmReadIdtr (&Idtr); + EssData->Ia32.IdtTable = (VOID *)Idtr.Base; + EssData->Ia32.IdtTableSize = Idtr.Limit + 1; + Status = InitializeCpuExceptionHandlersEx (NULL, EssData); + ASSERT_EFI_ERROR (Status); } /** - Initialize Multi-processor support. + Initializes MP exceptions handlers for the sake of stack switch requirement. + + This function will allocate required resources required to setup stack switch + and pass them through CPU_EXCEPTION_INIT_DATA to each logic processor. **/ VOID -InitializeMpSupport ( +InitializeMpExceptionStackSwitchHandlers ( VOID ) { - EFI_STATUS Status; - UINTN Timeout; + UINTN Index; + UINTN Bsp; + UINTN ExceptionNumber; + UINTN OldGdtSize; + UINTN NewGdtSize; + UINTN NewStackSize; + IA32_DESCRIPTOR Gdtr; + CPU_EXCEPTION_INIT_DATA EssData; + UINT8 *GdtBuffer; + UINT8 *StackTop; - gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber); - if (gMaxLogicalProcessorNumber < 1) { - DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n")); - return; - } + ExceptionNumber = FixedPcdGetSize (PcdCpuStackSwitchExceptionList); + NewStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize) * ExceptionNumber; + StackTop = AllocateRuntimeZeroPool (NewStackSize * mNumberOfProcessors); + ASSERT (StackTop != NULL); + StackTop += NewStackSize * mNumberOfProcessors; + // + // The default exception handlers must have been initialized. Let's just skip + // it in this method. + // + EssData.Ia32.Revision = CPU_EXCEPTION_INIT_DATA_REV; + EssData.Ia32.InitDefaultHandlers = FALSE; - InitMpSystemData (); + EssData.Ia32.StackSwitchExceptions = FixedPcdGetPtr(PcdCpuStackSwitchExceptionList); + EssData.Ia32.StackSwitchExceptionNumber = ExceptionNumber; + EssData.Ia32.KnownGoodStackSize = FixedPcdGet32(PcdCpuKnownGoodStackSize); // - // Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1 + // Initialize Gdtr to suppress incorrect compiler/analyzer warnings. // - if (gMaxLogicalProcessorNumber > 1) { - - gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize); - ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0); + Gdtr.Base = 0; + Gdtr.Limit = 0; + MpInitLibWhoAmI (&Bsp); + for (Index = 0; Index < mNumberOfProcessors; ++Index) { + // + // To support stack switch, we need to re-construct GDT but not IDT. + // + if (Index == Bsp) { + GetGdtr (&Gdtr); + } else { + // + // AP might have different size of GDT from BSP. + // + MpInitLibStartupThisAP (GetGdtr, Index, NULL, 0, (VOID *)&Gdtr, NULL); + } - mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize)); - ASSERT (mApStackStart != NULL); + // + // X64 needs only one TSS of current task working for all exceptions + // because of its IST feature. IA32 needs one TSS for each exception + // in addition to current task. Since AP is not supposed to allocate + // memory, we have to do it in BSP. To simplify the code, we allocate + // memory for IA32 case to cover both IA32 and X64 exception stack + // switch. + // + // Layout of memory to allocate for each processor: + // -------------------------------- + // | Alignment | (just in case) + // -------------------------------- + // | | + // | Original GDT | + // | | + // -------------------------------- + // | Current task descriptor | + // -------------------------------- + // | | + // | Exception task descriptors | X ExceptionNumber + // | | + // -------------------------------- + // | Current task-state segment | + // -------------------------------- + // | | + // | Exception task-state segment | X ExceptionNumber + // | | + // -------------------------------- + // + OldGdtSize = Gdtr.Limit + 1; + EssData.Ia32.ExceptionTssDescSize = sizeof (IA32_TSS_DESCRIPTOR) * + (ExceptionNumber + 1); + EssData.Ia32.ExceptionTssSize = sizeof (IA32_TASK_STATE_SEGMENT) * + (ExceptionNumber + 1); + NewGdtSize = sizeof (IA32_TSS_DESCRIPTOR) + + OldGdtSize + + EssData.Ia32.ExceptionTssDescSize + + EssData.Ia32.ExceptionTssSize; + + GdtBuffer = AllocateRuntimeZeroPool (NewGdtSize); + ASSERT (GdtBuffer != NULL); // - // the first buffer of stack size used for common stack, when the amount of AP - // more than 1, we should never free the common stack which maybe used for AP reset. + // Make sure GDT table alignment // - mCommonStack = mApStackStart; - mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize; - mApStackStart = mTopOfApCommonStack; + EssData.Ia32.GdtTable = ALIGN_POINTER(GdtBuffer, sizeof (IA32_TSS_DESCRIPTOR)); + NewGdtSize -= ((UINT8 *)EssData.Ia32.GdtTable - GdtBuffer); + EssData.Ia32.GdtTableSize = NewGdtSize; + + EssData.Ia32.ExceptionTssDesc = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize); + EssData.Ia32.ExceptionTss = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize + + EssData.Ia32.ExceptionTssDescSize); + + EssData.Ia32.KnownGoodStackTop = (UINTN)StackTop; + DEBUG ((DEBUG_INFO, + "Exception stack top[cpu%lu]: 0x%lX\n", + (UINT64)(UINTN)Index, + (UINT64)(UINTN)StackTop)); + + if (Index == Bsp) { + InitializeExceptionStackSwitchHandlers (&EssData); + } else { + MpInitLibStartupThisAP ( + InitializeExceptionStackSwitchHandlers, + Index, + NULL, + 0, + (VOID *)&EssData, + NULL + ); + } - PrepareAPStartupCode (); + StackTop -= NewStackSize; + } +} - StartApsStackless (); +/** + Initializes MP exceptions handlers for special features, such as Heap Guard + and Stack Guard. +**/ +VOID +InitializeMpExceptionHandlers ( + VOID + ) +{ + // + // Enable non-stop mode for #PF triggered by Heap Guard or NULL Pointer + // Detection. + // + if (HEAP_GUARD_NONSTOP_MODE || NULL_DETECTION_NONSTOP_MODE) { + RegisterCpuInterruptHandler (EXCEPT_IA32_DEBUG, DebugExceptionHandler); + RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT, PageFaultExceptionHandler); } - DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mMpSystemData.NumberOfProcessors)); - if (mMpSystemData.NumberOfProcessors == 1) { - FreeApStartupCode (); - if (mCommonStack != NULL) { - FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize)); - } + // + // Setup stack switch for Stack Guard feature. + // + if (PcdGetBool (PcdCpuStackGuard)) { + InitializeMpExceptionStackSwitchHandlers (); } +} - mMpSystemData.CpuDatas = ReallocatePool ( - sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber, - sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors, - mMpSystemData.CpuDatas); +/** + Initialize Multi-processor support. + +**/ +VOID +InitializeMpSupport ( + VOID + ) +{ + EFI_STATUS Status; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; // - // Release all APs to complete initialization and enter idle loop + // Wakeup APs to do initialization // - mAPsAlreadyInitFinished = TRUE; + Status = MpInitLibInitialize (); + ASSERT_EFI_ERROR (Status); + + MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors); + mNumberOfProcessors = NumberOfProcessors; + DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mNumberOfProcessors)); // - // Wait for all APs to enter idle loop. + // Initialize special exception handlers for each logic processor. // - Timeout = 0; - do { - if (CheckAllAPsSleeping ()) { - break; - } - gBS->Stall (gPollInterval); - Timeout += gPollInterval; - } while (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)); - ASSERT (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)); + InitializeMpExceptionHandlers (); // // Update CPU healthy information from Guided HOB @@ -1754,21 +845,5 @@ InitializeMpSupport ( NULL ); ASSERT_EFI_ERROR (Status); - - if (mMpSystemData.NumberOfProcessors > 1 && mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) { - if (mApStackStart != NULL) { - FreePages (mApStackStart, EFI_SIZE_TO_PAGES ( - (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) * - gApStackSize)); - } - } - - Status = gBS->CreateEvent ( - EVT_SIGNAL_EXIT_BOOT_SERVICES, - TPL_CALLBACK, - ExitBootServicesCallback, - NULL, - &mExitBootServicesEvent - ); - ASSERT_EFI_ERROR (Status); } +