+/**\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