2 CPU Features Initialize functions.
4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "RegisterCpuFeatures.h"
17 CHAR16
*mDependTypeStr
[] = {L
"None", L
"Thread", L
"Core", L
"Package", L
"Invalid" };
18 CHAR16
*mRegisterTypeStr
[] = {L
"MSR", L
"CR", L
"MMIO", L
"CACHE", L
"SEMAP", L
"INVALID" };
21 Worker function to save PcdCpuFeaturesCapability.
23 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
27 IN UINT8
*SupportedFeatureMask
33 BitMaskSize
= PcdGetSize (PcdCpuFeaturesCapability
);
34 Status
= PcdSetPtrS (PcdCpuFeaturesCapability
, &BitMaskSize
, SupportedFeatureMask
);
35 ASSERT_EFI_ERROR (Status
);
39 Worker function to save PcdCpuFeaturesSetting.
41 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
45 IN UINT8
*SupportedFeatureMask
51 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
52 Status
= PcdSetPtrS (PcdCpuFeaturesSetting
, &BitMaskSize
, SupportedFeatureMask
);
53 ASSERT_EFI_ERROR (Status
);
57 Worker function to get PcdCpuFeaturesSupport.
59 @return The pointer to CPU feature bits mask buffer.
66 UINT8
*SupportBitMask
;
68 SupportBitMask
= AllocateCopyPool (
69 PcdGetSize (PcdCpuFeaturesSupport
),
70 PcdGetPtr (PcdCpuFeaturesSupport
)
72 ASSERT (SupportBitMask
!= NULL
);
74 return SupportBitMask
;
78 Worker function to get PcdCpuFeaturesUserConfiguration.
80 @return The pointer to CPU feature bits mask buffer.
87 UINT8
*SupportBitMask
;
89 SupportBitMask
= AllocateCopyPool (
90 PcdGetSize (PcdCpuFeaturesUserConfiguration
),
91 PcdGetPtr (PcdCpuFeaturesUserConfiguration
)
93 ASSERT (SupportBitMask
!= NULL
);
95 return SupportBitMask
;
99 Collects CPU type and feature information.
101 @param[in, out] CpuInfo The pointer to CPU feature information
105 IN OUT REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
108 CPUID_VERSION_INFO_EAX Eax
;
109 CPUID_VERSION_INFO_ECX Ecx
;
110 CPUID_VERSION_INFO_EDX Edx
;
111 UINT32 DisplayedFamily
;
112 UINT32 DisplayedModel
;
114 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, &Ecx
.Uint32
, &Edx
.Uint32
);
116 DisplayedFamily
= Eax
.Bits
.FamilyId
;
117 if (Eax
.Bits
.FamilyId
== 0x0F) {
118 DisplayedFamily
|= (Eax
.Bits
.ExtendedFamilyId
<< 4);
121 DisplayedModel
= Eax
.Bits
.Model
;
122 if (Eax
.Bits
.FamilyId
== 0x06 || Eax
.Bits
.FamilyId
== 0x0f) {
123 DisplayedModel
|= (Eax
.Bits
.ExtendedModelId
<< 4);
126 CpuInfo
->DisplayFamily
= DisplayedFamily
;
127 CpuInfo
->DisplayModel
= DisplayedModel
;
128 CpuInfo
->SteppingId
= Eax
.Bits
.SteppingId
;
129 CpuInfo
->ProcessorType
= Eax
.Bits
.ProcessorType
;
130 CpuInfo
->CpuIdVersionInfoEcx
.Uint32
= Ecx
.Uint32
;
131 CpuInfo
->CpuIdVersionInfoEdx
.Uint32
= Edx
.Uint32
;
135 Prepares for private data used for CPU features.
137 @param[in] NumberOfCpus Number of processor in system
140 CpuInitDataInitialize (
141 IN UINTN NumberOfCpus
145 UINTN ProcessorNumber
;
146 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
147 CPU_FEATURES_ENTRY
*CpuFeature
;
148 CPU_FEATURES_INIT_ORDER
*InitOrder
;
149 CPU_FEATURES_DATA
*CpuFeaturesData
;
154 EFI_CPU_PHYSICAL_LOCATION
*Location
;
155 BOOLEAN
*CoresVisited
;
157 ACPI_CPU_DATA
*AcpiCpuData
;
158 CPU_STATUS_INFORMATION
*CpuStatus
;
159 UINT32
*ValidCoreCountPerPackage
;
165 CpuFeaturesData
= GetCpuFeaturesData ();
166 CpuFeaturesData
->InitOrder
= AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
167 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
170 // Collect CPU Features information
172 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
173 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
174 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
175 ASSERT (CpuFeature
->InitializeFunc
!= NULL
);
176 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
177 CpuFeature
->ConfigData
= CpuFeature
->GetConfigDataFunc (NumberOfCpus
);
179 Entry
= Entry
->ForwardLink
;
182 CpuFeaturesData
->NumberOfCpus
= (UINT32
) NumberOfCpus
;
184 AcpiCpuData
= GetAcpiCpuData ();
185 ASSERT (AcpiCpuData
!= NULL
);
186 CpuFeaturesData
->AcpiCpuData
= AcpiCpuData
;
188 CpuStatus
= &AcpiCpuData
->CpuStatus
;
189 Location
= AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
);
190 ASSERT (Location
!= NULL
);
191 AcpiCpuData
->ApLocation
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Location
;
193 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
194 InitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
195 InitOrder
->FeaturesSupportedMask
= AllocateZeroPool (CpuFeaturesData
->BitMaskSize
);
196 ASSERT (InitOrder
->FeaturesSupportedMask
!= NULL
);
197 InitializeListHead (&InitOrder
->OrderList
);
198 Status
= GetProcessorInformation (ProcessorNumber
, &ProcessorInfoBuffer
);
199 ASSERT_EFI_ERROR (Status
);
201 &InitOrder
->CpuInfo
.ProcessorInfo
,
202 &ProcessorInfoBuffer
,
203 sizeof (EFI_PROCESSOR_INFORMATION
)
206 &Location
[ProcessorNumber
],
207 &ProcessorInfoBuffer
.Location
,
208 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
212 // Collect CPU package count info.
214 if (Package
< ProcessorInfoBuffer
.Location
.Package
) {
215 Package
= ProcessorInfoBuffer
.Location
.Package
;
218 // Collect CPU max core count info.
220 if (Core
< ProcessorInfoBuffer
.Location
.Core
) {
221 Core
= ProcessorInfoBuffer
.Location
.Core
;
224 // Collect CPU max thread count info.
226 if (Thread
< ProcessorInfoBuffer
.Location
.Thread
) {
227 Thread
= ProcessorInfoBuffer
.Location
.Thread
;
230 CpuStatus
->PackageCount
= Package
+ 1;
231 CpuStatus
->MaxCoreCount
= Core
+ 1;
232 CpuStatus
->MaxThreadCount
= Thread
+ 1;
233 DEBUG ((DEBUG_INFO
, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",
234 CpuStatus
->PackageCount
,
235 CpuStatus
->MaxCoreCount
,
236 CpuStatus
->MaxThreadCount
));
239 // Collect valid core count in each package because not all cores are valid.
241 ValidCoreCountPerPackage
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
);
242 ASSERT (ValidCoreCountPerPackage
!= 0);
243 CpuStatus
->ValidCoreCountPerPackage
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ValidCoreCountPerPackage
;
244 CoresVisited
= AllocatePool (sizeof (BOOLEAN
) * CpuStatus
->MaxCoreCount
);
245 ASSERT (CoresVisited
!= NULL
);
247 for (Index
= 0; Index
< CpuStatus
->PackageCount
; Index
++ ) {
248 ZeroMem (CoresVisited
, sizeof (BOOLEAN
) * CpuStatus
->MaxCoreCount
);
250 // Collect valid cores in Current package.
252 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
253 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
254 if (Location
->Package
== Index
&& !CoresVisited
[Location
->Core
] ) {
256 // The ValidCores position for Location->Core is valid.
257 // The possible values in ValidCores[Index] are 0 or 1.
258 // FALSE means no valid threads in this Core.
259 // TRUE means have valid threads in this core, no matter the thead count is 1 or more.
261 CoresVisited
[Location
->Core
] = TRUE
;
262 ValidCoreCountPerPackage
[Index
]++;
266 FreePool (CoresVisited
);
268 for (Index
= 0; Index
<= Package
; Index
++) {
269 DEBUG ((DEBUG_INFO
, "Package: %d, Valid Core : %d\n", Index
, ValidCoreCountPerPackage
[Index
]));
272 CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
273 ASSERT (CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
!= NULL
);
274 CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
275 ASSERT (CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
!= NULL
);
278 // Get support and configuration PCDs
280 CpuFeaturesData
->SupportPcd
= GetSupportPcd ();
281 CpuFeaturesData
->ConfigurationPcd
= GetConfigurationPcd ();
285 Worker function to do OR operation on CPU feature supported bits mask buffer.
287 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
288 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
292 IN UINT8
*SupportedFeatureMask
,
293 IN UINT8
*OrFeatureBitMask
301 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
302 Data1
= SupportedFeatureMask
;
303 Data2
= OrFeatureBitMask
;
304 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
305 *(Data1
++) |= *(Data2
++);
310 Worker function to do AND operation on CPU feature supported bits mask buffer.
312 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
313 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
317 IN UINT8
*SupportedFeatureMask
,
318 IN UINT8
*AndFeatureBitMask
326 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
327 Data1
= SupportedFeatureMask
;
328 Data2
= AndFeatureBitMask
;
329 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
330 *(Data1
++) &= *(Data2
++);
335 Worker function to clean bit operation on CPU feature supported bits mask buffer.
337 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
338 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
341 SupportedMaskCleanBit (
342 IN UINT8
*SupportedFeatureMask
,
343 IN UINT8
*AndFeatureBitMask
351 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
352 Data1
= SupportedFeatureMask
;
353 Data2
= AndFeatureBitMask
;
354 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
355 *(Data1
++) &= ~(*(Data2
++));
360 Worker function to check if the compared CPU feature set in the CPU feature
361 supported bits mask buffer.
363 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
364 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
366 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
368 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
373 IN UINT8
*SupportedFeatureMask
,
374 IN UINT8
*ComparedFeatureBitMask
382 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
384 Data1
= SupportedFeatureMask
;
385 Data2
= ComparedFeatureBitMask
;
386 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
387 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
395 Collects processor data for calling processor.
397 @param[in,out] Buffer The pointer to private data buffer.
401 CollectProcessorData (
405 UINTN ProcessorNumber
;
406 CPU_FEATURES_ENTRY
*CpuFeature
;
407 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
409 CPU_FEATURES_DATA
*CpuFeaturesData
;
411 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
412 ProcessorNumber
= GetProcessorIndex ();
413 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
415 // collect processor information
417 FillProcessorInfo (CpuInfo
);
418 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
419 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
420 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
421 if (IsBitMaskMatch (CpuFeaturesData
->SupportPcd
, CpuFeature
->FeatureMask
)) {
422 if (CpuFeature
->SupportFunc
== NULL
) {
424 // If SupportFunc is NULL, then the feature is supported.
427 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
428 CpuFeature
->FeatureMask
430 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
432 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
433 CpuFeature
->FeatureMask
437 Entry
= Entry
->ForwardLink
;
442 Dump the contents of a CPU register table.
444 @param[in] ProcessorNumber The index of the CPU to show the register table contents
446 @note This service could be called by BSP only.
449 DumpRegisterTableOnProcessor (
450 IN UINTN ProcessorNumber
453 CPU_FEATURES_DATA
*CpuFeaturesData
;
455 CPU_REGISTER_TABLE
*RegisterTable
;
456 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
457 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
458 UINT32 DebugPrintErrorLevel
;
460 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
461 CpuFeaturesData
= GetCpuFeaturesData ();
465 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
466 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
468 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
470 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
471 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
472 switch (RegisterTableEntry
->RegisterType
) {
475 DebugPrintErrorLevel
,
476 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
478 RegisterTableEntry
->Index
,
479 RegisterTableEntry
->ValidBitStart
,
480 RegisterTableEntry
->ValidBitLength
,
481 RegisterTableEntry
->Value
484 case ControlRegister
:
486 DebugPrintErrorLevel
,
487 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
489 RegisterTableEntry
->Index
,
490 RegisterTableEntry
->ValidBitStart
,
491 RegisterTableEntry
->ValidBitLength
,
492 RegisterTableEntry
->Value
497 DebugPrintErrorLevel
,
498 "Processor: %d: MMIO: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
500 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
501 RegisterTableEntry
->ValidBitStart
,
502 RegisterTableEntry
->ValidBitLength
,
503 RegisterTableEntry
->Value
508 DebugPrintErrorLevel
,
509 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
511 RegisterTableEntry
->Index
,
512 RegisterTableEntry
->ValidBitStart
,
513 RegisterTableEntry
->ValidBitLength
,
514 RegisterTableEntry
->Value
519 DebugPrintErrorLevel
,
520 "Processor: %d: Semaphore: Scope Value: %s\r\n",
522 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
533 Get the biggest dependence type.
534 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
536 @param[in] BeforeDep Before dependence type.
537 @param[in] AfterDep After dependence type.
538 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.
539 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.
541 @retval Return the biggest dependence type.
543 CPU_FEATURE_DEPENDENCE_TYPE
545 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
,
546 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep
,
547 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
,
548 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
551 CPU_FEATURE_DEPENDENCE_TYPE Bigger
;
553 Bigger
= MAX (BeforeDep
, AfterDep
);
554 Bigger
= MAX (Bigger
, NoneNeibBeforeDep
);
555 return MAX(Bigger
, NoneNeibAfterDep
);
559 Analysis register CPU features on each processor and save CPU setting in CPU register table.
561 @param[in] NumberOfCpus Number of processor in system
565 AnalysisProcessorFeatures (
566 IN UINTN NumberOfCpus
570 UINTN ProcessorNumber
;
571 CPU_FEATURES_ENTRY
*CpuFeature
;
572 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
573 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
574 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
576 CPU_FEATURES_DATA
*CpuFeaturesData
;
577 LIST_ENTRY
*NextEntry
;
578 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
580 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
581 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
582 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
;
583 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
;
585 CpuFeaturesData
= GetCpuFeaturesData ();
586 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
587 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
588 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
589 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
590 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
592 // Calculate the last capability on all processors
594 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
);
597 // Calculate the last setting
600 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
601 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
602 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->ConfigurationPcd
);
605 // Save PCDs and display CPU PCDs
607 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
);
608 SetSettingPcd (CpuFeaturesData
->SettingPcd
);
611 // Dump the last CPU feature list
614 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
615 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
616 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
617 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
618 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
)) {
619 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
)) {
620 DEBUG ((DEBUG_INFO
, "[Enable ] "));
622 DEBUG ((DEBUG_INFO
, "[Disable ] "));
625 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
627 DumpCpuFeature (CpuFeature
);
628 Entry
= Entry
->ForwardLink
;
630 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesSupport:\n"));
631 DumpCpuFeatureMask (CpuFeaturesData
->SupportPcd
);
632 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesUserConfiguration:\n"));
633 DumpCpuFeatureMask (CpuFeaturesData
->ConfigurationPcd
);
634 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
635 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
);
636 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesSetting:\n"));
637 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
);
640 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
641 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
642 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
643 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
645 // Insert each feature into processor's order list
647 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
648 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
)) {
649 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
650 ASSERT (CpuFeatureInOrder
!= NULL
);
651 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
653 Entry
= Entry
->ForwardLink
;
656 // Go through ordered feature list to initialize CPU features
658 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
659 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
660 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
661 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
664 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
)) {
665 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
666 if (EFI_ERROR (Status
)) {
668 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
670 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
);
671 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
672 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
674 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
675 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
);
681 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
682 if (EFI_ERROR (Status
)) {
683 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
684 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
686 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
687 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
);
695 NextEntry
= Entry
->ForwardLink
;
696 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
697 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
700 // If feature has dependence with the next feature (ONLY care core/package dependency).
701 // and feature initialize succeed, add sync semaphere here.
703 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
704 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
706 // Check whether next feature has After type dependence with not neighborhood CPU
707 // Features in former CPU features.
709 NoneNeibAfterDep
= DetectNoneNeighborhoodFeatureScope(NextCpuFeatureInOrder
, FALSE
, &CpuInitOrder
->OrderList
);
711 BeforeDep
= NoneDepType
;
712 AfterDep
= NoneDepType
;
713 NoneNeibAfterDep
= NoneDepType
;
716 // Check whether current feature has Before type dependence with none neighborhood
717 // CPU features in after Cpu features.
719 NoneNeibBeforeDep
= DetectNoneNeighborhoodFeatureScope(CpuFeatureInOrder
, TRUE
, &CpuInitOrder
->OrderList
);
722 // Get the biggest dependence and add semaphore for it.
723 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
725 BeforeDep
= BiggestDep(BeforeDep
, AfterDep
, NoneNeibBeforeDep
, NoneNeibAfterDep
);
726 if (BeforeDep
> ThreadDepType
) {
727 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
731 Entry
= Entry
->ForwardLink
;
735 // Dump PcdCpuFeaturesSetting again because this value maybe updated
736 // again during initialize the features.
738 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
739 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
);
742 // Dump the RegisterTable
744 DumpRegisterTableOnProcessor (ProcessorNumber
);
749 Increment semaphore by 1.
751 @param Sem IN: 32-bit unsigned integer
755 LibReleaseSemaphore (
756 IN OUT
volatile UINT32
*Sem
759 InterlockedIncrement (Sem
);
763 Decrement the semaphore by 1 if it is not zero.
765 Performs an atomic decrement operation for semaphore.
766 The compare exchange operation must be performed using
769 @param Sem IN: 32-bit unsigned integer
773 LibWaitForSemaphore (
774 IN OUT
volatile UINT32
*Sem
781 } while (Value
== 0 ||
782 InterlockedCompareExchange32 (
790 Initialize the CPU registers from a register table.
792 @param[in] RegisterTable The register table for this AP.
793 @param[in] ApLocation AP location info for this ap.
794 @param[in] CpuStatus CPU status info for this CPU.
795 @param[in] CpuFlags Flags data structure used when program the register.
797 @note This service could be called by BSP/APs.
800 ProgramProcessorRegister (
801 IN CPU_REGISTER_TABLE
*RegisterTable
,
802 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
803 IN CPU_STATUS_INFORMATION
*CpuStatus
,
804 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
807 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
810 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
811 volatile UINT32
*SemaphorePtr
;
813 UINT32 PackageThreadsCount
;
814 UINT32 CurrentThread
;
815 UINTN ProcessorIndex
;
817 UINTN ValidThreadCount
;
818 UINT32
*ValidCoreCountPerPackage
;
821 // Traverse Register Table of this logical processor
823 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
825 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
827 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
830 AcquireSpinLock (&CpuFlags
->ConsoleLogLock
);
831 ThreadIndex
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
+
832 ApLocation
->Core
* CpuStatus
->MaxThreadCount
+
836 "Processor = %lu, Entry Index %lu, Type = %s!\n",
839 mRegisterTypeStr
[MIN ((REGISTER_TYPE
)RegisterTableEntry
->RegisterType
, InvalidReg
)]
841 ReleaseSpinLock (&CpuFlags
->ConsoleLogLock
);
845 // Check the type of specified register
847 switch (RegisterTableEntry
->RegisterType
) {
849 // The specified register is Control Register
851 case ControlRegister
:
852 switch (RegisterTableEntry
->Index
) {
854 Value
= AsmReadCr0 ();
855 Value
= (UINTN
) BitFieldWrite64 (
857 RegisterTableEntry
->ValidBitStart
,
858 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
859 RegisterTableEntry
->Value
864 Value
= AsmReadCr2 ();
865 Value
= (UINTN
) BitFieldWrite64 (
867 RegisterTableEntry
->ValidBitStart
,
868 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
869 RegisterTableEntry
->Value
874 Value
= AsmReadCr3 ();
875 Value
= (UINTN
) BitFieldWrite64 (
877 RegisterTableEntry
->ValidBitStart
,
878 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
879 RegisterTableEntry
->Value
884 Value
= AsmReadCr4 ();
885 Value
= (UINTN
) BitFieldWrite64 (
887 RegisterTableEntry
->ValidBitStart
,
888 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
889 RegisterTableEntry
->Value
895 // Do we need to support CR8?
903 // The specified register is Model Specific Register
906 if (RegisterTableEntry
->ValidBitLength
>= 64) {
908 // If length is not less than 64 bits, then directly write without reading
911 RegisterTableEntry
->Index
,
912 RegisterTableEntry
->Value
916 // Set the bit section according to bit start and length
918 AsmMsrBitFieldWrite64 (
919 RegisterTableEntry
->Index
,
920 RegisterTableEntry
->ValidBitStart
,
921 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
922 RegisterTableEntry
->Value
927 // MemoryMapped operations
930 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
931 MmioBitFieldWrite32 (
932 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
933 RegisterTableEntry
->ValidBitStart
,
934 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
935 (UINT32
)RegisterTableEntry
->Value
937 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
940 // Enable or disable cache
944 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
946 if (RegisterTableEntry
->Value
== 0) {
954 // Semaphore works logic like below:
956 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
957 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
959 // All threads (T0...Tn) waits in P() line and continues running
965 // V(0...n) V(0...n) ... V(0...n)
966 // n * P(0) n * P(1) ... n * P(n)
968 switch (RegisterTableEntry
->Value
) {
970 SemaphorePtr
= CpuFlags
->CoreSemaphoreCount
;
972 // Get Offset info for the first thread in the core which current thread belongs to.
974 FirstThread
= (ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
) * CpuStatus
->MaxThreadCount
;
975 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
977 // First Notify all threads in current Core that this thread has ready.
979 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
980 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
983 // Second, check whether all valid threads in current core have ready.
985 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
986 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
991 SemaphorePtr
= CpuFlags
->PackageSemaphoreCount
;
992 ValidCoreCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ValidCoreCountPerPackage
;
994 // Get Offset info for the first thread in the package which current thread belongs to.
996 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
998 // Get the possible threads count for current package.
1000 PackageThreadsCount
= CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
;
1001 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
1003 // Get the valid thread count for current package.
1005 ValidThreadCount
= CpuStatus
->MaxThreadCount
* ValidCoreCountPerPackage
[ApLocation
->Package
];
1008 // Different packages may have different valid cores in them. If driver maintail clearly
1009 // cores number in different packages, the logic will be much complicated.
1010 // Here driver just simply records the max core number in all packages and use it as expect
1011 // core number for all packages.
1012 // In below two steps logic, first current thread will Release semaphore for each thread
1013 // in current package. Maybe some threads are not valid in this package, but driver don't
1014 // care. Second, driver will let current thread wait semaphore for all valid threads in
1015 // current package. Because only the valid threads will do release semaphore for this
1016 // thread, driver here only need to wait the valid thread count.
1020 // First Notify ALL THREADS in current package that this thread has ready.
1022 for (ProcessorIndex
= 0; ProcessorIndex
< PackageThreadsCount
; ProcessorIndex
++) {
1023 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1026 // Second, check whether VALID THREADS (not all threads) in current package have ready.
1028 for (ProcessorIndex
= 0; ProcessorIndex
< ValidThreadCount
; ProcessorIndex
++) {
1029 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1045 Programs registers for the calling processor.
1047 @param[in,out] Buffer The pointer to private data buffer.
1052 SetProcessorRegister (
1056 CPU_FEATURES_DATA
*CpuFeaturesData
;
1057 CPU_REGISTER_TABLE
*RegisterTable
;
1058 CPU_REGISTER_TABLE
*RegisterTables
;
1062 ACPI_CPU_DATA
*AcpiCpuData
;
1064 CpuFeaturesData
= (CPU_FEATURES_DATA
*) Buffer
;
1065 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1067 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->RegisterTable
;
1069 InitApicId
= GetInitialApicId ();
1070 RegisterTable
= NULL
;
1071 ProcIndex
= (UINTN
)-1;
1072 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1073 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1074 RegisterTable
= &RegisterTables
[Index
];
1079 ASSERT (RegisterTable
!= NULL
);
1081 ProgramProcessorRegister (
1083 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->ApLocation
+ ProcIndex
,
1084 &AcpiCpuData
->CpuStatus
,
1085 &CpuFeaturesData
->CpuFlags
1090 Performs CPU features detection.
1092 This service will invoke MP service to check CPU features'
1093 capabilities on BSP/APs.
1095 @note This service could be called by BSP only.
1104 UINTN NumberOfEnabledProcessors
;
1105 CPU_FEATURES_DATA
*CpuFeaturesData
;
1107 CpuFeaturesData
= GetCpuFeaturesData();
1109 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
1111 CpuInitDataInitialize (NumberOfCpus
);
1114 // Wakeup all APs for data collection.
1116 StartupAPsWorker (CollectProcessorData
, NULL
);
1119 // Collect data on BSP
1121 CollectProcessorData (CpuFeaturesData
);
1123 AnalysisProcessorFeatures (NumberOfCpus
);