\r
return ApLoopMode;\r
}\r
+\r
+/**\r
+ Do sync on APs.\r
+\r
+ @param[in, out] Buffer Pointer to private data buffer.\r
+**/\r
+VOID\r
+EFIAPI\r
+ApInitializeSync (\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ CPU_MP_DATA *CpuMpData;\r
+\r
+ CpuMpData = (CPU_MP_DATA *) Buffer;\r
+ //\r
+ // Sync BSP's MTRR table to AP\r
+ //\r
+ MtrrSetAllMtrrs (&CpuMpData->MtrrTable);\r
+ //\r
+ // Load microcode on AP\r
+ //\r
+ MicrocodeDetect (CpuMpData);\r
+}\r
+\r
+/**\r
+ Find the current Processor number by APIC ID.\r
+\r
+ @param[in] CpuMpData Pointer to PEI CPU MP Data\r
+ @param[in] ProcessorNumber Return the pocessor number found\r
+\r
+ @retval EFI_SUCCESS ProcessorNumber is found and returned.\r
+ @retval EFI_NOT_FOUND ProcessorNumber is not found.\r
+**/\r
+EFI_STATUS\r
+GetProcessorNumber (\r
+ IN CPU_MP_DATA *CpuMpData,\r
+ OUT UINTN *ProcessorNumber\r
+ )\r
+{\r
+ UINTN TotalProcessorNumber;\r
+ UINTN Index;\r
+\r
+ TotalProcessorNumber = CpuMpData->CpuCount;\r
+ for (Index = 0; Index < TotalProcessorNumber; Index ++) {\r
+ if (CpuMpData->CpuData[Index].ApicId == GetApicId ()) {\r
+ *ProcessorNumber = Index;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
/*\r
Initialize CPU AP Data when AP is wakeup at the first time.\r
\r
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);\r
}\r
\r
+/**\r
+ This function will be called from AP reset code if BSP uses WakeUpAP.\r
+\r
+ @param[in] ExchangeInfo Pointer to the MP exchange info buffer\r
+ @param[in] NumApsExecuting Number of current executing AP\r
+**/\r
+VOID\r
+EFIAPI\r
+ApWakeupFunction (\r
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,\r
+ IN UINTN NumApsExecuting\r
+ )\r
+{\r
+ CPU_MP_DATA *CpuMpData;\r
+ UINTN ProcessorNumber;\r
+ EFI_AP_PROCEDURE Procedure;\r
+ VOID *Parameter;\r
+ UINT32 BistData;\r
+ volatile UINT32 *ApStartupSignalBuffer;\r
+\r
+ //\r
+ // AP finished assembly code and begin to execute C code\r
+ //\r
+ CpuMpData = ExchangeInfo->CpuMpData;\r
+\r
+ ProgramVirtualWireMode (); \r
+\r
+ while (TRUE) {\r
+ if (CpuMpData->InitFlag == ApInitConfig) {\r
+ //\r
+ // Add CPU number\r
+ //\r
+ InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);\r
+ ProcessorNumber = NumApsExecuting;\r
+ //\r
+ // This is first time AP wakeup, get BIST information from AP stack\r
+ //\r
+ BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN));\r
+ //\r
+ // Do some AP initialize sync\r
+ //\r
+ ApInitializeSync (CpuMpData);\r
+ //\r
+ // Sync BSP's Control registers to APs\r
+ //\r
+ RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);\r
+ InitializeApData (CpuMpData, ProcessorNumber, BistData);\r
+ ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
+ } else {\r
+ //\r
+ // Execute AP function if AP is ready\r
+ //\r
+ GetProcessorNumber (CpuMpData, &ProcessorNumber);\r
+ //\r
+ // Clear AP start-up signal when AP waken up\r
+ //\r
+ ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
+ InterlockedCompareExchange32 (\r
+ (UINT32 *) ApStartupSignalBuffer,\r
+ WAKEUP_AP_SIGNAL,\r
+ 0\r
+ );\r
+ if (CpuMpData->ApLoopMode == ApInHltLoop) {\r
+ //\r
+ // Restore AP's volatile registers saved\r
+ //\r
+ RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);\r
+ }\r
+\r
+ if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {\r
+ Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;\r
+ Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;\r
+ if (Procedure != NULL) {\r
+ SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);\r
+ //\r
+ // Invoke AP function here\r
+ //\r
+ Procedure (Parameter);\r
+ //\r
+ // Re-get the CPU APICID and Initial APICID\r
+ //\r
+ CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();\r
+ CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+ }\r
+ SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);\r
+ }\r
+ }\r
+\r
+ //\r
+ // AP finished executing C code\r
+ //\r
+ InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);\r
+\r
+ //\r
+ // Place AP is specified loop mode\r
+ //\r
+ if (CpuMpData->ApLoopMode == ApInHltLoop) {\r
+ //\r
+ // Save AP volatile registers\r
+ //\r
+ SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);\r
+ //\r
+ // Place AP in HLT-loop\r
+ //\r
+ while (TRUE) {\r
+ DisableInterrupts ();\r
+ CpuSleep ();\r
+ CpuPause ();\r
+ }\r
+ }\r
+ while (TRUE) {\r
+ DisableInterrupts ();\r
+ if (CpuMpData->ApLoopMode == ApInMwaitLoop) {\r
+ //\r
+ // Place AP in MWAIT-loop\r
+ //\r
+ AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0);\r
+ if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {\r
+ //\r
+ // Check AP start-up signal again.\r
+ // If AP start-up signal is not set, place AP into\r
+ // the specified C-state\r
+ //\r
+ AsmMwait (CpuMpData->ApTargetCState << 4, 0);\r
+ }\r
+ } else if (CpuMpData->ApLoopMode == ApInRunLoop) {\r
+ //\r
+ // Place AP in Run-loop\r
+ //\r
+ CpuPause ();\r
+ } else {\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ //\r
+ // If AP start-up signal is written, AP is waken up\r
+ // otherwise place AP in loop again\r
+ //\r
+ if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
/**\r
MP Initialize Library initialization.\r
\r