2 CPU Features Initialize functions.
4 Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "RegisterCpuFeatures.h"
11 CHAR16
*mDependTypeStr
[] = {L
"None", L
"Thread", L
"Core", L
"Package", L
"Invalid" };
14 Worker function to save PcdCpuFeaturesCapability.
16 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
17 @param[in] BitMaskSize CPU feature bits mask buffer size.
22 IN UINT8
*SupportedFeatureMask
,
28 Status
= PcdSetPtrS (PcdCpuFeaturesCapability
, &BitMaskSize
, SupportedFeatureMask
);
29 ASSERT_EFI_ERROR (Status
);
33 Worker function to save PcdCpuFeaturesSetting.
35 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
36 @param[in] BitMaskSize CPU feature bits mask buffer size.
40 IN UINT8
*SupportedFeatureMask
,
46 Status
= PcdSetPtrS (PcdCpuFeaturesSetting
, &BitMaskSize
, SupportedFeatureMask
);
47 ASSERT_EFI_ERROR (Status
);
51 Collects CPU type and feature information.
53 @param[in, out] CpuInfo The pointer to CPU feature information
57 IN OUT REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
60 CPUID_VERSION_INFO_EAX Eax
;
61 CPUID_VERSION_INFO_ECX Ecx
;
62 CPUID_VERSION_INFO_EDX Edx
;
63 UINT32 DisplayedFamily
;
64 UINT32 DisplayedModel
;
66 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, &Ecx
.Uint32
, &Edx
.Uint32
);
68 DisplayedFamily
= Eax
.Bits
.FamilyId
;
69 if (Eax
.Bits
.FamilyId
== 0x0F) {
70 DisplayedFamily
|= (Eax
.Bits
.ExtendedFamilyId
<< 4);
73 DisplayedModel
= Eax
.Bits
.Model
;
74 if (Eax
.Bits
.FamilyId
== 0x06 || Eax
.Bits
.FamilyId
== 0x0f) {
75 DisplayedModel
|= (Eax
.Bits
.ExtendedModelId
<< 4);
78 CpuInfo
->DisplayFamily
= DisplayedFamily
;
79 CpuInfo
->DisplayModel
= DisplayedModel
;
80 CpuInfo
->SteppingId
= Eax
.Bits
.SteppingId
;
81 CpuInfo
->ProcessorType
= Eax
.Bits
.ProcessorType
;
82 CpuInfo
->CpuIdVersionInfoEcx
.Uint32
= Ecx
.Uint32
;
83 CpuInfo
->CpuIdVersionInfoEdx
.Uint32
= Edx
.Uint32
;
87 Prepares for private data used for CPU features.
91 CpuInitDataInitialize (
96 UINTN ProcessorNumber
;
97 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
98 CPU_FEATURES_ENTRY
*CpuFeature
;
99 CPU_FEATURES_INIT_ORDER
*InitOrder
;
100 CPU_FEATURES_DATA
*CpuFeaturesData
;
105 EFI_CPU_PHYSICAL_LOCATION
*Location
;
106 BOOLEAN
*CoresVisited
;
111 ACPI_CPU_DATA
*AcpiCpuData
;
112 CPU_STATUS_INFORMATION
*CpuStatus
;
113 UINT32
*ValidCoreCountPerPackage
;
115 UINTN NumberOfEnabledProcessors
;
121 CpuFeaturesData
= GetCpuFeaturesData ();
124 // Initialize CpuFeaturesData->MpService as early as possile, so later function can use it.
126 CpuFeaturesData
->MpService
= GetMpService ();
128 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
130 CpuFeaturesData
->InitOrder
= AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
131 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
134 // Collect CPU Features information
136 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
137 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
138 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
139 ASSERT (CpuFeature
->InitializeFunc
!= NULL
);
140 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
141 CpuFeature
->ConfigData
= CpuFeature
->GetConfigDataFunc (NumberOfCpus
);
143 Entry
= Entry
->ForwardLink
;
146 CpuFeaturesData
->NumberOfCpus
= (UINT32
) NumberOfCpus
;
148 AcpiCpuData
= GetAcpiCpuData ();
149 ASSERT (AcpiCpuData
!= NULL
);
150 CpuFeaturesData
->AcpiCpuData
= AcpiCpuData
;
152 CpuStatus
= &AcpiCpuData
->CpuStatus
;
153 Location
= AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
);
154 ASSERT (Location
!= NULL
);
155 AcpiCpuData
->ApLocation
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Location
;
157 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
158 InitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
159 InitOrder
->FeaturesSupportedMask
= AllocateZeroPool (CpuFeaturesData
->BitMaskSize
);
160 ASSERT (InitOrder
->FeaturesSupportedMask
!= NULL
);
161 InitializeListHead (&InitOrder
->OrderList
);
162 Status
= GetProcessorInformation (ProcessorNumber
, &ProcessorInfoBuffer
);
163 ASSERT_EFI_ERROR (Status
);
165 &InitOrder
->CpuInfo
.ProcessorInfo
,
166 &ProcessorInfoBuffer
,
167 sizeof (EFI_PROCESSOR_INFORMATION
)
170 &Location
[ProcessorNumber
],
171 &ProcessorInfoBuffer
.Location
,
172 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
176 // Collect CPU package count info.
178 if (Package
< ProcessorInfoBuffer
.Location
.Package
) {
179 Package
= ProcessorInfoBuffer
.Location
.Package
;
182 // Collect CPU max core count info.
184 if (Core
< ProcessorInfoBuffer
.Location
.Core
) {
185 Core
= ProcessorInfoBuffer
.Location
.Core
;
188 // Collect CPU max thread count info.
190 if (Thread
< ProcessorInfoBuffer
.Location
.Thread
) {
191 Thread
= ProcessorInfoBuffer
.Location
.Thread
;
194 CpuStatus
->PackageCount
= Package
+ 1;
195 CpuStatus
->MaxCoreCount
= Core
+ 1;
196 CpuStatus
->MaxThreadCount
= Thread
+ 1;
197 DEBUG ((DEBUG_INFO
, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",
198 CpuStatus
->PackageCount
,
199 CpuStatus
->MaxCoreCount
,
200 CpuStatus
->MaxThreadCount
));
203 // Collect valid core count in each package because not all cores are valid.
205 ValidCoreCountPerPackage
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
);
206 ASSERT (ValidCoreCountPerPackage
!= 0);
207 CpuStatus
->ValidCoreCountPerPackage
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ValidCoreCountPerPackage
;
208 CoresVisited
= AllocatePool (sizeof (BOOLEAN
) * CpuStatus
->MaxCoreCount
);
209 ASSERT (CoresVisited
!= NULL
);
211 for (Index
= 0; Index
< CpuStatus
->PackageCount
; Index
++ ) {
212 ZeroMem (CoresVisited
, sizeof (BOOLEAN
) * CpuStatus
->MaxCoreCount
);
214 // Collect valid cores in Current package.
216 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
217 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
218 if (Location
->Package
== Index
&& !CoresVisited
[Location
->Core
] ) {
220 // The ValidCores position for Location->Core is valid.
221 // The possible values in ValidCores[Index] are 0 or 1.
222 // FALSE means no valid threads in this Core.
223 // TRUE means have valid threads in this core, no matter the thead count is 1 or more.
225 CoresVisited
[Location
->Core
] = TRUE
;
226 ValidCoreCountPerPackage
[Index
]++;
230 FreePool (CoresVisited
);
232 for (Index
= 0; Index
<= Package
; Index
++) {
233 DEBUG ((DEBUG_INFO
, "Package: %d, Valid Core : %d\n", Index
, ValidCoreCountPerPackage
[Index
]));
236 CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
237 ASSERT (CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
!= NULL
);
238 CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
239 ASSERT (CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
!= NULL
);
242 // Initialize CpuFeaturesData->InitOrder[].CpuInfo.First
246 // Set First.Package for each thread belonging to the first package.
249 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
250 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
251 First
= MIN (Location
->Package
, First
);
253 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
254 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
255 if (Location
->Package
== First
) {
256 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Package
= 1;
261 // Set First.Die/Tile/Module for each thread assuming:
262 // single Die under each package, single Tile under each Die, single Module under each Tile
264 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
265 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Die
= 1;
266 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Tile
= 1;
267 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Module
= 1;
270 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
272 // Set First.Core for each thread in the first core of each package.
275 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
276 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
277 if (Location
->Package
== PackageIndex
) {
278 First
= MIN (Location
->Core
, First
);
282 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
283 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
284 if (Location
->Package
== PackageIndex
&& Location
->Core
== First
) {
285 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Core
= 1;
290 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
291 for (CoreIndex
= 0; CoreIndex
< CpuStatus
->MaxCoreCount
; CoreIndex
++) {
293 // Set First.Thread for the first thread of each core.
296 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
297 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
298 if (Location
->Package
== PackageIndex
&& Location
->Core
== CoreIndex
) {
299 First
= MIN (Location
->Thread
, First
);
303 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
304 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
305 if (Location
->Package
== PackageIndex
&& Location
->Core
== CoreIndex
&& Location
->Thread
== First
) {
306 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Thread
= 1;
314 Worker function to do OR operation on CPU feature supported bits mask buffer.
316 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
317 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
318 @param[in] BitMaskSize The CPU feature bits mask buffer size.
323 IN UINT8
*SupportedFeatureMask
,
324 IN UINT8
*OrFeatureBitMask
,
325 IN UINT32 BitMaskSize
332 Data1
= SupportedFeatureMask
;
333 Data2
= OrFeatureBitMask
;
334 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
335 *(Data1
++) |= *(Data2
++);
340 Worker function to do AND operation on CPU feature supported bits mask buffer.
342 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
343 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
344 @param[in] BitMaskSize CPU feature bits mask buffer size.
349 IN UINT8
*SupportedFeatureMask
,
350 IN CONST UINT8
*AndFeatureBitMask
,
351 IN UINT32 BitMaskSize
358 Data1
= SupportedFeatureMask
;
359 Data2
= AndFeatureBitMask
;
360 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
361 *(Data1
++) &= *(Data2
++);
366 Worker function to clean bit operation on CPU feature supported bits mask buffer.
368 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
369 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
370 @param[in] BitMaskSize CPU feature bits mask buffer size.
373 SupportedMaskCleanBit (
374 IN UINT8
*SupportedFeatureMask
,
375 IN UINT8
*AndFeatureBitMask
,
376 IN UINT32 BitMaskSize
383 Data1
= SupportedFeatureMask
;
384 Data2
= AndFeatureBitMask
;
385 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
386 *(Data1
++) &= ~(*(Data2
++));
391 Worker function to check if the compared CPU feature set in the CPU feature
392 supported bits mask buffer.
394 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
395 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
396 @param[in] BitMaskSize CPU feature bits mask buffer size.
398 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
400 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
405 IN UINT8
*SupportedFeatureMask
,
406 IN UINT8
*ComparedFeatureBitMask
,
407 IN UINT32 BitMaskSize
414 Data1
= SupportedFeatureMask
;
415 Data2
= ComparedFeatureBitMask
;
416 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
417 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
425 Collects processor data for calling processor.
427 @param[in,out] Buffer The pointer to private data buffer.
431 CollectProcessorData (
435 UINTN ProcessorNumber
;
436 CPU_FEATURES_ENTRY
*CpuFeature
;
437 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
439 CPU_FEATURES_DATA
*CpuFeaturesData
;
441 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
442 ProcessorNumber
= GetProcessorIndex (CpuFeaturesData
);
443 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
445 // collect processor information
447 FillProcessorInfo (CpuInfo
);
448 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
449 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
450 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
451 if (CpuFeature
->SupportFunc
== NULL
) {
453 // If SupportFunc is NULL, then the feature is supported.
456 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
457 CpuFeature
->FeatureMask
,
458 CpuFeaturesData
->BitMaskSize
460 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
462 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
463 CpuFeature
->FeatureMask
,
464 CpuFeaturesData
->BitMaskSize
467 Entry
= Entry
->ForwardLink
;
472 Dump the contents of a CPU register table.
474 @param[in] ProcessorNumber The index of the CPU to show the register table contents
476 @note This service could be called by BSP only.
479 DumpRegisterTableOnProcessor (
480 IN UINTN ProcessorNumber
483 CPU_FEATURES_DATA
*CpuFeaturesData
;
485 CPU_REGISTER_TABLE
*RegisterTable
;
486 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
487 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
488 UINT32 DebugPrintErrorLevel
;
490 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
491 CpuFeaturesData
= GetCpuFeaturesData ();
495 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
496 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
498 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
500 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
501 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
502 switch (RegisterTableEntry
->RegisterType
) {
505 DebugPrintErrorLevel
,
506 "Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
509 RegisterTableEntry
->Index
,
510 RegisterTableEntry
->ValidBitStart
,
511 RegisterTableEntry
->ValidBitLength
,
512 RegisterTableEntry
->Value
515 case ControlRegister
:
517 DebugPrintErrorLevel
,
518 "Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
521 RegisterTableEntry
->Index
,
522 RegisterTableEntry
->ValidBitStart
,
523 RegisterTableEntry
->ValidBitLength
,
524 RegisterTableEntry
->Value
529 DebugPrintErrorLevel
,
530 "Processor: %04d: Index %04d, MMIO : %08lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
533 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
534 RegisterTableEntry
->ValidBitStart
,
535 RegisterTableEntry
->ValidBitLength
,
536 RegisterTableEntry
->Value
541 DebugPrintErrorLevel
,
542 "Processor: %04d: Index %04d, CACHE: %08lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
545 RegisterTableEntry
->Index
,
546 RegisterTableEntry
->ValidBitStart
,
547 RegisterTableEntry
->ValidBitLength
,
548 RegisterTableEntry
->Value
553 DebugPrintErrorLevel
,
554 "Processor: %04d: Index %04d, SEMAP: %s\r\n",
557 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
568 Get the biggest dependence type.
569 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
571 @param[in] BeforeDep Before dependence type.
572 @param[in] AfterDep After dependence type.
573 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.
574 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.
576 @retval Return the biggest dependence type.
578 CPU_FEATURE_DEPENDENCE_TYPE
580 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
,
581 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep
,
582 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
,
583 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
586 CPU_FEATURE_DEPENDENCE_TYPE Bigger
;
588 Bigger
= MAX (BeforeDep
, AfterDep
);
589 Bigger
= MAX (Bigger
, NoneNeibBeforeDep
);
590 return MAX(Bigger
, NoneNeibAfterDep
);
594 Analysis register CPU features on each processor and save CPU setting in CPU register table.
596 @param[in] NumberOfCpus Number of processor in system
600 AnalysisProcessorFeatures (
601 IN UINTN NumberOfCpus
605 UINTN ProcessorNumber
;
606 CPU_FEATURES_ENTRY
*CpuFeature
;
607 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
608 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
609 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
611 CPU_FEATURES_DATA
*CpuFeaturesData
;
612 LIST_ENTRY
*NextEntry
;
613 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
615 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
616 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
617 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
;
618 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
;
620 CpuFeaturesData
= GetCpuFeaturesData ();
621 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
622 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
623 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
624 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
625 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
627 // Calculate the last capability on all processors
629 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
, CpuFeaturesData
->BitMaskSize
);
632 // Calculate the last setting
634 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
635 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
636 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
639 // Dump the last CPU feature list
642 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
643 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
644 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
645 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
646 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
647 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
648 DEBUG ((DEBUG_INFO
, "[Enable ] "));
650 DEBUG ((DEBUG_INFO
, "[Disable ] "));
653 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
655 DumpCpuFeature (CpuFeature
, CpuFeaturesData
->BitMaskSize
);
656 Entry
= Entry
->ForwardLink
;
658 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
659 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
660 DEBUG ((DEBUG_INFO
, "Origin PcdCpuFeaturesSetting:\n"));
661 DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
662 DEBUG ((DEBUG_INFO
, "Final PcdCpuFeaturesSetting:\n"));
663 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
667 // Save PCDs and display CPU PCDs
669 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
670 SetSettingPcd (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
672 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
673 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
674 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
675 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
677 // Insert each feature into processor's order list
679 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
680 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
681 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
682 ASSERT (CpuFeatureInOrder
!= NULL
);
683 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
685 Entry
= Entry
->ForwardLink
;
688 // Go through ordered feature list to initialize CPU features
690 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
691 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
692 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
693 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
696 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
697 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
698 if (EFI_ERROR (Status
)) {
700 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
702 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
703 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
704 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
706 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
707 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
713 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
714 if (EFI_ERROR (Status
)) {
715 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
716 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
718 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
719 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
727 NextEntry
= Entry
->ForwardLink
;
728 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
729 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
732 // If feature has dependence with the next feature (ONLY care core/package dependency).
733 // and feature initialize succeed, add sync semaphere here.
735 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
736 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
738 // Check whether next feature has After type dependence with not neighborhood CPU
739 // Features in former CPU features.
741 NoneNeibAfterDep
= DetectNoneNeighborhoodFeatureScope(NextCpuFeatureInOrder
, FALSE
, &CpuInitOrder
->OrderList
);
743 BeforeDep
= NoneDepType
;
744 AfterDep
= NoneDepType
;
745 NoneNeibAfterDep
= NoneDepType
;
748 // Check whether current feature has Before type dependence with none neighborhood
749 // CPU features in after Cpu features.
751 NoneNeibBeforeDep
= DetectNoneNeighborhoodFeatureScope(CpuFeatureInOrder
, TRUE
, &CpuInitOrder
->OrderList
);
754 // Get the biggest dependence and add semaphore for it.
755 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
757 BeforeDep
= BiggestDep(BeforeDep
, AfterDep
, NoneNeibBeforeDep
, NoneNeibAfterDep
);
758 if (BeforeDep
> ThreadDepType
) {
759 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
763 Entry
= Entry
->ForwardLink
;
767 // Dump PcdCpuFeaturesSetting again because this value maybe updated
768 // again during initialize the features.
770 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
771 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
774 // Dump the RegisterTable
776 DumpRegisterTableOnProcessor (ProcessorNumber
);
781 Increment semaphore by 1.
783 @param Sem IN: 32-bit unsigned integer
787 LibReleaseSemaphore (
788 IN OUT
volatile UINT32
*Sem
791 InterlockedIncrement (Sem
);
795 Decrement the semaphore by 1 if it is not zero.
797 Performs an atomic decrement operation for semaphore.
798 The compare exchange operation must be performed using
801 @param Sem IN: 32-bit unsigned integer
805 LibWaitForSemaphore (
806 IN OUT
volatile UINT32
*Sem
813 } while (Value
== 0 ||
814 InterlockedCompareExchange32 (
822 Read / write CR value.
824 @param[in] CrIndex The CR index which need to read/write.
825 @param[in] Read Read or write. TRUE is read.
826 @param[in,out] CrValue CR value.
828 @retval EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.
834 IN OUT UINTN
*CrValue
840 *CrValue
= AsmReadCr0 ();
842 AsmWriteCr0 (*CrValue
);
847 *CrValue
= AsmReadCr2 ();
849 AsmWriteCr2 (*CrValue
);
854 *CrValue
= AsmReadCr3 ();
856 AsmWriteCr3 (*CrValue
);
861 *CrValue
= AsmReadCr4 ();
863 AsmWriteCr4 (*CrValue
);
867 return EFI_UNSUPPORTED
;;
874 Initialize the CPU registers from a register table.
876 @param[in] RegisterTable The register table for this AP.
877 @param[in] ApLocation AP location info for this ap.
878 @param[in] CpuStatus CPU status info for this CPU.
879 @param[in] CpuFlags Flags data structure used when program the register.
881 @note This service could be called by BSP/APs.
884 ProgramProcessorRegister (
885 IN CPU_REGISTER_TABLE
*RegisterTable
,
886 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
887 IN CPU_STATUS_INFORMATION
*CpuStatus
,
888 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
891 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
894 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
895 volatile UINT32
*SemaphorePtr
;
897 UINT32 PackageThreadsCount
;
898 UINT32 CurrentThread
;
899 UINTN ProcessorIndex
;
900 UINTN ValidThreadCount
;
901 UINT32
*ValidCoreCountPerPackage
;
906 // Traverse Register Table of this logical processor
908 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
910 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
912 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
915 // Check the type of specified register
917 switch (RegisterTableEntry
->RegisterType
) {
919 // The specified register is Control Register
921 case ControlRegister
:
922 Status
= ReadWriteCr (RegisterTableEntry
->Index
, TRUE
, &Value
);
923 if (EFI_ERROR (Status
)) {
926 if (RegisterTableEntry
->TestThenWrite
) {
927 CurrentValue
= BitFieldRead64 (
929 RegisterTableEntry
->ValidBitStart
,
930 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
932 if (CurrentValue
== RegisterTableEntry
->Value
) {
936 Value
= (UINTN
) BitFieldWrite64 (
938 RegisterTableEntry
->ValidBitStart
,
939 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
940 RegisterTableEntry
->Value
942 ReadWriteCr (RegisterTableEntry
->Index
, FALSE
, &Value
);
946 // The specified register is Model Specific Register
949 if (RegisterTableEntry
->TestThenWrite
) {
950 Value
= (UINTN
)AsmReadMsr64 (RegisterTableEntry
->Index
);
951 if (RegisterTableEntry
->ValidBitLength
>= 64) {
952 if (Value
== RegisterTableEntry
->Value
) {
956 CurrentValue
= BitFieldRead64 (
958 RegisterTableEntry
->ValidBitStart
,
959 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
961 if (CurrentValue
== RegisterTableEntry
->Value
) {
967 if (RegisterTableEntry
->ValidBitLength
>= 64) {
969 // If length is not less than 64 bits, then directly write without reading
972 RegisterTableEntry
->Index
,
973 RegisterTableEntry
->Value
977 // Set the bit section according to bit start and length
979 AsmMsrBitFieldWrite64 (
980 RegisterTableEntry
->Index
,
981 RegisterTableEntry
->ValidBitStart
,
982 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
983 RegisterTableEntry
->Value
988 // MemoryMapped operations
991 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
992 MmioBitFieldWrite32 (
993 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
994 RegisterTableEntry
->ValidBitStart
,
995 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
996 (UINT32
)RegisterTableEntry
->Value
998 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
1001 // Enable or disable cache
1005 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
1007 if (RegisterTableEntry
->Value
== 0) {
1015 // Semaphore works logic like below:
1017 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
1018 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
1020 // All threads (T0...Tn) waits in P() line and continues running
1026 // V(0...n) V(0...n) ... V(0...n)
1027 // n * P(0) n * P(1) ... n * P(n)
1029 switch (RegisterTableEntry
->Value
) {
1031 SemaphorePtr
= CpuFlags
->CoreSemaphoreCount
;
1033 // Get Offset info for the first thread in the core which current thread belongs to.
1035 FirstThread
= (ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
) * CpuStatus
->MaxThreadCount
;
1036 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
1038 // First Notify all threads in current Core that this thread has ready.
1040 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
1041 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1044 // Second, check whether all valid threads in current core have ready.
1046 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
1047 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1051 case PackageDepType
:
1052 SemaphorePtr
= CpuFlags
->PackageSemaphoreCount
;
1053 ValidCoreCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ValidCoreCountPerPackage
;
1055 // Get Offset info for the first thread in the package which current thread belongs to.
1057 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
1059 // Get the possible threads count for current package.
1061 PackageThreadsCount
= CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
;
1062 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
1064 // Get the valid thread count for current package.
1066 ValidThreadCount
= CpuStatus
->MaxThreadCount
* ValidCoreCountPerPackage
[ApLocation
->Package
];
1069 // Different packages may have different valid cores in them. If driver maintail clearly
1070 // cores number in different packages, the logic will be much complicated.
1071 // Here driver just simply records the max core number in all packages and use it as expect
1072 // core number for all packages.
1073 // In below two steps logic, first current thread will Release semaphore for each thread
1074 // in current package. Maybe some threads are not valid in this package, but driver don't
1075 // care. Second, driver will let current thread wait semaphore for all valid threads in
1076 // current package. Because only the valid threads will do release semaphore for this
1077 // thread, driver here only need to wait the valid thread count.
1081 // First Notify ALL THREADS in current package that this thread has ready.
1083 for (ProcessorIndex
= 0; ProcessorIndex
< PackageThreadsCount
; ProcessorIndex
++) {
1084 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1087 // Second, check whether VALID THREADS (not all threads) in current package have ready.
1089 for (ProcessorIndex
= 0; ProcessorIndex
< ValidThreadCount
; ProcessorIndex
++) {
1090 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1106 Programs registers for the calling processor.
1108 @param[in,out] Buffer The pointer to private data buffer.
1113 SetProcessorRegister (
1117 CPU_FEATURES_DATA
*CpuFeaturesData
;
1118 CPU_REGISTER_TABLE
*RegisterTable
;
1119 CPU_REGISTER_TABLE
*RegisterTables
;
1123 ACPI_CPU_DATA
*AcpiCpuData
;
1125 CpuFeaturesData
= (CPU_FEATURES_DATA
*) Buffer
;
1126 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1128 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->RegisterTable
;
1130 InitApicId
= GetInitialApicId ();
1131 RegisterTable
= NULL
;
1132 ProcIndex
= (UINTN
)-1;
1133 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1134 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1135 RegisterTable
= &RegisterTables
[Index
];
1140 ASSERT (RegisterTable
!= NULL
);
1142 ProgramProcessorRegister (
1144 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->ApLocation
+ ProcIndex
,
1145 &AcpiCpuData
->CpuStatus
,
1146 &CpuFeaturesData
->CpuFlags
1151 Performs CPU features detection.
1153 This service will invoke MP service to check CPU features'
1154 capabilities on BSP/APs.
1156 @note This service could be called by BSP only.
1164 CPU_FEATURES_DATA
*CpuFeaturesData
;
1166 CpuFeaturesData
= GetCpuFeaturesData();
1168 CpuInitDataInitialize ();
1170 if (CpuFeaturesData
->NumberOfCpus
> 1) {
1172 // Wakeup all APs for data collection.
1174 StartupAllAPsWorker (CollectProcessorData
, NULL
);
1178 // Collect data on BSP
1180 CollectProcessorData (CpuFeaturesData
);
1182 AnalysisProcessorFeatures (CpuFeaturesData
->NumberOfCpus
);