- PEI_CPU_MP_DATA *PeiCpuMpData;\r
- UINTN ProcessorNumber;\r
- EFI_AP_PROCEDURE Procedure;\r
- UINTN BistData;\r
- volatile UINT32 *ApStartupSignalBuffer;\r
-\r
- PeiCpuMpData = ExchangeInfo->PeiCpuMpData;\r
- while (TRUE) {\r
- if (PeiCpuMpData->InitFlag) {\r
- ProcessorNumber = NumApsExecuting;\r
- //\r
- // Sync BSP's Control registers to APs\r
- //\r
- RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters, FALSE);\r
- //\r
- // This is first time AP wakeup, get BIST information from AP stack\r
- //\r
- BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));\r
- PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;\r
- PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();\r
- if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {\r
- //\r
- // Set x2APIC mode if there are any logical processor reporting\r
- // an APIC ID of 255 or greater.\r
- //\r
- AcquireSpinLock(&PeiCpuMpData->MpLock);\r
- PeiCpuMpData->X2ApicEnable = TRUE;\r
- ReleaseSpinLock(&PeiCpuMpData->MpLock);\r
- }\r
- //\r
- // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.\r
- //\r
- MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);\r
- MicrocodeDetect ();\r
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
- } else {\r
- //\r
- // Execute AP function if AP is not disabled\r
- //\r
- GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);\r
- if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {\r
- //\r
- // Restore AP's volatile registers saved\r
- //\r
- RestoreVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);\r
- }\r
-\r
- if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&\r
- (PeiCpuMpData->ApFunction != 0)) {\r
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;\r
- Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;\r
- //\r
- // Invoke AP function here\r
- //\r
- Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);\r
- //\r
- // Re-get the processor number due to BSP/AP maybe exchange in AP function\r
- //\r
- GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);\r
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
- }\r
- }\r
-\r
- //\r
- // AP finished executing C code\r
- //\r
- InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);\r
-\r
- //\r
- // Place AP is specified loop mode\r
- //\r
- if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {\r
- //\r
- // Save AP volatile registers\r
- //\r
- SaveVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);\r
- //\r
- // Place AP in Hlt-loop\r
- //\r
- while (TRUE) {\r
- DisableInterrupts ();\r
- CpuSleep ();\r
- CpuPause ();\r
- }\r
- }\r
- ApStartupSignalBuffer = PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
- while (TRUE) {\r
- DisableInterrupts ();\r
- if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {\r
- //\r
- // Place AP in Mwait-loop\r
- //\r
- AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0);\r
- if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {\r
- //\r
- // If AP start-up signal is not set, place AP into\r
- // the maximum C-state\r
- //\r
- AsmMwait (PeiCpuMpData->ApTargetCState << 4, 0);\r
- }\r
- } else if (PeiCpuMpData->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
- //\r
- // Clear AP start-up signal when AP waken up\r
- //\r
- InterlockedCompareExchange32 (\r
- (UINT32 *)ApStartupSignalBuffer,\r
- WAKEUP_AP_SIGNAL,\r
- 0\r
- );\r
- break;\r
- }\r
- }\r
- }\r