}\r
}\r
\r
+/**\r
+ Wait for AP wakeup and write AP start-up signal till AP is waken up.\r
+\r
+ @param[in] ApStartupSignalBuffer Pointer to AP wakeup signal\r
+**/\r
+VOID\r
+WaitApWakeup (\r
+ IN volatile UINT32 *ApStartupSignalBuffer\r
+ )\r
+{\r
+ //\r
+ // If AP is waken up, StartupApSignal should be cleared.\r
+ // Otherwise, write StartupApSignal again till AP waken up.\r
+ //\r
+ while (InterlockedCompareExchange32 (\r
+ (UINT32 *) ApStartupSignalBuffer,\r
+ WAKEUP_AP_SIGNAL,\r
+ WAKEUP_AP_SIGNAL\r
+ ) != 0) {\r
+ CpuPause ();\r
+ }\r
+}\r
+\r
/**\r
This function will fill the exchange info structure.\r
\r
AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);\r
}\r
\r
+/**\r
+ This function will be called by BSP to wakeup AP.\r
+\r
+ @param[in] CpuMpData Pointer to CPU MP Data\r
+ @param[in] Broadcast TRUE: Send broadcast IPI to all APs\r
+ FALSE: Send IPI to AP by ApicId\r
+ @param[in] ProcessorNumber The handle number of specified processor\r
+ @param[in] Procedure The function to be invoked by AP\r
+ @param[in] ProcedureArgument The argument to be passed into AP function\r
+**/\r
+VOID\r
+WakeUpAP (\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ IN BOOLEAN Broadcast,\r
+ IN UINTN ProcessorNumber,\r
+ IN EFI_AP_PROCEDURE Procedure, OPTIONAL\r
+ IN VOID *ProcedureArgument OPTIONAL\r
+ )\r
+{\r
+ volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;\r
+ UINTN Index;\r
+ CPU_AP_DATA *CpuData;\r
+ BOOLEAN ResetVectorRequired;\r
+\r
+ CpuMpData->FinishedCount = 0;\r
+ ResetVectorRequired = FALSE;\r
+\r
+ if (CpuMpData->ApLoopMode == ApInHltLoop ||\r
+ CpuMpData->InitFlag != ApInitDone) {\r
+ ResetVectorRequired = TRUE;\r
+ AllocateResetVector (CpuMpData);\r
+ FillExchangeInfoData (CpuMpData);\r
+ } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) {\r
+ //\r
+ // Get AP target C-state each time when waking up AP,\r
+ // for it maybe updated by platform again\r
+ //\r
+ CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate);\r
+ }\r
+\r
+ ExchangeInfo = CpuMpData->MpCpuExchangeInfo;\r
+\r
+ if (Broadcast) {\r
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+ if (Index != CpuMpData->BspNumber) {\r
+ CpuData = &CpuMpData->CpuData[Index];\r
+ CpuData->ApFunction = (UINTN) Procedure;\r
+ CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;\r
+ SetApState (CpuData, CpuStateReady);\r
+ if (CpuMpData->InitFlag != ApInitConfig) {\r
+ *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;\r
+ }\r
+ }\r
+ }\r
+ if (ResetVectorRequired) {\r
+ //\r
+ // Wakeup all APs\r
+ //\r
+ SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);\r
+ }\r
+ if (CpuMpData->InitFlag != ApInitConfig) {\r
+ //\r
+ // Wait all APs waken up if this is not the 1st broadcast of SIPI\r
+ //\r
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
+ CpuData = &CpuMpData->CpuData[Index];\r
+ if (Index != CpuMpData->BspNumber) {\r
+ WaitApWakeup (CpuData->StartupApSignal);\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ CpuData = &CpuMpData->CpuData[ProcessorNumber];\r
+ CpuData->ApFunction = (UINTN) Procedure;\r
+ CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;\r
+ SetApState (CpuData, CpuStateReady);\r
+ //\r
+ // Wakeup specified AP\r
+ //\r
+ ASSERT (CpuMpData->InitFlag != ApInitConfig);\r
+ *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;\r
+ if (ResetVectorRequired) {\r
+ SendInitSipiSipi (\r
+ CpuData->ApicId,\r
+ (UINT32) ExchangeInfo->BufferStart\r
+ );\r
+ }\r
+ //\r
+ // Wait specified AP waken up\r
+ //\r
+ WaitApWakeup (CpuData->StartupApSignal);\r
+ }\r
+\r
+ if (ResetVectorRequired) {\r
+ FreeResetVector (CpuMpData);\r
+ }\r
+}\r
+\r
/**\r
MP Initialize Library initialization.\r
\r
IN CPU_MP_DATA *CpuMpData\r
);\r
\r
+/**\r
+ This function will be called by BSP to wakeup AP.\r
+\r
+ @param[in] CpuMpData Pointer to CPU MP Data\r
+ @param[in] Broadcast TRUE: Send broadcast IPI to all APs\r
+ FALSE: Send IPI to AP by ApicId\r
+ @param[in] ProcessorNumber The handle number of specified processor\r
+ @param[in] Procedure The function to be invoked by AP\r
+ @param[in] ProcedureArgument The argument to be passed into AP function\r
+**/\r
+VOID\r
+WakeUpAP (\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ IN BOOLEAN Broadcast,\r
+ IN UINTN ProcessorNumber,\r
+ IN EFI_AP_PROCEDURE Procedure, OPTIONAL\r
+ IN VOID *ProcedureArgument OPTIONAL\r
+ );\r
+\r
/**\r
Initialize global data for MP support.\r
\r