/** Do sync on APs. @param[in, out] Buffer Pointer to private data buffer. **/ VOID EFIAPI RelocateApLoop ( IN OUT VOID *Buffer ) { CPU_MP_DATA *CpuMpData; BOOLEAN MwaitSupport; ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; UINTN ProcessorNumber; MpInitLibWhoAmI (&ProcessorNumber); CpuMpData = GetCpuMpData (); MwaitSupport = IsMwaitSupport (); AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc; AsmRelocateApLoopFunc ( MwaitSupport, CpuMpData->ApTargetCState, CpuMpData->PmCodeSegment, mReservedTopOfApStack - ProcessorNumber * AP_SAFE_STACK_SIZE, (UINTN) &mNumberToFinish ); // // It should never reach here // ASSERT (FALSE); }
/** Notify function on End Of PEI PPI. On S3 boot, this function will restore wakeup buffer data. On normal boot, this function will flag wakeup buffer to be un-used type. @param[in] PeiServices The pointer to the PEI Services Table. @param[in] NotifyDescriptor Address of the notification descriptor data structure. @param[in] Ppi Address of the PPI that was installed. @retval EFI_SUCCESS When everything is OK. **/ EFI_STATUS EFIAPI CpuMpEndOfPeiCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; CPU_MP_DATA *CpuMpData; EFI_PEI_HOB_POINTERS Hob; EFI_HOB_MEMORY_ALLOCATION *MemoryHob; DEBUG ((DEBUG_INFO, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n")); Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); CpuMpData = GetCpuMpData (); if (BootMode != BOOT_ON_S3_RESUME) { // // Get the HOB list for processing // Hob.Raw = GetHobList (); // // Collect memory ranges // while (!END_OF_HOB_LIST (Hob)) { if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { MemoryHob = Hob.MemoryAllocation; if (MemoryHob->AllocDescriptor.MemoryBaseAddress == CpuMpData->WakeupBuffer) { // // Flag this HOB type to un-used // GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED; break; } } Hob.Raw = GET_NEXT_HOB (Hob); } } else { CpuMpData->SaveRestoreFlag = TRUE; RestoreWakeupBuffer (CpuMpData); } return EFI_SUCCESS; }
/** Callback function for ExitBootServices. @param[in] Event Event whose notification function is being invoked. @param[in] Context The pointer to the notification function's context, which is implementation-dependent. **/ VOID EFIAPI MpInitChangeApLoopCallback ( IN EFI_EVENT Event, IN VOID *Context ) { CPU_MP_DATA *CpuMpData; CpuMpData = GetCpuMpData (); CpuMpData->PmCodeSegment = GetProtectedModeCS (); CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); mNumberToFinish = CpuMpData->CpuCount - 1; WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); while (mNumberToFinish > 0) { CpuPause (); } DEBUG ((DEBUG_INFO, "%a() done!\n", __FUNCTION__)); }
/** Checks APs status and updates APs status if needed. **/ VOID CheckAndUpdateApsStatus ( VOID ) { UINTN ProcessorNumber; EFI_STATUS Status; CPU_MP_DATA *CpuMpData; CpuMpData = GetCpuMpData (); // // First, check whether pending StartupAllAPs() exists. // if (CpuMpData->WaitEvent != NULL) { Status = CheckAllAPs (); // // If all APs finish for StartupAllAPs(), signal the WaitEvent for it. // if (Status != EFI_NOT_READY) { Status = gBS->SignalEvent (CpuMpData->WaitEvent); CpuMpData->WaitEvent = NULL; } } // // Second, check whether pending StartupThisAPs() callings exist. // for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) { if (CpuMpData->CpuData[ProcessorNumber].WaitEvent == NULL) { continue; } Status = CheckThisAP (ProcessorNumber); if (Status != EFI_NOT_READY) { gBS->SignalEvent (CpuMpData->CpuData[ProcessorNumber].WaitEvent); CpuMpData->CpuData[ProcessorNumber].WaitEvent = NULL; } } }
/** S3 SMM Init Done notification function. @param PeiServices Indirect reference to the PEI Services Table. @param NotifyDesc Address of the notification descriptor data structure. @param InvokePpi Address of the PPI that was invoked. @retval EFI_SUCCESS The function completes successfully. **/ EFI_STATUS EFIAPI NotifyOnS3SmmInitDonePpi ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, IN VOID *InvokePpi ) { CPU_MP_DATA *CpuMpData; CpuMpData = GetCpuMpData (); // // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode. // So in this notify function, code need to check the current loop // mode, if it is not HLT mode, code need to change loop mode back // to the original mode. // if (CpuMpData->ApLoopMode != ApInHltLoop) { CpuMpData->WakeUpByInitSipiSipi = TRUE; } return EFI_SUCCESS; }