- UINTN Index;\r
- UINT32 ProcessorId;\r
-\r
- if (ProcessorNumber == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- ProcessorId = GetApicId ();\r
- for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) {\r
- if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) {\r
- break;\r
- }\r
- }\r
-\r
- *ProcessorNumber = Index;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Terminate AP's task and set it to idle state.\r
-\r
- This function terminates AP's task due to timeout by sending INIT-SIPI,\r
- and sends it to idle state.\r
-\r
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
-\r
-**/\r
-VOID\r
-ResetProcessorToIdleState (\r
- IN CPU_DATA_BLOCK *CpuData\r
- )\r
-{\r
- ResetApStackless ((UINT32)CpuData->Info.ProcessorId);\r
-}\r
-\r
-/**\r
- Application Processors do loop routine\r
- after switch to its own stack.\r
-\r
- @param Context1 A pointer to the context to pass into the function.\r
- @param Context2 A pointer to the context to pass into the function.\r
-\r
-**/\r
-VOID\r
-ProcessorToIdleState (\r
- IN VOID *Context1, OPTIONAL\r
- IN VOID *Context2 OPTIONAL\r
- )\r
-{\r
- UINTN ProcessorNumber;\r
- CPU_DATA_BLOCK *CpuData;\r
- EFI_AP_PROCEDURE Procedure;\r
- volatile VOID *ProcedureArgument;\r
-\r
- AsmApDoneWithCommonStack ();\r
-\r
- while (!mAPsAlreadyInitFinished) {\r
- CpuPause ();\r
- }\r
-\r
- WhoAmI (&mMpServicesTemplate, &ProcessorNumber);\r
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
-\r
- //\r
- // Avoid forcibly reset AP caused the AP got lock not release.\r
- //\r
- if (CpuData->LockSelf == (INTN) GetApicId ()) {\r
- ReleaseSpinLock (&CpuData->CpuDataLock);\r
- }\r
-\r
- //\r
- // Avoid forcibly reset AP caused the timeout AP State is not\r
- // updated.\r
- //\r
- GetMpSpinLock (CpuData);\r
- if (CpuData->State == CpuStateBusy) {\r
- CpuData->Procedure = NULL;\r
- }\r
- CpuData->State = CpuStateIdle;\r
- ReleaseMpSpinLock (CpuData);\r
-\r
- while (TRUE) {\r
- GetMpSpinLock (CpuData);\r
- ProcedureArgument = CpuData->Parameter;\r
- Procedure = CpuData->Procedure;\r
- ReleaseMpSpinLock (CpuData);\r
-\r
- if (Procedure != NULL) {\r
- SetApState (CpuData, CpuStateBusy);\r
-\r
- Procedure ((VOID*) ProcedureArgument);\r
-\r
- GetMpSpinLock (CpuData);\r
- CpuData->Procedure = NULL;\r
- CpuData->State = CpuStateFinished;\r
- ReleaseMpSpinLock (CpuData);\r
- } else {\r
- //\r
- // if no procedure to execution, we simply put AP\r
- // into sleeping state, and waiting BSP sent SIPI.\r
- //\r
- GetMpSpinLock (CpuData);\r
- if (CpuData->State == CpuStateIdle) {\r
- CpuData->State = CpuStateSleeping;\r
- }\r
- ReleaseMpSpinLock (CpuData);\r
- }\r
-\r
- if (GetApState (CpuData) == CpuStateSleeping) {\r
- CpuSleep ();\r
- }\r
-\r
- CpuPause ();\r
- }\r
-\r
- CpuSleep ();\r
- CpuDeadLoop ();\r
-}\r
-\r
-/**\r
- Checks AP' status periodically.\r
-\r
- This function is triggerred by timer perodically to check the\r
- state of AP forStartupThisAP() executed in non-blocking mode.\r
-\r
- @param Event Event triggered.\r
- @param Context Parameter passed with the event.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CheckThisAPStatus (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- CPU_DATA_BLOCK *CpuData;\r
- CPU_STATE CpuState;\r
-\r
- CpuData = (CPU_DATA_BLOCK *) Context;\r
- if (CpuData->TimeoutActive) {\r
- CpuData->Timeout -= gPollInterval;\r
- }\r
-\r
- CpuState = GetApState (CpuData);\r
-\r
- if (CpuState == CpuStateFinished) {\r
- if (CpuData->Finished) {\r
- *CpuData->Finished = TRUE;\r
- }\r
- SetApState (CpuData, CpuStateIdle);\r
- goto out;\r
- }\r
-\r
- if (CpuData->TimeoutActive && CpuData->Timeout < 0) {\r
- if (CpuState != CpuStateIdle &&\r
- CpuData->Finished) {\r
- *CpuData->Finished = FALSE;\r
- }\r
- ResetProcessorToIdleState (CpuData);\r
- goto out;\r
- }\r
-\r
- return;\r
-\r
-out:\r
- CpuData->TimeoutActive = FALSE;\r
- gBS->SignalEvent (CpuData->WaitEvent);\r
- CpuData->WaitEvent = NULL;\r
-}\r
-\r
-/**\r
- Checks APs' status periodically.\r
-\r
- This function is triggerred by timer perodically to check the\r
- state of APs for StartupAllAPs() executed in non-blocking mode.\r
-\r
- @param Event Event triggered.\r
- @param Context Parameter passed with the event.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CheckAllAPsStatus (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- CPU_DATA_BLOCK *CpuData;\r
- UINTN Number;\r
- EFI_STATUS Status;\r
-\r
- if (mMpSystemData.TimeoutActive) {\r
- mMpSystemData.Timeout -= gPollInterval;\r
- }\r
-\r
- if (mStopCheckAllAPsStatus) {\r
- return;\r
- }\r
-\r
- //\r
- // avoid next timer enter.\r
- //\r
- Status = gBS->SetTimer (\r
- mMpSystemData.CheckAllAPsEvent,\r
- TimerCancel,\r
- 0\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (mMpSystemData.WaitEvent != NULL) {\r
- CheckAndUpdateAllAPsToIdleState ();\r
- //\r
- // task timeout\r
- //\r
- if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {\r
- ResetAllFailedAPs();\r
- //\r
- // force exit\r
- //\r
- mMpSystemData.FinishCount = mMpSystemData.StartCount;\r
- }\r
-\r
- if (mMpSystemData.FinishCount != mMpSystemData.StartCount) {\r
- goto EXIT;\r
- }\r
-\r
- mMpSystemData.TimeoutActive = FALSE;\r
- gBS->SignalEvent (mMpSystemData.WaitEvent);\r
- mMpSystemData.WaitEvent = NULL;\r
- mStopCheckAllAPsStatus = TRUE;\r
-\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // check each AP status for StartupThisAP\r
- //\r
- for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
- CpuData = &mMpSystemData.CpuDatas[Number];\r
- if (CpuData->WaitEvent) {\r
- CheckThisAPStatus (NULL, (VOID *)CpuData);\r
- }\r
- }\r
-\r
-EXIT:\r
- Status = gBS->SetTimer (\r
- mMpSystemData.CheckAllAPsEvent,\r
- TimerPeriodic,\r
- EFI_TIMER_PERIOD_MICROSECONDS (100)\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-/**\r
- Application Processor C code entry point.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ApEntryPointInC (\r
- VOID\r
- )\r
-{\r
- VOID* TopOfApStack;\r
- UINTN ProcessorNumber;\r
-\r
- if (!mAPsAlreadyInitFinished) {\r
- FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);\r
- TopOfApStack = (UINT8*)mApStackStart + gApStackSize;\r
- mApStackStart = TopOfApStack;\r
-\r
- //\r
- // Store the Stack address, when reset the AP, We can found the original address.\r
- //\r
- mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = TopOfApStack;\r
- mMpSystemData.NumberOfProcessors++;\r
- mMpSystemData.NumberOfEnabledProcessors++;\r
- } else {\r
- WhoAmI (&mMpServicesTemplate, &ProcessorNumber);\r
- //\r
- // Get the original stack address.\r
- //\r
- TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack;\r
- }\r
-\r
- SwitchStack (\r
- (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,\r
- NULL,\r
- NULL,\r
- TopOfApStack);\r
-}\r
-\r
-/**\r
- This function is called by all processors (both BSP and AP) once and collects MP related data.\r
-\r
- @param Bsp TRUE if the CPU is BSP\r
- @param ProcessorNumber The specific processor number\r
-\r
- @retval EFI_SUCCESS Data for the processor collected and filled in\r
-\r
-**/\r
-EFI_STATUS\r
-FillInProcessorInformation (\r
- IN BOOLEAN Bsp,\r
- IN UINTN ProcessorNumber\r
- )\r
-{\r
- CPU_DATA_BLOCK *CpuData;\r
- UINT32 ProcessorId;\r
-\r
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
- ProcessorId = GetApicId ();\r
- CpuData->Info.ProcessorId = ProcessorId;\r
- CpuData->Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;\r
- if (Bsp) {\r
- CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;\r
- }\r
- CpuData->Info.Location.Package = ProcessorId;\r
- CpuData->Info.Location.Core = 0;\r
- CpuData->Info.Location.Thread = 0;\r
- CpuData->State = Bsp ? CpuStateBusy : CpuStateIdle;\r
-\r
- CpuData->Procedure = NULL;\r
- CpuData->Parameter = NULL;\r
- InitializeSpinLock (&CpuData->CpuDataLock);\r
- CpuData->LockSelf = -1;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Prepare the System Data.\r
-\r
- @retval EFI_SUCCESS the System Data finished initilization.\r
-\r
-**/\r
-EFI_STATUS\r
-InitMpSystemData (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));\r
-\r
- mMpSystemData.NumberOfProcessors = 1;\r
- mMpSystemData.NumberOfEnabledProcessors = 1;\r
-\r
- mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);\r
- ASSERT(mMpSystemData.CpuDatas != NULL);\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- CheckAllAPsStatus,\r
- NULL,\r
- &mMpSystemData.CheckAllAPsEvent\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Set timer to check all APs status.\r
- //\r
- Status = gBS->SetTimer (\r
- mMpSystemData.CheckAllAPsEvent,\r
- TimerPeriodic,\r
- EFI_TIMER_PERIOD_MICROSECONDS (100)\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // BSP\r
- //\r
- FillInProcessorInformation (TRUE, 0);\r
-\r
- return EFI_SUCCESS;\r