UINTN gPollInterval = 100; // 100 microseconds\r
\r
MP_SYSTEM_DATA mMpSystemData;\r
-EFI_HANDLE mMpServiceHandle = NULL;\r
+EFI_HANDLE mMpServiceHandle = NULL;\r
+EFI_EVENT mExitBootServicesEvent = (EFI_EVENT)NULL;\r
\r
VOID *mCommonStack = 0;\r
VOID *mTopOfApCommonStack = 0;\r
Ret = CpuData->Info.StatusFlag & Flags;\r
ReleaseMpSpinLock (CpuData);\r
\r
- return !!(Ret);\r
+ return (BOOLEAN) (Ret != 0);\r
}\r
\r
/**\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
-\r
SetApState (CpuData, CpuStateIdle);\r
}\r
}\r
}\r
\r
CpuState = GetApState (CpuData);\r
- if (CpuState != CpuStateIdle) {\r
+ if (CpuState != CpuStateIdle &&\r
+ CpuState != CpuStateSleeping) {\r
if (mMpSystemData.FailedList != NULL) {\r
(*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;\r
}\r
CPU_DATA_BLOCK *CpuData;\r
UINTN Number;\r
CPU_STATE APInitialState;\r
+ CPU_STATE CpuState;\r
\r
CpuData = NULL;\r
\r
continue;\r
}\r
\r
- if (GetApState (CpuData) != CpuStateIdle) {\r
+ CpuState = GetApState (CpuData);\r
+ if (CpuState != CpuStateIdle &&\r
+ CpuState != CpuStateSleeping) {\r
return EFI_NOT_READY;\r
}\r
}\r
mMpSystemData.ProcedureArgument = ProcedureArgument;\r
mMpSystemData.WaitEvent = WaitEvent;\r
mMpSystemData.Timeout = TimeoutInMicroseconds;\r
- mMpSystemData.TimeoutActive = !!(TimeoutInMicroseconds);\r
+ mMpSystemData.TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);\r
mMpSystemData.FinishCount = 0;\r
mMpSystemData.StartCount = 0;\r
mMpSystemData.SingleThread = SingleThread;\r
// state 1 by 1, until the previous 1 finished its task\r
// if not "SingleThread", all APs are put to ready state from the beginning\r
//\r
- if (GetApState (CpuData) == CpuStateIdle) {\r
+ CpuState = GetApState (CpuData);\r
+ if (CpuState == CpuStateIdle ||\r
+ CpuState == CpuStateSleeping) {\r
mMpSystemData.StartCount++;\r
\r
SetApState (CpuData, APInitialState);\r
\r
if (APInitialState == CpuStateReady) {\r
SetApProcedure (CpuData, Procedure, ProcedureArgument);\r
+ //\r
+ // If this AP previous state is Sleeping, 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
+ if (CpuState == CpuStateSleeping) {\r
+ ResetProcessorToIdleState (CpuData);\r
+ }\r
}\r
\r
if (SingleThread) {\r
)\r
{\r
CPU_DATA_BLOCK *CpuData;\r
+ CPU_STATE CpuState;\r
\r
CpuData = NULL;\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (GetApState (CpuData) != CpuStateIdle) {\r
+ CpuState = GetApState (CpuData);\r
+ if (CpuState != CpuStateIdle &&\r
+ CpuState != CpuStateSleeping) {\r
return EFI_NOT_READY;\r
}\r
\r
SetApState (CpuData, CpuStateReady);\r
\r
SetApProcedure (CpuData, Procedure, ProcedureArgument);\r
+ //\r
+ // If this AP previous state is Sleeping, 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
+ if (CpuState == CpuStateSleeping) {\r
+ ResetProcessorToIdleState (CpuData);\r
+ }\r
\r
CpuData->Timeout = TimeoutInMicroseconds;\r
CpuData->WaitEvent = WaitEvent;\r
- CpuData->TimeoutActive = !!(TimeoutInMicroseconds);\r
+ CpuData->TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);\r
CpuData->Finished = Finished;\r
\r
mStopCheckAllAPsStatus = FALSE;\r
{\r
CPU_DATA_BLOCK *CpuData;\r
BOOLEAN TempStopCheckState;\r
+ CPU_STATE CpuState;\r
\r
CpuData = NULL;\r
TempStopCheckState = FALSE;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (GetApState (CpuData) != CpuStateIdle) {\r
+ CpuState = GetApState (CpuData);\r
+ if (CpuState != CpuStateIdle &&\r
+ CpuState != CpuStateSleeping) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
UINTN ProcessorNumber;\r
CPU_DATA_BLOCK *CpuData;\r
EFI_AP_PROCEDURE Procedure;\r
- VOID *ProcedureArgument;\r
+ volatile VOID *ProcedureArgument;\r
\r
AsmApDoneWithCommonStack ();\r
\r
}\r
\r
//\r
- // Avoid forcibly reset AP caused the AP State is not updated.\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
- CpuData->Procedure = NULL;\r
ReleaseMpSpinLock (CpuData);\r
\r
while (TRUE) {\r
ReleaseMpSpinLock (CpuData);\r
\r
if (Procedure != NULL) {\r
- Procedure (ProcedureArgument);\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
CpuData->Info.Location.Package = ProcessorId;\r
CpuData->Info.Location.Core = 0;\r
CpuData->Info.Location.Thread = 0;\r
- CpuData->State = Bsp ? CpuStateBuzy : CpuStateIdle;\r
+ CpuData->State = Bsp ? CpuStateBusy : CpuStateIdle;\r
\r
CpuData->Procedure = NULL;\r
CpuData->Parameter = NULL;\r
return EFI_SUCCESS;\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
(gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *\r
gApStackSize));\r
}\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
+ TPL_CALLBACK,\r
+ ExitBootServicesCallback,\r
+ NULL,\r
+ &mExitBootServicesEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
}\r