\r
#include "RegisterCpuFeatures.h"\r
\r
+CHAR16 *mDependTypeStr[] = {L"None", L"Thread", L"Core", L"Package", L"Invalid" };\r
+CHAR16 *mRegisterTypeStr[] = {L"MSR", L"CR", L"MMIO", L"CACHE", L"SEMAP", L"INVALID" };\r
+\r
/**\r
Worker function to save PcdCpuFeaturesCapability.\r
\r
CPU_FEATURES_INIT_ORDER *InitOrder;\r
CPU_FEATURES_DATA *CpuFeaturesData;\r
LIST_ENTRY *Entry;\r
+ UINT32 Core;\r
+ UINT32 Package;\r
+ UINT32 Thread;\r
+ EFI_CPU_PHYSICAL_LOCATION *Location;\r
+ BOOLEAN *CoresVisited;\r
+ UINTN Index;\r
+ ACPI_CPU_DATA *AcpiCpuData;\r
+ CPU_STATUS_INFORMATION *CpuStatus;\r
+ UINT32 *ValidCoreCountPerPackage;\r
+\r
+ Core = 0;\r
+ Package = 0;\r
+ Thread = 0;\r
\r
CpuFeaturesData = GetCpuFeaturesData ();\r
CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);\r
Entry = Entry->ForwardLink;\r
}\r
\r
+ CpuFeaturesData->NumberOfCpus = (UINT32) NumberOfCpus;\r
+\r
+ AcpiCpuData = GetAcpiCpuData ();\r
+ ASSERT (AcpiCpuData != NULL);\r
+ CpuFeaturesData->AcpiCpuData= AcpiCpuData;\r
+\r
+ CpuStatus = &AcpiCpuData->CpuStatus;\r
+ Location = AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION) * NumberOfCpus);\r
+ ASSERT (Location != NULL);\r
+ AcpiCpuData->ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)Location;\r
+\r
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
InitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
InitOrder->FeaturesSupportedMask = AllocateZeroPool (CpuFeaturesData->BitMaskSize);\r
&ProcessorInfoBuffer,\r
sizeof (EFI_PROCESSOR_INFORMATION)\r
);\r
+ CopyMem (\r
+ &Location[ProcessorNumber],\r
+ &ProcessorInfoBuffer.Location,\r
+ sizeof (EFI_CPU_PHYSICAL_LOCATION)\r
+ );\r
+\r
+ //\r
+ // Collect CPU package count info.\r
+ //\r
+ if (Package < ProcessorInfoBuffer.Location.Package) {\r
+ Package = ProcessorInfoBuffer.Location.Package;\r
+ }\r
+ //\r
+ // Collect CPU max core count info.\r
+ //\r
+ if (Core < ProcessorInfoBuffer.Location.Core) {\r
+ Core = ProcessorInfoBuffer.Location.Core;\r
+ }\r
+ //\r
+ // Collect CPU max thread count info.\r
+ //\r
+ if (Thread < ProcessorInfoBuffer.Location.Thread) {\r
+ Thread = ProcessorInfoBuffer.Location.Thread;\r
+ }\r
}\r
+ CpuStatus->PackageCount = Package + 1;\r
+ CpuStatus->MaxCoreCount = Core + 1;\r
+ CpuStatus->MaxThreadCount = Thread + 1;\r
+ DEBUG ((DEBUG_INFO, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",\r
+ CpuStatus->PackageCount,\r
+ CpuStatus->MaxCoreCount,\r
+ CpuStatus->MaxThreadCount));\r
+\r
+ //\r
+ // Collect valid core count in each package because not all cores are valid.\r
+ //\r
+ ValidCoreCountPerPackage= AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount);\r
+ ASSERT (ValidCoreCountPerPackage != 0);\r
+ CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ValidCoreCountPerPackage;\r
+ CoresVisited = AllocatePool (sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);\r
+ ASSERT (CoresVisited != NULL);\r
+\r
+ for (Index = 0; Index < CpuStatus->PackageCount; Index ++ ) {\r
+ ZeroMem (CoresVisited, sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);\r
+ //\r
+ // Collect valid cores in Current package.\r
+ //\r
+ for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
+ Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
+ if (Location->Package == Index && !CoresVisited[Location->Core] ) {\r
+ //\r
+ // The ValidCores position for Location->Core is valid.\r
+ // The possible values in ValidCores[Index] are 0 or 1.\r
+ // FALSE means no valid threads in this Core.\r
+ // TRUE means have valid threads in this core, no matter the thead count is 1 or more.\r
+ //\r
+ CoresVisited[Location->Core] = TRUE;\r
+ ValidCoreCountPerPackage[Index]++;\r
+ }\r
+ }\r
+ }\r
+ FreePool (CoresVisited);\r
+\r
+ for (Index = 0; Index <= Package; Index++) {\r
+ DEBUG ((DEBUG_INFO, "Package: %d, Valid Core : %d\n", Index, ValidCoreCountPerPackage[Index]));\r
+ }\r
+\r
+ CpuFeaturesData->CpuFlags.SemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
+ ASSERT (CpuFeaturesData->CpuFlags.SemaphoreCount != NULL);\r
+\r
//\r
// Get support and configuration PCDs\r
//\r
LIST_ENTRY *Entry;\r
CPU_FEATURES_DATA *CpuFeaturesData;\r
\r
- CpuFeaturesData = GetCpuFeaturesData ();\r
+ CpuFeaturesData = (CPU_FEATURES_DATA *)Buffer;\r
ProcessorNumber = GetProcessorIndex ();\r
CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
//\r
RegisterTableEntry->Value\r
));\r
break;\r
+ case Semaphore:\r
+ DEBUG ((\r
+ DebugPrintErrorLevel,\r
+ "Processor: %d: Semaphore: Scope Value: %s\r\n",\r
+ ProcessorNumber,\r
+ mDependTypeStr[MIN (RegisterTableEntry->Value, InvalidDepType)]\r
+ ));\r
+ break;\r
+\r
default:\r
break;\r
}\r
REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
LIST_ENTRY *Entry;\r
CPU_FEATURES_DATA *CpuFeaturesData;\r
+ LIST_ENTRY *NextEntry;\r
+ CPU_FEATURES_ENTRY *NextCpuFeatureInOrder;\r
+ BOOLEAN Success;\r
+ CPU_FEATURE_DEPENDENCE_TYPE BeforeDep;\r
+ CPU_FEATURE_DEPENDENCE_TYPE AfterDep;\r
\r
CpuFeaturesData = GetCpuFeaturesData ();\r
CpuFeaturesData->CapabilityPcd = AllocatePool (CpuFeaturesData->BitMaskSize);\r
//\r
CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
Entry = GetFirstNode (&CpuInitOrder->OrderList);\r
+ NextEntry = Entry->ForwardLink;\r
while (!IsNull (&CpuInitOrder->OrderList, Entry)) {\r
CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
+ if (!IsNull (&CpuInitOrder->OrderList, NextEntry)) {\r
+ NextCpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (NextEntry);\r
+ } else {\r
+ NextCpuFeatureInOrder = NULL;\r
+ }\r
+ Success = FALSE;\r
if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcd)) {\r
Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, TRUE);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_WARN, "Warning :: Failed to enable Feature: Mask = "));\r
DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask);\r
}\r
+ } else {\r
+ Success = TRUE;\r
}\r
} else {\r
Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, FALSE);\r
DEBUG ((DEBUG_WARN, "Warning :: Failed to disable Feature: Mask = "));\r
DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask);\r
}\r
+ } else {\r
+ Success = TRUE;\r
}\r
}\r
- Entry = Entry->ForwardLink;\r
+\r
+ if (Success) {\r
+ //\r
+ // If feature has dependence with the next feature (ONLY care core/package dependency).\r
+ // and feature initialize succeed, add sync semaphere here.\r
+ //\r
+ BeforeDep = DetectFeatureScope (CpuFeatureInOrder, TRUE);\r
+ if (NextCpuFeatureInOrder != NULL) {\r
+ AfterDep = DetectFeatureScope (NextCpuFeatureInOrder, FALSE);\r
+ } else {\r
+ AfterDep = NoneDepType;\r
+ }\r
+ //\r
+ // Assume only one of the depend is valid.\r
+ //\r
+ ASSERT (!(BeforeDep > ThreadDepType && AfterDep > ThreadDepType));\r
+ if (BeforeDep > ThreadDepType) {\r
+ CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, BeforeDep);\r
+ }\r
+ if (AfterDep > ThreadDepType) {\r
+ CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, AfterDep);\r
+ }\r
+ }\r
+\r
+ Entry = Entry->ForwardLink;\r
+ NextEntry = Entry->ForwardLink;\r
}\r
\r
//\r
}\r
}\r
\r
+/**\r
+ Increment semaphore by 1.\r
+\r
+ @param Sem IN: 32-bit unsigned integer\r
+\r
+**/\r
+VOID\r
+LibReleaseSemaphore (\r
+ IN OUT volatile UINT32 *Sem\r
+ )\r
+{\r
+ InterlockedIncrement (Sem);\r
+}\r
+\r
+/**\r
+ Decrement the semaphore by 1 if it is not zero.\r
+\r
+ Performs an atomic decrement operation for semaphore.\r
+ The compare exchange operation must be performed using\r
+ MP safe mechanisms.\r
+\r
+ @param Sem IN: 32-bit unsigned integer\r
+\r
+**/\r
+VOID\r
+LibWaitForSemaphore (\r
+ IN OUT volatile UINT32 *Sem\r
+ )\r
+{\r
+ UINT32 Value;\r
+\r
+ do {\r
+ Value = *Sem;\r
+ } while (Value == 0 ||\r
+ InterlockedCompareExchange32 (\r
+ Sem,\r
+ Value,\r
+ Value - 1\r
+ ) != Value);\r
+}\r
+\r
/**\r
Initialize the CPU registers from a register table.\r
\r
- @param[in] ProcessorNumber The index of the CPU executing this function.\r
+ @param[in] RegisterTable The register table for this AP.\r
+ @param[in] ApLocation AP location info for this ap.\r
+ @param[in] CpuStatus CPU status info for this CPU.\r
+ @param[in] CpuFlags Flags data structure used when program the register.\r
\r
@note This service could be called by BSP/APs.\r
**/\r
VOID\r
ProgramProcessorRegister (\r
- IN UINTN ProcessorNumber\r
+ IN CPU_REGISTER_TABLE *RegisterTable,\r
+ IN EFI_CPU_PHYSICAL_LOCATION *ApLocation,\r
+ IN CPU_STATUS_INFORMATION *CpuStatus,\r
+ IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags\r
)\r
{\r
- CPU_FEATURES_DATA *CpuFeaturesData;\r
- CPU_REGISTER_TABLE *RegisterTable;\r
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
UINTN Index;\r
UINTN Value;\r
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
-\r
- CpuFeaturesData = GetCpuFeaturesData ();\r
- RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
+ volatile UINT32 *SemaphorePtr;\r
+ UINT32 FirstThread;\r
+ UINT32 PackageThreadsCount;\r
+ UINT32 CurrentThread;\r
+ UINTN ProcessorIndex;\r
+ UINTN ThreadIndex;\r
+ UINTN ValidThreadCount;\r
+ UINT32 *ValidCoreCountPerPackage;\r
\r
//\r
// Traverse Register Table of this logical processor\r
\r
RegisterTableEntry = &RegisterTableEntryHead[Index];\r
\r
+ DEBUG_CODE_BEGIN ();\r
+ AcquireSpinLock (&CpuFlags->ConsoleLogLock);\r
+ ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount +\r
+ ApLocation->Core * CpuStatus->MaxThreadCount +\r
+ ApLocation->Thread;\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Processor = %lu, Entry Index %lu, Type = %s!\n",\r
+ (UINT64)ThreadIndex,\r
+ (UINT64)Index,\r
+ mRegisterTypeStr[MIN ((REGISTER_TYPE)RegisterTableEntry->RegisterType, InvalidReg)]\r
+ ));\r
+ ReleaseSpinLock (&CpuFlags->ConsoleLogLock);\r
+ DEBUG_CODE_END ();\r
+\r
//\r
// Check the type of specified register\r
//\r
// The specified register is Model Specific Register\r
//\r
case Msr:\r
- //\r
- // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode\r
- //\r
- AcquireSpinLock (&CpuFeaturesData->MsrLock);\r
if (RegisterTableEntry->ValidBitLength >= 64) {\r
//\r
// If length is not less than 64 bits, then directly write without reading\r
RegisterTableEntry->Value\r
);\r
}\r
- ReleaseSpinLock (&CpuFeaturesData->MsrLock);\r
break;\r
//\r
// MemoryMapped operations\r
//\r
case MemoryMapped:\r
- AcquireSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
+ AcquireSpinLock (&CpuFlags->MemoryMappedLock);\r
MmioBitFieldWrite32 (\r
(UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),\r
RegisterTableEntry->ValidBitStart,\r
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
(UINT32)RegisterTableEntry->Value\r
);\r
- ReleaseSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
+ ReleaseSpinLock (&CpuFlags->MemoryMappedLock);\r
break;\r
//\r
// Enable or disable cache\r
}\r
break;\r
\r
+ case Semaphore:\r
+ // Semaphore works logic like below:\r
+ //\r
+ // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);\r
+ // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);\r
+ //\r
+ // All threads (T0...Tn) waits in P() line and continues running\r
+ // together.\r
+ //\r
+ //\r
+ // T0 T1 ... Tn\r
+ //\r
+ // V(0...n) V(0...n) ... V(0...n)\r
+ // n * P(0) n * P(1) ... n * P(n)\r
+ //\r
+ SemaphorePtr = CpuFlags->SemaphoreCount;\r
+ switch (RegisterTableEntry->Value) {\r
+ case CoreDepType:\r
+ //\r
+ // Get Offset info for the first thread in the core which current thread belongs to.\r
+ //\r
+ FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount;\r
+ CurrentThread = FirstThread + ApLocation->Thread;\r
+ //\r
+ // First Notify all threads in current Core that this thread has ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
+ LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
+ }\r
+ //\r
+ // Second, check whether all valid threads in current core have ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
+ LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
+ }\r
+ break;\r
+\r
+ case PackageDepType:\r
+ ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
+ //\r
+ // Get Offset info for the first thread in the package which current thread belongs to.\r
+ //\r
+ FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount;\r
+ //\r
+ // Get the possible threads count for current package.\r
+ //\r
+ PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount;\r
+ CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;\r
+ //\r
+ // Get the valid thread count for current package.\r
+ //\r
+ ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package];\r
+\r
+ //\r
+ // Different packages may have different valid cores in them. If driver maintail clearly\r
+ // cores number in different packages, the logic will be much complicated.\r
+ // Here driver just simply records the max core number in all packages and use it as expect\r
+ // core number for all packages.\r
+ // In below two steps logic, first current thread will Release semaphore for each thread\r
+ // in current package. Maybe some threads are not valid in this package, but driver don't\r
+ // care. Second, driver will let current thread wait semaphore for all valid threads in\r
+ // current package. Because only the valid threads will do release semaphore for this\r
+ // thread, driver here only need to wait the valid thread count.\r
+ //\r
+\r
+ //\r
+ // First Notify ALL THREADS in current package that this thread has ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {\r
+ LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
+ }\r
+ //\r
+ // Second, check whether VALID THREADS (not all threads) in current package have ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {\r
+ LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+\r
default:\r
break;\r
}\r
IN OUT VOID *Buffer\r
)\r
{\r
- UINTN ProcessorNumber;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+ CPU_REGISTER_TABLE *RegisterTable;\r
+ CPU_REGISTER_TABLE *RegisterTables;\r
+ UINT32 InitApicId;\r
+ UINTN ProcIndex;\r
+ UINTN Index;\r
+ ACPI_CPU_DATA *AcpiCpuData;\r
\r
- ProcessorNumber = GetProcessorIndex ();\r
- ProgramProcessorRegister (ProcessorNumber);\r
+ CpuFeaturesData = (CPU_FEATURES_DATA *) Buffer;\r
+ AcpiCpuData = CpuFeaturesData->AcpiCpuData;\r
+\r
+ RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable;\r
+\r
+ InitApicId = GetInitialApicId ();\r
+ RegisterTable = NULL;\r
+ for (Index = 0; Index < AcpiCpuData->NumberOfCpus; Index++) {\r
+ if (RegisterTables[Index].InitialApicId == InitApicId) {\r
+ RegisterTable = &RegisterTables[Index];\r
+ ProcIndex = Index;\r
+ break;\r
+ }\r
+ }\r
+ ASSERT (RegisterTable != NULL);\r
+\r
+ ProgramProcessorRegister (\r
+ RegisterTable,\r
+ (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation + ProcIndex,\r
+ &AcpiCpuData->CpuStatus,\r
+ &CpuFeaturesData->CpuFlags\r
+ );\r
}\r
\r
/**\r
{\r
UINTN NumberOfCpus;\r
UINTN NumberOfEnabledProcessors;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData();\r
\r
GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
\r
//\r
// Wakeup all APs for data collection.\r
//\r
- StartupAPsWorker (CollectProcessorData);\r
+ StartupAPsWorker (CollectProcessorData, NULL);\r
\r
//\r
// Collect data on BSP\r
//\r
- CollectProcessorData (NULL);\r
+ CollectProcessorData (CpuFeaturesData);\r
\r
AnalysisProcessorFeatures (NumberOfCpus);\r
}\r
\r
-/**\r
- Performs CPU features Initialization.\r
-\r
- This service will invoke MP service to perform CPU features\r
- initialization on BSP/APs per user configuration.\r
-\r
- @note This service could be called by BSP only.\r
-**/\r
-VOID\r
-EFIAPI\r
-CpuFeaturesInitialize (\r
- VOID\r
- )\r
-{\r
- CPU_FEATURES_DATA *CpuFeaturesData;\r
- UINTN OldBspNumber;\r
-\r
- CpuFeaturesData = GetCpuFeaturesData ();\r
-\r
- OldBspNumber = GetProcessorIndex();\r
- CpuFeaturesData->BspNumber = OldBspNumber;\r
- //\r
- // Wakeup all APs for programming.\r
- //\r
- StartupAPsWorker (SetProcessorRegister);\r
- //\r
- // Programming BSP\r
- //\r
- SetProcessorRegister (NULL);\r
- //\r
- // Switch to new BSP if required\r
- //\r
- if (CpuFeaturesData->BspNumber != OldBspNumber) {\r
- SwitchNewBsp (CpuFeaturesData->BspNumber);\r
- }\r
-}\r
#include <PiDxe.h>\r
\r
#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
\r
#include "RegisterCpuFeatures.h"\r
\r
\r
@param[in] Procedure A pointer to the function to be run on\r
enabled APs of the system.\r
+ @param[in] MpEvent A pointer to the event to be used later\r
+ to check whether procedure has done.\r
**/\r
VOID\r
StartupAPsWorker (\r
- IN EFI_AP_PROCEDURE Procedure\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN EFI_EVENT MpEvent\r
)\r
{\r
EFI_STATUS Status;\r
EFI_MP_SERVICES_PROTOCOL *MpServices;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
\r
MpServices = GetMpProtocol ();\r
//\r
MpServices,\r
Procedure,\r
FALSE,\r
- NULL,\r
+ MpEvent,\r
0,\r
- NULL,\r
+ CpuFeaturesData,\r
NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
ASSERT_EFI_ERROR (Status);\r
}\r
\r
+/**\r
+ Performs CPU features Initialization.\r
+\r
+ This service will invoke MP service to perform CPU features\r
+ initialization on BSP/APs per user configuration.\r
+\r
+ @note This service could be called by BSP only.\r
+**/\r
+VOID\r
+EFIAPI\r
+CpuFeaturesInitialize (\r
+ VOID\r
+ )\r
+{\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+ UINTN OldBspNumber;\r
+ EFI_EVENT MpEvent;\r
+ EFI_STATUS Status;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+\r
+ OldBspNumber = GetProcessorIndex();\r
+ CpuFeaturesData->BspNumber = OldBspNumber;\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_CALLBACK,\r
+ EfiEventEmptyFunction,\r
+ NULL,\r
+ &MpEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Wakeup all APs for programming.\r
+ //\r
+ StartupAPsWorker (SetProcessorRegister, MpEvent);\r
+ //\r
+ // Programming BSP\r
+ //\r
+ SetProcessorRegister (CpuFeaturesData);\r
+\r
+ //\r
+ // Wait all processors to finish the task.\r
+ //\r
+ do {\r
+ Status = gBS->CheckEvent (MpEvent);\r
+ } while (Status == EFI_NOT_READY);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Switch to new BSP if required\r
+ //\r
+ if (CpuFeaturesData->BspNumber != OldBspNumber) {\r
+ SwitchNewBsp (CpuFeaturesData->BspNumber);\r
+ }\r
+}\r
+\r
SynchronizationLib\r
UefiBootServicesTableLib\r
IoLib\r
+ UefiBootServicesTableLib\r
+ UefiLib\r
\r
[Protocols]\r
gEfiMpServiceProtocolGuid ## CONSUMES\r
**/\r
VOID\r
StartupAPsWorker (\r
- IN EFI_AP_PROCEDURE Procedure\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN EFI_EVENT MpEvent\r
)\r
{\r
EFI_STATUS Status;\r
EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
\r
//\r
// Get MP Services Protocol\r
Procedure,\r
FALSE,\r
0,\r
- NULL\r
+ CpuFeaturesData\r
);\r
ASSERT_EFI_ERROR (Status);\r
}\r
);\r
ASSERT_EFI_ERROR (Status);\r
}\r
+\r
+/**\r
+ Performs CPU features Initialization.\r
+\r
+ This service will invoke MP service to perform CPU features\r
+ initialization on BSP/APs per user configuration.\r
+\r
+ @note This service could be called by BSP only.\r
+**/\r
+VOID\r
+EFIAPI\r
+CpuFeaturesInitialize (\r
+ VOID\r
+ )\r
+{\r
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+ UINTN OldBspNumber;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+\r
+ OldBspNumber = GetProcessorIndex();\r
+ CpuFeaturesData->BspNumber = OldBspNumber;\r
+\r
+ //\r
+ // Known limitation: In PEI phase, CpuFeatures driver not\r
+ // support async mode execute tasks. So semaphore type\r
+ // register can't been used for this instance, must use\r
+ // DXE type instance.\r
+ //\r
+\r
+ //\r
+ // Wakeup all APs for programming.\r
+ //\r
+ StartupAPsWorker (SetProcessorRegister, NULL);\r
+ //\r
+ // Programming BSP\r
+ //\r
+ SetProcessorRegister (CpuFeaturesData);\r
+\r
+ //\r
+ // Switch to new BSP if required\r
+ //\r
+ if (CpuFeaturesData->BspNumber != OldBspNumber) {\r
+ SwitchNewBsp (CpuFeaturesData->BspNumber);\r
+ }\r
+}\r
+\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/SynchronizationLib.h>\r
#include <Library/IoLib.h>\r
+#include <Library/LocalApicLib.h>\r
\r
#include <AcpiCpuData.h>\r
\r
CPU_FEATURE_INITIALIZE InitializeFunc;\r
UINT8 *BeforeFeatureBitMask;\r
UINT8 *AfterFeatureBitMask;\r
+ UINT8 *CoreBeforeFeatureBitMask;\r
+ UINT8 *CoreAfterFeatureBitMask;\r
+ UINT8 *PackageBeforeFeatureBitMask;\r
+ UINT8 *PackageAfterFeatureBitMask;\r
VOID *ConfigData;\r
BOOLEAN BeforeAll;\r
BOOLEAN AfterAll;\r
} CPU_FEATURES_ENTRY;\r
\r
+//\r
+// Flags used when program the register.\r
+//\r
+typedef struct {\r
+ volatile UINTN ConsoleLogLock; // Spinlock used to control console.\r
+ volatile UINTN MemoryMappedLock; // Spinlock used to program mmio\r
+ volatile UINT32 *SemaphoreCount; // Semaphore used to program semaphore.\r
+} PROGRAM_CPU_REGISTER_FLAGS;\r
+\r
typedef struct {\r
UINTN FeaturesCount;\r
UINT32 BitMaskSize;\r
- SPIN_LOCK MsrLock;\r
- SPIN_LOCK MemoryMappedLock;\r
LIST_ENTRY FeatureList;\r
\r
CPU_FEATURES_INIT_ORDER *InitOrder;\r
UINT8 *ConfigurationPcd;\r
UINT8 *SettingPcd;\r
\r
+ UINT32 NumberOfCpus;\r
+ ACPI_CPU_DATA *AcpiCpuData;\r
+\r
CPU_REGISTER_TABLE *RegisterTable;\r
CPU_REGISTER_TABLE *PreSmmRegisterTable;\r
UINTN BspNumber;\r
+\r
+ PROGRAM_CPU_REGISTER_FLAGS CpuFlags;\r
} CPU_FEATURES_DATA;\r
\r
#define CPU_FEATURE_ENTRY_FROM_LINK(a) \\r
\r
@param[in] Procedure A pointer to the function to be run on\r
enabled APs of the system.\r
+ @param[in] MpEvent A pointer to the event to be used later\r
+ to check whether procedure has done.\r
**/\r
VOID\r
StartupAPsWorker (\r
- IN EFI_AP_PROCEDURE Procedure\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN EFI_EVENT MpEvent\r
);\r
\r
/**\r
IN CPU_FEATURES_ENTRY *CpuFeature\r
);\r
\r
+/**\r
+ Return feature dependence result.\r
+\r
+ @param[in] CpuFeature Pointer to CPU feature.\r
+ @param[in] Before Check before dependence or after.\r
+\r
+ @retval return the dependence result.\r
+**/\r
+CPU_FEATURE_DEPENDENCE_TYPE\r
+DetectFeatureScope (\r
+ IN CPU_FEATURES_ENTRY *CpuFeature,\r
+ IN BOOLEAN Before\r
+ );\r
+\r
+/**\r
+ Programs registers for the calling processor.\r
+\r
+ @param[in,out] Buffer The pointer to private data buffer.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetProcessorRegister (\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Return ACPI_CPU_DATA data.\r
+\r
+ @return Pointer to ACPI_CPU_DATA data.\r
+**/\r
+ACPI_CPU_DATA *\r
+GetAcpiCpuData (\r
+ VOID\r
+ );\r
+\r
#endif\r
return FALSE;\r
}\r
\r
+/**\r
+ Return feature dependence result.\r
+\r
+ @param[in] CpuFeature Pointer to CPU feature.\r
+ @param[in] Before Check before dependence or after.\r
+\r
+ @retval return the dependence result.\r
+**/\r
+CPU_FEATURE_DEPENDENCE_TYPE\r
+DetectFeatureScope (\r
+ IN CPU_FEATURES_ENTRY *CpuFeature,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ if (Before) {\r
+ if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
+ return PackageDepType;\r
+ }\r
+\r
+ if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
+ return CoreDepType;\r
+ }\r
+\r
+ if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
+ return ThreadDepType;\r
+ }\r
+\r
+ return NoneDepType;\r
+ }\r
+\r
+ if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
+ return PackageDepType;\r
+ }\r
+\r
+ if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
+ return CoreDepType;\r
+ }\r
+\r
+ if (CpuFeature->AfterFeatureBitMask != NULL) {\r
+ return ThreadDepType;\r
+ }\r
+\r
+ return NoneDepType;\r
+}\r
+\r
+/**\r
+ Clear dependence for the specified type.\r
+\r
+ @param[in] CurrentFeature Cpu feature need to clear.\r
+ @param[in] Before Before or after dependence relationship.\r
+\r
+**/\r
+VOID\r
+ClearFeatureScope (\r
+ IN CPU_FEATURES_ENTRY *CpuFeature,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ if (Before) {\r
+ if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->BeforeFeatureBitMask);\r
+ CpuFeature->BeforeFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->CoreBeforeFeatureBitMask);\r
+ CpuFeature->CoreBeforeFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->PackageBeforeFeatureBitMask);\r
+ CpuFeature->PackageBeforeFeatureBitMask = NULL;\r
+ }\r
+ } else {\r
+ if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->PackageAfterFeatureBitMask);\r
+ CpuFeature->PackageAfterFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->CoreAfterFeatureBitMask);\r
+ CpuFeature->CoreAfterFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->AfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->AfterFeatureBitMask);\r
+ CpuFeature->AfterFeatureBitMask = NULL;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Base on dependence relationship to asjust feature dependence.\r
+\r
+ ONLY when the feature before(or after) the find feature also has \r
+ dependence with the find feature. In this case, driver need to base\r
+ on dependce relationship to decide how to insert current feature and\r
+ adjust the feature dependence.\r
+\r
+ @param[in] PreviousFeature CPU feature current before the find one.\r
+ @param[in] CurrentFeature Cpu feature need to adjust.\r
+ @param[in] Before Before or after dependence relationship.\r
+\r
+ @retval TRUE means the current feature dependence has been adjusted.\r
+\r
+ @retval FALSE means the previous feature dependence has been adjusted.\r
+ or previous feature has no dependence with the find one.\r
+\r
+**/\r
+BOOLEAN\r
+AdjustFeaturesDependence (\r
+ IN OUT CPU_FEATURES_ENTRY *PreviousFeature,\r
+ IN OUT CPU_FEATURES_ENTRY *CurrentFeature,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ CPU_FEATURE_DEPENDENCE_TYPE PreDependType;\r
+ CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType;\r
+\r
+ PreDependType = DetectFeatureScope(PreviousFeature, Before);\r
+ CurrentDependType = DetectFeatureScope(CurrentFeature, Before);\r
+\r
+ //\r
+ // If previous feature has no dependence with the find featue.\r
+ // return FALSE.\r
+ //\r
+ if (PreDependType == NoneDepType) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // If both feature have dependence, keep the one which needs use more \r
+ // processors and clear the dependence for the other one.\r
+ //\r
+ if (PreDependType >= CurrentDependType) {\r
+ ClearFeatureScope (CurrentFeature, Before);\r
+ return TRUE;\r
+ } else {\r
+ ClearFeatureScope (PreviousFeature, Before);\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Base on dependence relationship to asjust feature order.\r
+\r
+ @param[in] FeatureList Pointer to CPU feature list\r
+ @param[in] FindEntry The entry this feature depend on.\r
+ @param[in] CurrentEntry The entry for this feature.\r
+ @param[in] Before Before or after dependence relationship.\r
+\r
+**/\r
+VOID\r
+AdjustEntry (\r
+ IN LIST_ENTRY *FeatureList,\r
+ IN OUT LIST_ENTRY *FindEntry,\r
+ IN OUT LIST_ENTRY *CurrentEntry,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ LIST_ENTRY *PreviousEntry;\r
+ CPU_FEATURES_ENTRY *PreviousFeature;\r
+ CPU_FEATURES_ENTRY *CurrentFeature;\r
+\r
+ //\r
+ // For CPU feature which has core or package type dependence, later code need to insert\r
+ // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.\r
+ // So if driver finds both feature A and B need to execute before feature C, driver will\r
+ // base on dependence type of feature A and B to update the logic here.\r
+ // For example, feature A has package type dependence and feature B has core type dependence,\r
+ // because package type dependence need to wait for more processors which has strong dependence\r
+ // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver \r
+ // will remove the feature dependence in feature B. \r
+ // Driver just needs to make sure before feature C been executed, feature A has finished its task\r
+ // in all all thread. Feature A finished in all threads also means feature B have finshed in all\r
+ // threads.\r
+ //\r
+ if (Before) {\r
+ PreviousEntry = GetPreviousNode (FeatureList, FindEntry);\r
+ } else {\r\r
+ PreviousEntry = GetNextNode (FeatureList, FindEntry);\r
+ }\r
+\r
+ CurrentFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
+ RemoveEntryList (CurrentEntry);\r
+\r
+ if (IsNull (FeatureList, PreviousEntry)) {\r
+ //\r
+ // If not exist the previous or next entry, just insert the current entry.\r
+ //\r
+ if (Before) {\r
+ InsertTailList (FindEntry, CurrentEntry);\r
+ } else {\r
+ InsertHeadList (FindEntry, CurrentEntry);\r
+ }\r
+ } else {\r
+ //\r
+ // If exist the previous or next entry, need to check it before insert curent entry.\r
+ //\r
+ PreviousFeature = CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry);\r
+\r
+ if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, Before)) {\r
+ //\r
+ // Return TRUE means current feature dependence has been cleared and the previous\r
+ // feature dependence has been kept and used. So insert current feature before (or after)\r
+ // the previous feature.\r
+ //\r
+ if (Before) {\r
+ InsertTailList (PreviousEntry, CurrentEntry);\r
+ } else {\r
+ InsertHeadList (PreviousEntry, CurrentEntry);\r
+ }\r
+ } else {\r
+ if (Before) {\r
+ InsertTailList (FindEntry, CurrentEntry);\r
+ } else {\r
+ InsertHeadList (FindEntry, CurrentEntry);\r
+ }\r
+ }\r
+ }\r
+}\r\r
+\r
+/**\r
+ Checks and adjusts current CPU features per dependency relationship.\r
+\r
+ @param[in] FeatureList Pointer to CPU feature list\r
+ @param[in] CurrentEntry Pointer to current checked CPU feature\r
+ @param[in] FeatureMask The feature bit mask.\r
+\r
+ @retval return Swapped info.\r
+**/\r
+BOOLEAN\r
+InsertToBeforeEntry (\r
+ IN LIST_ENTRY *FeatureList,\r
+ IN LIST_ENTRY *CurrentEntry,\r
+ IN UINT8 *FeatureMask\r
+ )\r
+{\r
+ LIST_ENTRY *CheckEntry;\r
+ CPU_FEATURES_ENTRY *CheckFeature;\r
+ BOOLEAN Swapped;\r
+\r
+ Swapped = FALSE;\r
+\r
+ //\r
+ // Check all features dispatched before this entry\r
+ //\r
+ CheckEntry = GetFirstNode (FeatureList);\r
+ while (CheckEntry != CurrentEntry) {\r
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+ if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {\r
+ AdjustEntry (FeatureList, CheckEntry, CurrentEntry, TRUE);\r
+ Swapped = TRUE;\r
+ break;\r
+ }\r
+ CheckEntry = CheckEntry->ForwardLink;\r
+ }\r
+\r
+ return Swapped;\r
+}\r
+\r
+/**\r
+ Checks and adjusts current CPU features per dependency relationship.\r
+\r
+ @param[in] FeatureList Pointer to CPU feature list\r
+ @param[in] CurrentEntry Pointer to current checked CPU feature\r
+ @param[in] FeatureMask The feature bit mask.\r
+\r
+ @retval return Swapped info.\r
+**/\r
+BOOLEAN\r
+InsertToAfterEntry (\r
+ IN LIST_ENTRY *FeatureList,\r
+ IN LIST_ENTRY *CurrentEntry,\r
+ IN UINT8 *FeatureMask\r
+ )\r
+{\r
+ LIST_ENTRY *CheckEntry;\r
+ CPU_FEATURES_ENTRY *CheckFeature;\r
+ BOOLEAN Swapped;\r
+\r
+ Swapped = FALSE;\r
+\r
+ //\r
+ // Check all features dispatched after this entry\r
+ //\r
+ CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
+ while (!IsNull (FeatureList, CheckEntry)) {\r
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+ if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {\r
+ AdjustEntry (FeatureList, CheckEntry, CurrentEntry, FALSE);\r
+ Swapped = TRUE;\r
+ break;\r
+ }\r
+ CheckEntry = CheckEntry->ForwardLink;\r
+ }\r
+\r
+ return Swapped;\r
+}\r
+\r
/**\r
Checks and adjusts CPU features order per dependency relationship.\r
\r
CPU_FEATURES_ENTRY *CheckFeature;\r
BOOLEAN Swapped;\r
LIST_ENTRY *TempEntry;\r
+ LIST_ENTRY *NextEntry;\r
\r
CurrentEntry = GetFirstNode (FeatureList);\r
while (!IsNull (FeatureList, CurrentEntry)) {\r
Swapped = FALSE;\r
CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
+ NextEntry = CurrentEntry->ForwardLink;\r
if (CpuFeature->BeforeAll) {\r
//\r
// Check all features dispatched before this entry\r
CheckEntry = CheckEntry->ForwardLink;\r
}\r
if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
continue;\r
}\r
}\r
CheckEntry = CheckEntry->ForwardLink;\r
}\r
if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
continue;\r
}\r
}\r
\r
if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
- //\r
- // Check all features dispatched before this entry\r
- //\r
- CheckEntry = GetFirstNode (FeatureList);\r
- while (CheckEntry != CurrentEntry) {\r
- CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
- if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {\r
- //\r
- // If there is dependency, swap them\r
- //\r
- RemoveEntryList (CurrentEntry);\r
- InsertTailList (CheckEntry, CurrentEntry);\r
- Swapped = TRUE;\r
- break;\r
- }\r
- CheckEntry = CheckEntry->ForwardLink;\r
- }\r
+ Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->BeforeFeatureBitMask);\r
if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
continue;\r
}\r
}\r
\r
if (CpuFeature->AfterFeatureBitMask != NULL) {\r
- //\r
- // Check all features dispatched after this entry\r
- //\r
- CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
- while (!IsNull (FeatureList, CheckEntry)) {\r
- CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
- if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {\r
- //\r
- // If there is dependency, swap them\r
- //\r
- TempEntry = GetNextNode (FeatureList, CurrentEntry);\r
- RemoveEntryList (CurrentEntry);\r
- InsertHeadList (CheckEntry, CurrentEntry);\r
- CurrentEntry = TempEntry;\r
- Swapped = TRUE;\r
- break;\r
- }\r
- CheckEntry = CheckEntry->ForwardLink;\r
+ Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->AfterFeatureBitMask);\r
+ if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
+ Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->CoreBeforeFeatureBitMask);\r
+ if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
+ continue;\r
}\r
+ }\r
+\r
+ if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
+ Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->CoreAfterFeatureBitMask);\r
if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
continue;\r
}\r
}\r
- //\r
- // No swap happened, check the next feature\r
- //\r
+\r
+ if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
+ Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->PackageBeforeFeatureBitMask);\r
+ if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
+ Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->PackageAfterFeatureBitMask);\r
+ if (Swapped) {\r
+ CurrentEntry = NextEntry;\r
+ continue;\r
+ }\r
+ }\r
+\r
CurrentEntry = CurrentEntry->ForwardLink;\r
}\r
}\r
CpuFeaturesData = GetCpuFeaturesData ();\r
if (CpuFeaturesData->FeaturesCount == 0) {\r
InitializeListHead (&CpuFeaturesData->FeatureList);\r
- InitializeSpinLock (&CpuFeaturesData->MsrLock);\r
- InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
+ InitializeSpinLock (&CpuFeaturesData->CpuFlags.MemoryMappedLock);\r
+ InitializeSpinLock (&CpuFeaturesData->CpuFlags.ConsoleLogLock);\r
CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;\r
}\r
ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);\r
}\r
CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;\r
}\r
+ if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
+ if (CpuFeatureEntry->CoreBeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeatureEntry->CoreBeforeFeatureBitMask);\r
+ }\r
+ CpuFeatureEntry->CoreBeforeFeatureBitMask = CpuFeature->CoreBeforeFeatureBitMask;\r
+ }\r
+ if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
+ if (CpuFeatureEntry->CoreAfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeatureEntry->CoreAfterFeatureBitMask);\r
+ }\r
+ CpuFeatureEntry->CoreAfterFeatureBitMask = CpuFeature->CoreAfterFeatureBitMask;\r
+ }\r
+ if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
+ if (CpuFeatureEntry->PackageBeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeatureEntry->PackageBeforeFeatureBitMask);\r
+ }\r
+ CpuFeatureEntry->PackageBeforeFeatureBitMask = CpuFeature->PackageBeforeFeatureBitMask;\r
+ }\r
+ if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
+ if (CpuFeatureEntry->PackageAfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeatureEntry->PackageAfterFeatureBitMask);\r
+ }\r
+ CpuFeatureEntry->PackageAfterFeatureBitMask = CpuFeature->PackageAfterFeatureBitMask;\r
+ }\r
+\r
CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;\r
CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;\r
\r
@retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r
supported due to a circular dependency between\r
BEFORE and AFTER features.\r
+ @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration\r
+ not updated by Platform driver yet.\r
\r
@note This service could be called by BSP only.\r
**/\r
UINT8 *FeatureMask;\r
UINT8 *BeforeFeatureBitMask;\r
UINT8 *AfterFeatureBitMask;\r
+ UINT8 *CoreBeforeFeatureBitMask;\r
+ UINT8 *CoreAfterFeatureBitMask;\r
+ UINT8 *PackageBeforeFeatureBitMask;\r
+ UINT8 *PackageAfterFeatureBitMask;\r
BOOLEAN BeforeAll;\r
BOOLEAN AfterAll;\r
\r
- FeatureMask = NULL;\r
- BeforeFeatureBitMask = NULL;\r
- AfterFeatureBitMask = NULL;\r
+ FeatureMask = NULL;\r
+ BeforeFeatureBitMask = NULL;\r
+ AfterFeatureBitMask = NULL;\r
+ CoreBeforeFeatureBitMask = NULL;\r
+ CoreAfterFeatureBitMask = NULL;\r
+ PackageBeforeFeatureBitMask = NULL;\r
+ PackageAfterFeatureBitMask = NULL;\r
BeforeAll = FALSE;\r
AfterAll = FALSE;\r
\r
!= (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));\r
ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))\r
!= (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));\r
+ ASSERT ((Feature & (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER))\r
+ != (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER));\r
+ ASSERT ((Feature & (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER))\r
+ != (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER));\r
if (Feature < CPU_FEATURE_BEFORE) {\r
BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;\r
AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;\r
SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);\r
} else if ((Feature & CPU_FEATURE_AFTER) != 0) {\r
SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);\r
+ } else if ((Feature & CPU_FEATURE_CORE_BEFORE) != 0) {\r
+ SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask, Feature & ~CPU_FEATURE_CORE_BEFORE, BitMaskSize);\r
+ } else if ((Feature & CPU_FEATURE_CORE_AFTER) != 0) {\r
+ SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask, Feature & ~CPU_FEATURE_CORE_AFTER, BitMaskSize);\r
+ } else if ((Feature & CPU_FEATURE_PACKAGE_BEFORE) != 0) {\r
+ SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_BEFORE, BitMaskSize);\r
+ } else if ((Feature & CPU_FEATURE_PACKAGE_AFTER) != 0) {\r
+ SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_AFTER, BitMaskSize);\r
}\r
Feature = VA_ARG (Marker, UINT32);\r
}\r
\r
CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));\r
ASSERT (CpuFeature != NULL);\r
- CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;\r
- CpuFeature->FeatureMask = FeatureMask;\r
- CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r
- CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;\r
- CpuFeature->BeforeAll = BeforeAll;\r
- CpuFeature->AfterAll = AfterAll;\r
- CpuFeature->GetConfigDataFunc = GetConfigDataFunc;\r
- CpuFeature->SupportFunc = SupportFunc;\r
- CpuFeature->InitializeFunc = InitializeFunc;\r
+ CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;\r
+ CpuFeature->FeatureMask = FeatureMask;\r
+ CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r
+ CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;\r
+ CpuFeature->CoreBeforeFeatureBitMask = CoreBeforeFeatureBitMask;\r
+ CpuFeature->CoreAfterFeatureBitMask = CoreAfterFeatureBitMask;\r
+ CpuFeature->PackageBeforeFeatureBitMask = PackageBeforeFeatureBitMask;\r
+ CpuFeature->PackageAfterFeatureBitMask = PackageAfterFeatureBitMask;\r
+ CpuFeature->BeforeAll = BeforeAll;\r
+ CpuFeature->AfterAll = AfterAll;\r
+ CpuFeature->GetConfigDataFunc = GetConfigDataFunc;\r
+ CpuFeature->SupportFunc = SupportFunc;\r
+ CpuFeature->InitializeFunc = InitializeFunc;\r
if (FeatureName != NULL) {\r
CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
ASSERT (CpuFeature->FeatureName != NULL);\r
}\r
\r
/**\r
- Allocates boot service data to save ACPI_CPU_DATA.\r
+ Return ACPI_CPU_DATA data.\r
\r
- @return Pointer to allocated ACPI_CPU_DATA.\r
+ @return Pointer to ACPI_CPU_DATA data.\r
**/\r
-STATIC\r
ACPI_CPU_DATA *\r
-AllocateAcpiCpuData (\r
+GetAcpiCpuData (\r
VOID\r
)\r
{\r
UINTN Index;\r
EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
\r
+ AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
+ if (AcpiCpuData != NULL) {\r
+ return AcpiCpuData;\r
+ }\r
+\r
AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));\r
ASSERT (AcpiCpuData != NULL);\r
\r
+ //\r
+ // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
+ //\r
+ Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;\r
\r
IN UINT64 Value\r
)\r
{\r
- EFI_STATUS Status;\r
CPU_FEATURES_DATA *CpuFeaturesData;\r
ACPI_CPU_DATA *AcpiCpuData;\r
CPU_REGISTER_TABLE *RegisterTable;\r
\r
CpuFeaturesData = GetCpuFeaturesData ();\r
if (CpuFeaturesData->RegisterTable == NULL) {\r
- AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
- if (AcpiCpuData == NULL) {\r
- AcpiCpuData = AllocateAcpiCpuData ();\r
- ASSERT (AcpiCpuData != NULL);\r
- //\r
- // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
- //\r
- Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- ASSERT (AcpiCpuData->RegisterTable != 0);\r
+ AcpiCpuData = GetAcpiCpuData ();\r
+ ASSERT ((AcpiCpuData != NULL) && (AcpiCpuData->RegisterTable != 0));\r
CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;\r
CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;\r
}\r