/** The function is invoked after SMBASE relocation in S3 path to restors CPU status. The function is invoked after SMBASE relocation in S3 path. It restores configuration according to data saved by normal boot path for both BSP and APs. **/ VOID InitializeCpu ( VOID ) { CPU_REGISTER_TABLE *RegisterTableList; UINT32 InitApicId; UINTN Index; RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable; InitApicId = GetInitialApicId (); for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) { if (RegisterTableList[Index].InitialApicId == InitApicId) { SetProcessorRegister (&RegisterTableList[Index]); break; } } mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1; mExchangeInfo->ApFunction = (VOID *) (UINTN) MPRendezvousProcedure; // // Send INIT IPI - SIPI to all APs // SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector); while (mNumberToFinish > 0) { CpuPause (); } }
/** AP initialization after SMBASE relocation in the S3 boot path. **/ VOID MPRendezvousProcedure ( VOID ) { CPU_REGISTER_TABLE *RegisterTableList; UINT32 InitApicId; UINTN Index; ProgramVirtualWireMode (); DisableLvtInterrupts (); RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable; InitApicId = GetInitialApicId (); for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) { if (RegisterTableList[Index].InitialApicId == InitApicId) { SetProcessorRegister (&RegisterTableList[Index]); break; } } // // Count down the number with lock mechanism. // InterlockedDecrement (&mNumberToFinish); }
/** The function is invoked after SMBASE relocation in S3 path to restores CPU status. The function is invoked after SMBASE relocation in S3 path. It restores configuration according to data saved by normal boot path for both BSP and APs. **/ VOID InitializeCpu ( VOID ) { CPU_REGISTER_TABLE *RegisterTableList; UINT32 InitApicId; UINTN Index; RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable; InitApicId = GetInitialApicId (); for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) { if (RegisterTableList[Index].InitialApicId == InitApicId) { SetProcessorRegister (&RegisterTableList[Index]); break; } } mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1; // // StackStart was updated when APs were waken up in EarlyInitializeCpu. // Re-initialize StackAddress to original beginning address. // mExchangeInfo->StackStart = (VOID *) (UINTN) mAcpiCpuData.StackAddress; mExchangeInfo->ApFunction = (VOID *) (UINTN) MPRendezvousProcedure; // // Send INIT IPI - SIPI to all APs // SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector); while (mNumberToFinish > 0) { CpuPause (); } }
/** AP initialization before SMBASE relocation in the S3 boot path. **/ VOID EarlyMPRendezvousProcedure ( VOID ) { CPU_REGISTER_TABLE *RegisterTableList; UINT32 InitApicId; UINTN Index; LoadMtrrData (mAcpiCpuData.MtrrTable); // // Find processor number for this CPU. // RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable; InitApicId = GetInitialApicId (); for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) { if (RegisterTableList[Index].InitialApicId == InitApicId) { SetProcessorRegister (&RegisterTableList[Index]); break; } } // // Count down the number with lock mechanism. // InterlockedDecrement (&mNumberToFinish); }
/** The function is invoked before SMBASE relocation in S3 path to restores CPU status. The function is invoked before SMBASE relocation in S3 path. It does first time microcode load and restores MTRRs for both BSP and APs. **/ VOID InitializeCpuBeforeRebase ( VOID ) { LoadMtrrData (mAcpiCpuData.MtrrTable); SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus); ProgramVirtualWireMode (); PrepareApStartupVector (mAcpiCpuData.StartupVector); mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1; mExchangeInfo->ApFunction = (VOID *) (UINTN) InitializeAp; // // Execute code for before SmmBaseReloc. Note: This flag is maintained across S3 boots. // mInitApsAfterSmmBaseReloc = FALSE; // // Send INIT IPI - SIPI to all APs // SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector); while (mNumberToFinish > 0) { CpuPause (); } }
/** AP initialization before then after SMBASE relocation in the S3 boot path. **/ VOID InitializeAp ( VOID ) { UINTN TopOfStack; UINT8 Stack[128]; LoadMtrrData (mAcpiCpuData.MtrrTable); SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus); // // Count down the number with lock mechanism. // InterlockedDecrement (&mNumberToFinish); // // Wait for BSP to signal SMM Base relocation done. // while (!mInitApsAfterSmmBaseReloc) { CpuPause (); } ProgramVirtualWireMode (); DisableLvtInterrupts (); SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable, mAcpiCpuData.NumberOfCpus); // // Place AP into the safe code, count down the number with lock mechanism in the safe code. // TopOfStack = (UINTN) Stack + sizeof (Stack); TopOfStack &= ~(UINTN) (CPU_STACK_ALIGNMENT - 1); CopyMem ((VOID *) (UINTN) mApHltLoopCode, mApHltLoopCodeTemplate, sizeof (mApHltLoopCodeTemplate)); TransferApToSafeState ((UINTN)mApHltLoopCode, TopOfStack, (UINTN)&mNumberToFinish); }
/** The function is invoked after SMBASE relocation in S3 path to restores CPU status. The function is invoked after SMBASE relocation in S3 path. It restores configuration according to data saved by normal boot path for both BSP and APs. **/ VOID InitializeCpuAfterRebase ( VOID ) { SetProcessorRegister ((CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable, mAcpiCpuData.NumberOfCpus); mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1; // // Signal that SMM base relocation is complete and to continue initialization. // mInitApsAfterSmmBaseReloc = TRUE; while (mNumberToFinish > 0) { CpuPause (); } }
/** The function is invoked before SMBASE relocation in S3 path to restors CPU status. The function is invoked before SMBASE relocation in S3 path. It does first time microcode load and restores MTRRs for both BSP and APs. **/ VOID EarlyInitializeCpu ( VOID ) { CPU_REGISTER_TABLE *RegisterTableList; UINT32 InitApicId; UINTN Index; LoadMtrrData (mAcpiCpuData.MtrrTable); // // Find processor number for this CPU. // RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable; InitApicId = GetInitialApicId (); for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) { if (RegisterTableList[Index].InitialApicId == InitApicId) { SetProcessorRegister (&RegisterTableList[Index]); break; } } ProgramVirtualWireMode (); PrepareAPStartupVector (mAcpiCpuData.StartupVector); mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1; mExchangeInfo->ApFunction = (VOID *) (UINTN) EarlyMPRendezvousProcedure; // // Send INIT IPI - SIPI to all APs // SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector); while (mNumberToFinish > 0) { CpuPause (); } }
/** Performs CPU features Initialization. This service will invoke MP service to perform CPU features initialization on BSP/APs per user configuration. @note This service could be called by BSP only. **/ VOID EFIAPI CpuFeaturesInitialize ( VOID ) { CPU_FEATURES_DATA *CpuFeaturesData; UINTN OldBspNumber; CpuFeaturesData = GetCpuFeaturesData (); OldBspNumber = GetProcessorIndex (CpuFeaturesData); CpuFeaturesData->BspNumber = OldBspNumber; // // Known limitation: In PEI phase, CpuFeatures driver not // support async mode execute tasks. So semaphore type // register can't been used for this instance, must use // DXE type instance. // // // Wakeup all APs for programming. // StartupAPsWorker (SetProcessorRegister, NULL); // // Programming BSP // SetProcessorRegister (CpuFeaturesData); // // Switch to new BSP if required // if (CpuFeaturesData->BspNumber != OldBspNumber) { SwitchNewBsp (CpuFeaturesData->BspNumber); } }
/** Programs processor registers according to register tables. This function programs processor registers according to register tables. **/ VOID SettingPhase ( VOID ) { UINT8 CallbackSignalValue; UINTN Index; UINTN ProcessorNumber; CPU_REGISTER_TABLE *RegisterTable; BOOLEAN NeedCpuOnlyReset; // // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back. // CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_PROCESSOR_SETTING_SIGNAL); // // Checks whether the callback function requests to bypass Setting phase. // if (CallbackSignalValue == CPU_BYPASS_SIGNAL) { return; } // // Check if CPU-only reset is needed // NeedCpuOnlyReset = FALSE; for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) { RegisterTable = &mCpuConfigConextBuffer.RegisterTable[Index]; if (RegisterTable->NumberBeforeReset > 0) { NeedCpuOnlyReset = TRUE; break; } } // // if CPU-only reset is needed, then program corresponding registers, and // trigger CPU-only reset. // if (NeedCpuOnlyReset) { mSetBeforeCpuOnlyReset = TRUE; DispatchAPAndWait ( TRUE, 0, SetProcessorRegister ); SetProcessorRegister (mCpuConfigConextBuffer.BspNumber); CpuOnlyResetAndRestore (); } // // Program processors' registers in sequential mode. // mSetBeforeCpuOnlyReset = FALSE; for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) { ProcessorNumber = mCpuConfigConextBuffer.SettingSequence[Index]; if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) { SetProcessorRegister (ProcessorNumber); } else { DispatchAPAndWait ( FALSE, GET_CPU_MISC_DATA (ProcessorNumber, ApicID), SetProcessorRegister ); } RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber]; RegisterTable->InitialApicId = GetInitialLocalApicId (ProcessorNumber); } // // Set PcdCpuCallbackSignal to trigger callback function // PcdSet8 (PcdCpuCallbackSignal, CPU_PROCESSOR_SETTING_END_SIGNAL); // // From now on, SetProcessorRegister() will be called only by SimpleApProcWrapper() // and ApProcWrapper to restore register settings after INIT signal, so switch // this flag from FALSE to TRUE. // mRestoreSettingAfterInit = TRUE; }