/** @file\r
CPU Features Initialize functions.\r
\r
- Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
UINT32 Package;\r
UINT32 Thread;\r
EFI_CPU_PHYSICAL_LOCATION *Location;\r
- BOOLEAN *CoresVisited;\r
- UINTN Index;\r
+ UINT32 PackageIndex;\r
+ UINT32 CoreIndex;\r
+ UINTN Pages;\r
+ UINT32 FirstPackage;\r
+ UINT32 *FirstCore;\r
+ UINT32 *FirstThread;\r
ACPI_CPU_DATA *AcpiCpuData;\r
CPU_STATUS_INFORMATION *CpuStatus;\r
- UINT32 *ValidCoreCountPerPackage;\r
+ UINT32 *ThreadCountPerPackage;\r
+ UINT8 *ThreadCountPerCore;\r
UINTN NumberOfCpus;\r
UINTN NumberOfEnabledProcessors;\r
\r
\r
GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
\r
- CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);\r
+ CpuFeaturesData->InitOrder = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus));\r
ASSERT (CpuFeaturesData->InitOrder != NULL);\r
+ ZeroMem (CpuFeaturesData->InitOrder, sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);\r
\r
//\r
// Collect CPU Features information\r
ASSERT (AcpiCpuData != NULL);\r
CpuFeaturesData->AcpiCpuData= AcpiCpuData;\r
\r
- CpuStatus = &AcpiCpuData->CpuStatus;\r
+ CpuStatus = &AcpiCpuData->CpuFeatureInitData.CpuStatus;\r
Location = AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION) * NumberOfCpus);\r
ASSERT (Location != NULL);\r
- AcpiCpuData->ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)Location;\r
+ AcpiCpuData->CpuFeatureInitData.ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)Location;\r
\r
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
InitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\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
+ ThreadCountPerPackage = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount);\r
+ ASSERT (ThreadCountPerPackage != NULL);\r
+ CpuStatus->ThreadCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ThreadCountPerPackage;\r
+\r
+ ThreadCountPerCore = AllocateZeroPool (sizeof (UINT8) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount);\r
+ ASSERT (ThreadCountPerCore != NULL);\r
+ CpuStatus->ThreadCountPerCore = (EFI_PHYSICAL_ADDRESS)(UINTN)ThreadCountPerCore;\r
+\r
+ for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
+ Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
+ ThreadCountPerPackage[Location->Package]++;\r
+ ThreadCountPerCore[Location->Package * CpuStatus->MaxCoreCount + Location->Core]++;\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
+ for (PackageIndex = 0; PackageIndex < CpuStatus->PackageCount; PackageIndex++) {\r
+ if (ThreadCountPerPackage[PackageIndex] != 0) {\r
+ DEBUG ((DEBUG_INFO, "P%02d: Thread Count = %d\n", PackageIndex, ThreadCountPerPackage[PackageIndex]));\r
+ for (CoreIndex = 0; CoreIndex < CpuStatus->MaxCoreCount; CoreIndex++) {\r
+ if (ThreadCountPerCore[PackageIndex * CpuStatus->MaxCoreCount + CoreIndex] != 0) {\r
+ DEBUG ((\r
+ DEBUG_INFO, " P%02d C%04d, Thread Count = %d\n", PackageIndex, CoreIndex,\r
+ ThreadCountPerCore[PackageIndex * CpuStatus->MaxCoreCount + CoreIndex]\r
+ ));\r
+ }\r
+ }\r
+ }\r
}\r
\r
CpuFeaturesData->CpuFlags.CoreSemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
ASSERT (CpuFeaturesData->CpuFlags.CoreSemaphoreCount != NULL);\r
CpuFeaturesData->CpuFlags.PackageSemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
ASSERT (CpuFeaturesData->CpuFlags.PackageSemaphoreCount != NULL);\r
+\r
+ //\r
+ // Initialize CpuFeaturesData->InitOrder[].CpuInfo.First\r
+ // Use AllocatePages () instead of AllocatePool () because pool cannot be freed in PEI phase but page can.\r
+ //\r
+ Pages = EFI_SIZE_TO_PAGES (CpuStatus->PackageCount * sizeof (UINT32) + CpuStatus->PackageCount * CpuStatus->MaxCoreCount * sizeof (UINT32));\r
+ FirstCore = AllocatePages (Pages);\r
+ ASSERT (FirstCore != NULL);\r
+ FirstThread = FirstCore + CpuStatus->PackageCount;\r
+\r
+ //\r
+ // Set FirstPackage, FirstCore[], FirstThread[] to maximum package ID, core ID, thread ID.\r
+ //\r
+ FirstPackage = MAX_UINT32;\r
+ SetMem32 (FirstCore, CpuStatus->PackageCount * sizeof (UINT32), MAX_UINT32);\r
+ SetMem32 (FirstThread, CpuStatus->PackageCount * CpuStatus->MaxCoreCount * sizeof (UINT32), MAX_UINT32);\r
+\r
+ for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
+ Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
+\r
+ //\r
+ // Save the minimum package ID in the platform.\r
+ //\r
+ FirstPackage = MIN (Location->Package, FirstPackage);\r
+\r
+ //\r
+ // Save the minimum core ID per package.\r
+ //\r
+ FirstCore[Location->Package] = MIN (Location->Core, FirstCore[Location->Package]);\r
+\r
+ //\r
+ // Save the minimum thread ID per core.\r
+ //\r
+ FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core] = MIN (\r
+ Location->Thread,\r
+ FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core]\r
+ );\r
+ }\r
+\r
+ //\r
+ // Update the First field.\r
+ //\r
+ for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
+ Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
+\r
+ if (Location->Package == FirstPackage) {\r
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Package = 1;\r
+ }\r
+\r
+ //\r
+ // Set First.Die/Tile/Module for each thread assuming:\r
+ // single Die under each package, single Tile under each Die, single Module under each Tile\r
+ //\r
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Die = 1;\r
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Tile = 1;\r
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Module = 1;\r
+\r
+ if (Location->Core == FirstCore[Location->Package]) {\r
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Core = 1;\r
+ }\r
+ if (Location->Thread == FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core]) {\r
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Thread = 1;\r
+ }\r
+ }\r
+\r
+ FreePages (FirstCore, Pages);\r
}\r
\r
/**\r
DEBUG ((\r
DebugPrintErrorLevel,\r
"Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
- ProcessorNumber,\r
- FeatureIndex,\r
+ (UINT32) ProcessorNumber,\r
+ (UINT32) FeatureIndex,\r
RegisterTableEntry->Index,\r
RegisterTableEntry->ValidBitStart,\r
RegisterTableEntry->ValidBitLength,\r
DEBUG ((\r
DebugPrintErrorLevel,\r
"Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
- ProcessorNumber,\r
- FeatureIndex,\r
+ (UINT32) ProcessorNumber,\r
+ (UINT32) FeatureIndex,\r
RegisterTableEntry->Index,\r
RegisterTableEntry->ValidBitStart,\r
RegisterTableEntry->ValidBitLength,\r
case MemoryMapped:\r
DEBUG ((\r
DebugPrintErrorLevel,\r
- "Processor: %04d: Index %04d, MMIO : %08lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
- ProcessorNumber,\r
- FeatureIndex,\r
+ "Processor: %04d: Index %04d, MMIO : %016lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
+ (UINT32) ProcessorNumber,\r
+ (UINT32) FeatureIndex,\r
RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),\r
RegisterTableEntry->ValidBitStart,\r
RegisterTableEntry->ValidBitLength,\r
case CacheControl:\r
DEBUG ((\r
DebugPrintErrorLevel,\r
- "Processor: %04d: Index %04d, CACHE: %08lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
- ProcessorNumber,\r
- FeatureIndex,\r
+ "Processor: %04d: Index %04d, CACHE: %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
+ (UINT32) ProcessorNumber,\r
+ (UINT32) FeatureIndex,\r
RegisterTableEntry->Index,\r
RegisterTableEntry->ValidBitStart,\r
RegisterTableEntry->ValidBitLength,\r
DEBUG ((\r
DebugPrintErrorLevel,\r
"Processor: %04d: Index %04d, SEMAP: %s\r\n",\r
- ProcessorNumber,\r
- FeatureIndex,\r
+ (UINT32) ProcessorNumber,\r
+ (UINT32) FeatureIndex,\r
mDependTypeStr[MIN ((UINT32)RegisterTableEntry->Value, InvalidDepType)]\r
));\r
break;\r
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
volatile UINT32 *SemaphorePtr;\r
UINT32 FirstThread;\r
- UINT32 PackageThreadsCount;\r
UINT32 CurrentThread;\r
+ UINT32 CurrentCore;\r
UINTN ProcessorIndex;\r
- UINTN ValidThreadCount;\r
- UINT32 *ValidCoreCountPerPackage;\r
+ UINT32 *ThreadCountPerPackage;\r
+ UINT8 *ThreadCountPerCore;\r
EFI_STATUS Status;\r
+ UINT64 CurrentValue;\r
\r
//\r
// Traverse Register Table of this logical processor\r
if (EFI_ERROR (Status)) {\r
break;\r
}\r
-\r
+ if (RegisterTableEntry->TestThenWrite) {\r
+ CurrentValue = BitFieldRead64 (\r
+ Value,\r
+ RegisterTableEntry->ValidBitStart,\r
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
+ );\r
+ if (CurrentValue == RegisterTableEntry->Value) {\r
+ break;\r
+ }\r
+ }\r
Value = (UINTN) BitFieldWrite64 (\r
Value,\r
RegisterTableEntry->ValidBitStart,\r
);\r
ReadWriteCr (RegisterTableEntry->Index, FALSE, &Value);\r
break;\r
+\r
//\r
// The specified register is Model Specific Register\r
//\r
case Msr:\r
+ if (RegisterTableEntry->TestThenWrite) {\r
+ Value = (UINTN)AsmReadMsr64 (RegisterTableEntry->Index);\r
+ if (RegisterTableEntry->ValidBitLength >= 64) {\r
+ if (Value == RegisterTableEntry->Value) {\r
+ break;\r
+ }\r
+ } else {\r
+ CurrentValue = BitFieldRead64 (\r
+ Value,\r
+ RegisterTableEntry->ValidBitStart,\r
+ RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
+ );\r
+ if (CurrentValue == RegisterTableEntry->Value) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
if (RegisterTableEntry->ValidBitLength >= 64) {\r
//\r
// If length is not less than 64 bits, then directly write without reading\r
switch (RegisterTableEntry->Value) {\r
case CoreDepType:\r
SemaphorePtr = CpuFlags->CoreSemaphoreCount;\r
+ ThreadCountPerCore = (UINT8 *)(UINTN)CpuStatus->ThreadCountPerCore;\r
+\r
+ CurrentCore = ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core;\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
+ FirstThread = CurrentCore * CpuStatus->MaxThreadCount;\r
CurrentThread = FirstThread + ApLocation->Thread;\r
+\r
+ //\r
+ // Different cores may have different valid threads in them. If driver maintail clearly\r
+ // thread index in different cores, the logic will be much complicated.\r
+ // Here driver just simply records the max thread number in all cores and use it as expect\r
+ // thread number for all cores.\r
+ // In below two steps logic, first current thread will Release semaphore for each thread\r
+ // in current core. Maybe some threads are not valid in this core, but driver don't\r
+ // care. Second, driver will let current thread wait semaphore for all valid threads in\r
+ // current core. 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 Core that this thread has ready.\r
+ // First Notify ALL THREADs in current Core that this thread is ready.\r
//\r
for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
- LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
+ LibReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
}\r
//\r
- // Second, check whether all valid threads in current core have ready.\r
+ // Second, check whether all VALID THREADs (not all threads) in current core are ready.\r
//\r
- for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
+ for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerCore[CurrentCore]; ProcessorIndex ++) {\r
LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
}\r
break;\r
\r
case PackageDepType:\r
SemaphorePtr = CpuFlags->PackageSemaphoreCount;\r
- ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
+ ThreadCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ThreadCountPerPackage;\r
//\r
// Get Offset info for the first thread in the package which current thread belongs to.\r
//\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
+ // Different packages may have different valid threads in them. If driver maintail clearly\r
+ // thread index in different packages, the logic will be much complicated.\r
+ // Here driver just simply records the max thread number in all packages and use it as expect\r
+ // thread 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
//\r
\r
//\r
- // First Notify ALL THREADS in current package that this thread has ready.\r
+ // First Notify ALL THREADS in current package that this thread is ready.\r
//\r
- for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {\r
- LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; ProcessorIndex ++) {\r
+ LibReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
}\r
//\r
- // Second, check whether VALID THREADS (not all threads) in current package have ready.\r
+ // Second, check whether VALID THREADS (not all threads) in current package are ready.\r
//\r
- for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {\r
+ for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerPackage[ApLocation->Package]; ProcessorIndex ++) {\r
LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
}\r
break;\r
CpuFeaturesData = (CPU_FEATURES_DATA *) Buffer;\r
AcpiCpuData = CpuFeaturesData->AcpiCpuData;\r
\r
- RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable;\r
+ RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->CpuFeatureInitData.RegisterTable;\r
\r
InitApicId = GetInitialApicId ();\r
RegisterTable = NULL;\r
\r
ProgramProcessorRegister (\r
RegisterTable,\r
- (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation + ProcIndex,\r
- &AcpiCpuData->CpuStatus,\r
+ (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->CpuFeatureInitData.ApLocation + ProcIndex,\r
+ &AcpiCpuData->CpuFeatureInitData.CpuStatus,\r
&CpuFeaturesData->CpuFlags\r
);\r
}\r