#include "CpuDxe.h"\r
#include "CpuMp.h"\r
\r
-UINTN gMaxLogicalProcessorNumber;\r
-UINTN gApStackSize;\r
-UINTN gPollInterval = 100; // 100 microseconds\r
-\r
-MP_SYSTEM_DATA mMpSystemData;\r
EFI_HANDLE mMpServiceHandle = NULL;\r
UINTN mNumberOfProcessors = 1;\r
-EFI_EVENT mExitBootServicesEvent = (EFI_EVENT)NULL;\r
-\r
-VOID *mCommonStack = 0;\r
-VOID *mTopOfApCommonStack = 0;\r
-VOID *mApStackStart = 0;\r
-\r
-volatile BOOLEAN mAPsAlreadyInitFinished = FALSE;\r
\r
EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {\r
GetNumberOfProcessors,\r
WhoAmI\r
};\r
\r
-/**\r
- Get Mp Service Lock.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified processor\r
-\r
-**/\r
-VOID\r
-GetMpSpinLock (\r
- IN CPU_DATA_BLOCK *CpuData\r
- )\r
-{\r
- while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {\r
- CpuPause ();\r
- }\r
- CpuData->LockSelf = GetApicId ();\r
-}\r
-\r
-/**\r
- Release Mp Service Lock.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified processor\r
-\r
-**/\r
-VOID\r
-ReleaseMpSpinLock (\r
- IN CPU_DATA_BLOCK *CpuData\r
- )\r
-{\r
- ReleaseSpinLock (&CpuData->CpuDataLock);\r
-}\r
-\r
-/**\r
- Check whether caller processor is BSP.\r
-\r
- @retval TRUE the caller is BSP\r
- @retval FALSE the caller is AP\r
-\r
-**/\r
-BOOLEAN\r
-IsBSP (\r
- VOID\r
- )\r
-{\r
- UINTN CpuIndex;\r
- CPU_DATA_BLOCK *CpuData;\r
-\r
- CpuData = NULL;\r
-\r
- WhoAmI (&mMpServicesTemplate, &CpuIndex);\r
- CpuData = &mMpSystemData.CpuDatas[CpuIndex];\r
-\r
- return CpuData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT ? TRUE : FALSE;\r
-}\r
-\r
-/**\r
- Get the Application Processors state.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
-\r
- @retval CPU_STATE the AP status\r
-\r
-**/\r
-STATIC\r
-CPU_STATE\r
-GetApState (\r
- IN CPU_DATA_BLOCK *CpuData\r
- )\r
-{\r
- CPU_STATE State;\r
-\r
- GetMpSpinLock (CpuData);\r
- State = CpuData->State;\r
- ReleaseMpSpinLock (CpuData);\r
-\r
- return State;\r
-}\r
-\r
-/**\r
- Set the Application Processors state.\r
-\r
- @param CpuData The pointer to CPU_DATA_BLOCK of specified AP\r
- @param State The AP status\r
-\r
-**/\r
-STATIC\r
-VOID\r
-SetApState (\r
- IN CPU_DATA_BLOCK *CpuData,\r
- IN CPU_STATE State\r
- )\r
-{\r
- GetMpSpinLock (CpuData);\r
- CpuData->State = State;\r
- ReleaseMpSpinLock (CpuData);\r
-}\r
-\r
-/**\r
- Set the Application Processor prepare to run a function specified\r
- by Params.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
- @param Procedure A pointer to the function to be run on enabled APs of the system\r
- @param ProcedureArgument Pointer to the optional parameter of the assigned function\r
-\r
-**/\r
-VOID\r
-SetApProcedure (\r
- IN CPU_DATA_BLOCK *CpuData,\r
- IN EFI_AP_PROCEDURE Procedure,\r
- IN VOID *ProcedureArgument\r
- )\r
-{\r
- GetMpSpinLock (CpuData);\r
- CpuData->Parameter = ProcedureArgument;\r
- CpuData->Procedure = Procedure;\r
- ReleaseMpSpinLock (CpuData);\r
-}\r
-\r
-/**\r
- Check the Application Processors Status whether contains the Flags.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
- @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION\r
-\r
- @retval TRUE the AP status includes the StatusFlag\r
- @retval FALSE the AP status excludes the StatusFlag\r
-\r
-**/\r
-BOOLEAN\r
-TestCpuStatusFlag (\r
- IN CPU_DATA_BLOCK *CpuData,\r
- IN UINT32 Flags\r
- )\r
-{\r
- UINT32 Ret;\r
-\r
- GetMpSpinLock (CpuData);\r
- Ret = CpuData->Info.StatusFlag & Flags;\r
- ReleaseMpSpinLock (CpuData);\r
-\r
- return (BOOLEAN) (Ret != 0);\r
-}\r
-\r
-/**\r
- Bitwise-Or of the Application Processors Status with the Flags.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
- @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION\r
-\r
-**/\r
-VOID\r
-CpuStatusFlagOr (\r
- IN CPU_DATA_BLOCK *CpuData,\r
- IN UINT32 Flags\r
- )\r
-{\r
- GetMpSpinLock (CpuData);\r
- CpuData->Info.StatusFlag |= Flags;\r
- ReleaseMpSpinLock (CpuData);\r
-}\r
-\r
-/**\r
- Bitwise-AndNot of the Application Processors Status with the Flags.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
- @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION\r
-\r
-**/\r
-VOID\r
-CpuStatusFlagAndNot (\r
- IN CPU_DATA_BLOCK *CpuData,\r
- IN UINT32 Flags\r
- )\r
-{\r
- GetMpSpinLock (CpuData);\r
- CpuData->Info.StatusFlag &= ~Flags;\r
- ReleaseMpSpinLock (CpuData);\r
-}\r
-\r
-/**\r
- Searches for the next blocking AP.\r
-\r
- Search for the next AP that is put in blocking state by single-threaded StartupAllAPs().\r
-\r
- @param NextNumber Pointer to the processor number of the next blocking AP.\r
-\r
- @retval EFI_SUCCESS The next blocking AP has been found.\r
- @retval EFI_NOT_FOUND No blocking AP exists.\r
-\r
-**/\r
-EFI_STATUS\r
-GetNextBlockedNumber (\r
- OUT UINTN *NextNumber\r
- )\r
-{\r
- UINTN Number;\r
- CPU_STATE CpuState;\r
- CPU_DATA_BLOCK *CpuData;\r
-\r
- for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
- CpuData = &mMpSystemData.CpuDatas[Number];\r
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
- //\r
- // Skip BSP\r
- //\r
- continue;\r
- }\r
-\r
- CpuState = GetApState (CpuData);\r
- if (CpuState == CpuStateBlocked) {\r
- *NextNumber = Number;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
- Check if the APs state are finished, and update them to idle state\r
- by StartupAllAPs().\r
-\r
-**/\r
-VOID\r
-CheckAndUpdateAllAPsToIdleState (\r
- VOID\r
- )\r
-{\r
- UINTN ProcessorNumber;\r
- UINTN NextNumber;\r
- CPU_DATA_BLOCK *CpuData;\r
- EFI_STATUS Status;\r
- CPU_STATE CpuState;\r
-\r
- for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {\r
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
- //\r
- // Skip BSP\r
- //\r
- continue;\r
- }\r
-\r
- if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
- //\r
- // Skip Disabled processors\r
- //\r
- continue;\r
- }\r
-\r
- CpuState = GetApState (CpuData);\r
- if (CpuState == CpuStateFinished) {\r
- mMpSystemData.FinishCount++;\r
- if (mMpSystemData.SingleThread) {\r
- Status = GetNextBlockedNumber (&NextNumber);\r
- if (!EFI_ERROR (Status)) {\r
- SetApState (&mMpSystemData.CpuDatas[NextNumber], CpuStateReady);\r
- SetApProcedure (&mMpSystemData.CpuDatas[NextNumber],\r
- mMpSystemData.Procedure,\r
- mMpSystemData.ProcedureArgument);\r
- //\r
- // If this AP previous state is blocked, we should\r
- // wake up this AP by sent a SIPI. and avoid\r
- // re-involve the sleeping state. we must call\r
- // SetApProcedure() first.\r
- //\r
- ResetProcessorToIdleState (&mMpSystemData.CpuDatas[NextNumber]);\r
- }\r
- }\r
- SetApState (CpuData, CpuStateIdle);\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Check if all APs are in state CpuStateSleeping.\r
-\r
- Return TRUE if all APs are in the CpuStateSleeping state. Do not\r
- check the state of the BSP or any disabled APs.\r
-\r
- @retval TRUE All APs are in CpuStateSleeping state.\r
- @retval FALSE One or more APs are not in CpuStateSleeping state.\r
-\r
-**/\r
-BOOLEAN\r
-CheckAllAPsSleeping (\r
- VOID\r
- )\r
-{\r
- UINTN ProcessorNumber;\r
- CPU_DATA_BLOCK *CpuData;\r
-\r
- for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {\r
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
- //\r
- // Skip BSP\r
- //\r
- continue;\r
- }\r
-\r
- if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
- //\r
- // Skip Disabled processors\r
- //\r
- continue;\r
- }\r
-\r
- if (GetApState (CpuData) != CpuStateSleeping) {\r
- return FALSE;\r
- }\r
- }\r
- return TRUE;\r
-}\r
-\r
-/**\r
- If the timeout expires before all APs returns from Procedure,\r
- we should forcibly terminate the executing AP and fill FailedList back\r
- by StartupAllAPs().\r
-\r
-**/\r
-VOID\r
-ResetAllFailedAPs (\r
- VOID\r
- )\r
-{\r
- CPU_DATA_BLOCK *CpuData;\r
- UINTN Number;\r
- CPU_STATE CpuState;\r
-\r
- if (mMpSystemData.FailedList != NULL) {\r
- *mMpSystemData.FailedList = AllocatePool ((mMpSystemData.StartCount - mMpSystemData.FinishCount + 1) * sizeof(UINTN));\r
- ASSERT (*mMpSystemData.FailedList != NULL);\r
- }\r
-\r
- for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
- CpuData = &mMpSystemData.CpuDatas[Number];\r
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
- //\r
- // Skip BSP\r
- //\r
- continue;\r
- }\r
-\r
- if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
- //\r
- // Skip Disabled processors\r
- //\r
- continue;\r
- }\r
-\r
- CpuState = GetApState (CpuData);\r
- if (CpuState != CpuStateIdle &&\r
- CpuState != CpuStateSleeping) {\r
- if (mMpSystemData.FailedList != NULL) {\r
- (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;\r
- }\r
- ResetProcessorToIdleState (CpuData);\r
- }\r
- }\r
-\r
- if (mMpSystemData.FailedList != NULL) {\r
- (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex] = END_OF_CPU_LIST;\r
- }\r
-}\r
-\r
/**\r
This service retrieves the number of logical processor in the platform\r
and the number of those logical processors that are enabled on this boot.\r
}\r
}\r
\r
-/**\r
- Callback function for ExitBootServices.\r
-\r
- @param Event Event whose notification function is being invoked.\r
- @param Context The pointer to the notification function's context,\r
- which is implementation-dependent.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ExitBootServicesCallback (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- //\r
- // Avoid APs access invalid buff datas which allocated by BootServices,\r
- // so we send INIT IPI to APs to let them wait for SIPI state.\r
- //\r
- SendInitIpiAllExcludingSelf ();\r
-}\r
-\r
/**\r
Initialize Multi-processor support.\r
\r