\r
#include "MpLib.h"\r
\r
+/**\r
+ Get the Application Processors state.\r
+\r
+ @param[in] CpuData The pointer to CPU_AP_DATA of specified AP\r
+\r
+ @return The AP status\r
+**/\r
+CPU_STATE\r
+GetApState (\r
+ IN CPU_AP_DATA *CpuData\r
+ )\r
+{\r
+ return CpuData->State;\r
+}\r
+\r
+/**\r
+ Set the Application Processors state.\r
+\r
+ @param[in] CpuData The pointer to CPU_AP_DATA of specified AP\r
+ @param[in] State The AP status\r
+**/\r
+VOID\r
+SetApState (\r
+ IN CPU_AP_DATA *CpuData,\r
+ IN CPU_STATE State\r
+ )\r
+{\r
+ AcquireSpinLock (&CpuData->ApLock);\r
+ CpuData->State = State;\r
+ ReleaseSpinLock (&CpuData->ApLock);\r
+}\r
+\r
+/**\r
+ Save the volatile registers required to be restored following INIT IPI.\r
+\r
+ @param[out] VolatileRegisters Returns buffer saved the volatile resisters\r
+**/\r
+VOID\r
+SaveVolatileRegisters (\r
+ OUT CPU_VOLATILE_REGISTERS *VolatileRegisters\r
+ )\r
+{\r
+ CPUID_VERSION_INFO_EDX VersionInfoEdx;\r
+\r
+ VolatileRegisters->Cr0 = AsmReadCr0 ();\r
+ VolatileRegisters->Cr3 = AsmReadCr3 ();\r
+ VolatileRegisters->Cr4 = AsmReadCr4 ();\r
+\r
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);\r
+ if (VersionInfoEdx.Bits.DE != 0) {\r
+ //\r
+ // If processor supports Debugging Extensions feature\r
+ // by CPUID.[EAX=01H]:EDX.BIT2\r
+ //\r
+ VolatileRegisters->Dr0 = AsmReadDr0 ();\r
+ VolatileRegisters->Dr1 = AsmReadDr1 ();\r
+ VolatileRegisters->Dr2 = AsmReadDr2 ();\r
+ VolatileRegisters->Dr3 = AsmReadDr3 ();\r
+ VolatileRegisters->Dr6 = AsmReadDr6 ();\r
+ VolatileRegisters->Dr7 = AsmReadDr7 ();\r
+ }\r
+}\r
+\r
+/**\r
+ Restore the volatile registers following INIT IPI.\r
+\r
+ @param[in] VolatileRegisters Pointer to volatile resisters\r
+ @param[in] IsRestoreDr TRUE: Restore DRx if supported\r
+ FALSE: Do not restore DRx\r
+**/\r
+VOID\r
+RestoreVolatileRegisters (\r
+ IN CPU_VOLATILE_REGISTERS *VolatileRegisters,\r
+ IN BOOLEAN IsRestoreDr\r
+ )\r
+{\r
+ CPUID_VERSION_INFO_EDX VersionInfoEdx;\r
+\r
+ AsmWriteCr0 (VolatileRegisters->Cr0);\r
+ AsmWriteCr3 (VolatileRegisters->Cr3);\r
+ AsmWriteCr4 (VolatileRegisters->Cr4);\r
+\r
+ if (IsRestoreDr) {\r
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);\r
+ if (VersionInfoEdx.Bits.DE != 0) {\r
+ //\r
+ // If processor supports Debugging Extensions feature\r
+ // by CPUID.[EAX=01H]:EDX.BIT2\r
+ //\r
+ AsmWriteDr0 (VolatileRegisters->Dr0);\r
+ AsmWriteDr1 (VolatileRegisters->Dr1);\r
+ AsmWriteDr2 (VolatileRegisters->Dr2);\r
+ AsmWriteDr3 (VolatileRegisters->Dr3);\r
+ AsmWriteDr6 (VolatileRegisters->Dr6);\r
+ AsmWriteDr7 (VolatileRegisters->Dr7);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Detect whether Mwait-monitor feature is supported.\r
+\r
+ @retval TRUE Mwait-monitor feature is supported.\r
+ @retval FALSE Mwait-monitor feature is not supported.\r
+**/\r
+BOOLEAN\r
+IsMwaitSupport (\r
+ VOID\r
+ )\r
+{\r
+ CPUID_VERSION_INFO_ECX VersionInfoEcx;\r
+\r
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);\r
+ return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;\r
+}\r
+\r
+/**\r
+ Get AP loop mode.\r
+\r
+ @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.\r
+\r
+ @return The AP loop mode.\r
+**/\r
+UINT8\r
+GetApLoopMode (\r
+ OUT UINT32 *MonitorFilterSize\r
+ )\r
+{\r
+ UINT8 ApLoopMode;\r
+ CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;\r
+\r
+ ASSERT (MonitorFilterSize != NULL);\r
+\r
+ ApLoopMode = PcdGet8 (PcdCpuApLoopMode);\r
+ ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);\r
+ if (ApLoopMode == ApInMwaitLoop) {\r
+ if (!IsMwaitSupport ()) {\r
+ //\r
+ // If processor does not support MONITOR/MWAIT feature,\r
+ // force AP in Hlt-loop mode\r
+ //\r
+ ApLoopMode = ApInHltLoop;\r
+ }\r
+ }\r
+\r
+ if (ApLoopMode != ApInMwaitLoop) {\r
+ *MonitorFilterSize = sizeof (UINT32);\r
+ } else {\r
+ //\r
+ // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes\r
+ // CPUID.[EAX=05H].EDX: C-states supported using MWAIT\r
+ //\r
+ AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL);\r
+ *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;\r
+ }\r
+\r
+ return ApLoopMode;\r
+}\r
+/*\r
+ Initialize CPU AP Data when AP is wakeup at the first time.\r
+\r
+ @param[in, out] CpuMpData Pointer to PEI CPU MP Data\r
+ @param[in] ProcessorNumber The handle number of processor\r
+ @param[in] BistData Processor BIST data\r
+\r
+**/\r
+VOID\r
+InitializeApData (\r
+ IN OUT CPU_MP_DATA *CpuMpData,\r
+ IN UINTN ProcessorNumber,\r
+ IN UINT32 BistData\r
+ )\r
+{\r
+ CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;\r
+ CpuMpData->CpuData[ProcessorNumber].Health = BistData;\r
+ CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;\r
+ CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();\r
+ CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+ if (CpuMpData->CpuData[ProcessorNumber].InitialApicId >= 0xFF) {\r
+ //\r
+ // Set x2APIC mode if there are any logical processor reporting\r
+ // an Initial APIC ID of 255 or greater.\r
+ //\r
+ AcquireSpinLock(&CpuMpData->MpLock);\r
+ CpuMpData->X2ApicEnable = TRUE;\r
+ ReleaseSpinLock(&CpuMpData->MpLock);\r
+ }\r
+\r
+ InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);\r
+ SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);\r
+}\r
\r
/**\r
MP Initialize Library initialization.\r
VOID\r
)\r
{\r
+ UINT32 MaxLogicalProcessorNumber;\r
+ UINT32 ApStackSize;\r
MP_ASSEMBLY_ADDRESS_MAP AddressMap;\r
+ UINTN BufferSize;\r
+ UINT32 MonitorFilterSize;\r
+ VOID *MpBuffer;\r
+ UINTN Buffer;\r
+ CPU_MP_DATA *CpuMpData;\r
+ UINT8 ApLoopMode;\r
+ UINT8 *MonitorBuffer;\r
+ UINTN Index;\r
UINTN ApResetVectorSize;\r
+ UINTN BackupBufferAddr;\r
+ MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);\r
\r
AsmGetAddressMap (&AddressMap);\r
ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);\r
+ ApStackSize = PcdGet32(PcdCpuApStackSize);\r
+ ApLoopMode = GetApLoopMode (&MonitorFilterSize);\r
+\r
+ BufferSize = ApStackSize * MaxLogicalProcessorNumber;\r
+ BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;\r
+ BufferSize += sizeof (CPU_MP_DATA);\r
+ BufferSize += ApResetVectorSize;\r
+ BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;\r
+ MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));\r
+ ASSERT (MpBuffer != NULL);\r
+ ZeroMem (MpBuffer, BufferSize);\r
+ Buffer = (UINTN) MpBuffer;\r
+\r
+ MonitorBuffer = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber);\r
+ BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;\r
+ CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize);\r
+ CpuMpData->Buffer = Buffer;\r
+ CpuMpData->CpuApStackSize = ApStackSize;\r
+ CpuMpData->BackupBuffer = BackupBufferAddr;\r
+ CpuMpData->BackupBufferSize = ApResetVectorSize;\r
+ CpuMpData->EndOfPeiFlag = FALSE;\r
+ CpuMpData->WakeupBuffer = (UINTN) -1;\r
+ CpuMpData->CpuCount = 1;\r
+ CpuMpData->BspNumber = 0;\r
+ CpuMpData->WaitEvent = NULL;\r
+ CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);\r
+ CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);\r
+ InitializeSpinLock(&CpuMpData->MpLock);\r
+ //\r
+ // Save BSP's Control registers to APs\r
+ //\r
+ SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);\r
+ //\r
+ // Set BSP basic information\r
+ //\r
+ InitializeApData (CpuMpData, 0, 0);\r
+ //\r
+ // Save assembly code information\r
+ //\r
+ CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));\r
+ //\r
+ // Finally set AP loop mode\r
+ //\r
+ CpuMpData->ApLoopMode = ApLoopMode;\r
+ DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));\r
+ //\r
+ // Set up APs wakeup signal buffer\r
+ //\r
+ for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {\r
+ CpuMpData->CpuData[Index].StartupApSignal =\r
+ (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);\r
+ }\r
+ //\r
+ // Load Microcode on BSP\r
+ //\r
+ MicrocodeDetect (CpuMpData);\r
+ //\r
+ // Store BSP's MTRR setting\r
+ //\r
+ MtrrGetAllMtrrs (&CpuMpData->MtrrTable);\r
+\r
return EFI_SUCCESS;\r
}\r
\r