2 CPU Features Initialize functions.
4 Copyright (c) 2017 - 2019, 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
24 @param[in] FeatureMaskSize CPU feature bits mask buffer size.
29 IN UINT8
*SupportedFeatureMask
,
30 IN UINT32 FeatureMaskSize
36 BitMaskSize
= PcdGetSize (PcdCpuFeaturesCapability
);
37 ASSERT (FeatureMaskSize
== BitMaskSize
);
39 Status
= PcdSetPtrS (PcdCpuFeaturesCapability
, &BitMaskSize
, SupportedFeatureMask
);
40 ASSERT_EFI_ERROR (Status
);
44 Worker function to save PcdCpuFeaturesSetting.
46 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
50 IN UINT8
*SupportedFeatureMask
56 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
57 Status
= PcdSetPtrS (PcdCpuFeaturesSetting
, &BitMaskSize
, SupportedFeatureMask
);
58 ASSERT_EFI_ERROR (Status
);
62 Collects CPU type and feature information.
64 @param[in, out] CpuInfo The pointer to CPU feature information
68 IN OUT REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
71 CPUID_VERSION_INFO_EAX Eax
;
72 CPUID_VERSION_INFO_ECX Ecx
;
73 CPUID_VERSION_INFO_EDX Edx
;
74 UINT32 DisplayedFamily
;
75 UINT32 DisplayedModel
;
77 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, &Ecx
.Uint32
, &Edx
.Uint32
);
79 DisplayedFamily
= Eax
.Bits
.FamilyId
;
80 if (Eax
.Bits
.FamilyId
== 0x0F) {
81 DisplayedFamily
|= (Eax
.Bits
.ExtendedFamilyId
<< 4);
84 DisplayedModel
= Eax
.Bits
.Model
;
85 if (Eax
.Bits
.FamilyId
== 0x06 || Eax
.Bits
.FamilyId
== 0x0f) {
86 DisplayedModel
|= (Eax
.Bits
.ExtendedModelId
<< 4);
89 CpuInfo
->DisplayFamily
= DisplayedFamily
;
90 CpuInfo
->DisplayModel
= DisplayedModel
;
91 CpuInfo
->SteppingId
= Eax
.Bits
.SteppingId
;
92 CpuInfo
->ProcessorType
= Eax
.Bits
.ProcessorType
;
93 CpuInfo
->CpuIdVersionInfoEcx
.Uint32
= Ecx
.Uint32
;
94 CpuInfo
->CpuIdVersionInfoEdx
.Uint32
= Edx
.Uint32
;
98 Prepares for private data used for CPU features.
102 CpuInitDataInitialize (
107 UINTN ProcessorNumber
;
108 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
109 CPU_FEATURES_ENTRY
*CpuFeature
;
110 CPU_FEATURES_INIT_ORDER
*InitOrder
;
111 CPU_FEATURES_DATA
*CpuFeaturesData
;
116 EFI_CPU_PHYSICAL_LOCATION
*Location
;
117 BOOLEAN
*CoresVisited
;
119 ACPI_CPU_DATA
*AcpiCpuData
;
120 CPU_STATUS_INFORMATION
*CpuStatus
;
121 UINT32
*ValidCoreCountPerPackage
;
123 UINTN NumberOfEnabledProcessors
;
129 CpuFeaturesData
= GetCpuFeaturesData ();
132 // Initialize CpuFeaturesData->MpService as early as possile, so later function can use it.
134 CpuFeaturesData
->MpService
= GetMpService ();
136 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
138 CpuFeaturesData
->InitOrder
= AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
139 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
142 // Collect CPU Features information
144 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
145 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
146 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
147 ASSERT (CpuFeature
->InitializeFunc
!= NULL
);
148 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
149 CpuFeature
->ConfigData
= CpuFeature
->GetConfigDataFunc (NumberOfCpus
);
151 Entry
= Entry
->ForwardLink
;
154 CpuFeaturesData
->NumberOfCpus
= (UINT32
) NumberOfCpus
;
156 AcpiCpuData
= GetAcpiCpuData ();
157 ASSERT (AcpiCpuData
!= NULL
);
158 CpuFeaturesData
->AcpiCpuData
= AcpiCpuData
;
160 CpuStatus
= &AcpiCpuData
->CpuStatus
;
161 Location
= AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
);
162 ASSERT (Location
!= NULL
);
163 AcpiCpuData
->ApLocation
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Location
;
165 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
166 InitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
167 InitOrder
->FeaturesSupportedMask
= AllocateZeroPool (CpuFeaturesData
->BitMaskSize
);
168 ASSERT (InitOrder
->FeaturesSupportedMask
!= NULL
);
169 InitializeListHead (&InitOrder
->OrderList
);
170 Status
= GetProcessorInformation (ProcessorNumber
, &ProcessorInfoBuffer
);
171 ASSERT_EFI_ERROR (Status
);
173 &InitOrder
->CpuInfo
.ProcessorInfo
,
174 &ProcessorInfoBuffer
,
175 sizeof (EFI_PROCESSOR_INFORMATION
)
178 &Location
[ProcessorNumber
],
179 &ProcessorInfoBuffer
.Location
,
180 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
184 // Collect CPU package count info.
186 if (Package
< ProcessorInfoBuffer
.Location
.Package
) {
187 Package
= ProcessorInfoBuffer
.Location
.Package
;
190 // Collect CPU max core count info.
192 if (Core
< ProcessorInfoBuffer
.Location
.Core
) {
193 Core
= ProcessorInfoBuffer
.Location
.Core
;
196 // Collect CPU max thread count info.
198 if (Thread
< ProcessorInfoBuffer
.Location
.Thread
) {
199 Thread
= ProcessorInfoBuffer
.Location
.Thread
;
202 CpuStatus
->PackageCount
= Package
+ 1;
203 CpuStatus
->MaxCoreCount
= Core
+ 1;
204 CpuStatus
->MaxThreadCount
= Thread
+ 1;
205 DEBUG ((DEBUG_INFO
, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",
206 CpuStatus
->PackageCount
,
207 CpuStatus
->MaxCoreCount
,
208 CpuStatus
->MaxThreadCount
));
211 // Collect valid core count in each package because not all cores are valid.
213 ValidCoreCountPerPackage
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
);
214 ASSERT (ValidCoreCountPerPackage
!= 0);
215 CpuStatus
->ValidCoreCountPerPackage
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ValidCoreCountPerPackage
;
216 CoresVisited
= AllocatePool (sizeof (BOOLEAN
) * CpuStatus
->MaxCoreCount
);
217 ASSERT (CoresVisited
!= NULL
);
219 for (Index
= 0; Index
< CpuStatus
->PackageCount
; Index
++ ) {
220 ZeroMem (CoresVisited
, sizeof (BOOLEAN
) * CpuStatus
->MaxCoreCount
);
222 // Collect valid cores in Current package.
224 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
225 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
226 if (Location
->Package
== Index
&& !CoresVisited
[Location
->Core
] ) {
228 // The ValidCores position for Location->Core is valid.
229 // The possible values in ValidCores[Index] are 0 or 1.
230 // FALSE means no valid threads in this Core.
231 // TRUE means have valid threads in this core, no matter the thead count is 1 or more.
233 CoresVisited
[Location
->Core
] = TRUE
;
234 ValidCoreCountPerPackage
[Index
]++;
238 FreePool (CoresVisited
);
240 for (Index
= 0; Index
<= Package
; Index
++) {
241 DEBUG ((DEBUG_INFO
, "Package: %d, Valid Core : %d\n", Index
, ValidCoreCountPerPackage
[Index
]));
244 CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
245 ASSERT (CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
!= NULL
);
246 CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
247 ASSERT (CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
!= NULL
);
251 Worker function to do OR operation on CPU feature supported bits mask buffer.
253 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
254 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
258 IN UINT8
*SupportedFeatureMask
,
259 IN UINT8
*OrFeatureBitMask
267 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
268 Data1
= SupportedFeatureMask
;
269 Data2
= OrFeatureBitMask
;
270 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
271 *(Data1
++) |= *(Data2
++);
276 Worker function to do AND operation on CPU feature supported bits mask buffer.
278 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
279 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
283 IN UINT8
*SupportedFeatureMask
,
284 IN CONST UINT8
*AndFeatureBitMask
292 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
293 Data1
= SupportedFeatureMask
;
294 Data2
= AndFeatureBitMask
;
295 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
296 *(Data1
++) &= *(Data2
++);
301 Worker function to clean bit operation on CPU feature supported bits mask buffer.
303 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
304 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
307 SupportedMaskCleanBit (
308 IN UINT8
*SupportedFeatureMask
,
309 IN UINT8
*AndFeatureBitMask
317 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
318 Data1
= SupportedFeatureMask
;
319 Data2
= AndFeatureBitMask
;
320 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
321 *(Data1
++) &= ~(*(Data2
++));
326 Worker function to check if the compared CPU feature set in the CPU feature
327 supported bits mask buffer.
329 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
330 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
332 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
334 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
339 IN UINT8
*SupportedFeatureMask
,
340 IN UINT8
*ComparedFeatureBitMask
348 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
350 Data1
= SupportedFeatureMask
;
351 Data2
= ComparedFeatureBitMask
;
352 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
353 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
361 Collects processor data for calling processor.
363 @param[in,out] Buffer The pointer to private data buffer.
367 CollectProcessorData (
371 UINTN ProcessorNumber
;
372 CPU_FEATURES_ENTRY
*CpuFeature
;
373 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
375 CPU_FEATURES_DATA
*CpuFeaturesData
;
377 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
378 ProcessorNumber
= GetProcessorIndex (CpuFeaturesData
);
379 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
381 // collect processor information
383 FillProcessorInfo (CpuInfo
);
384 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
385 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
386 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
387 if (CpuFeature
->SupportFunc
== NULL
) {
389 // If SupportFunc is NULL, then the feature is supported.
392 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
393 CpuFeature
->FeatureMask
395 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
397 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
398 CpuFeature
->FeatureMask
401 Entry
= Entry
->ForwardLink
;
406 Dump the contents of a CPU register table.
408 @param[in] ProcessorNumber The index of the CPU to show the register table contents
410 @note This service could be called by BSP only.
413 DumpRegisterTableOnProcessor (
414 IN UINTN ProcessorNumber
417 CPU_FEATURES_DATA
*CpuFeaturesData
;
419 CPU_REGISTER_TABLE
*RegisterTable
;
420 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
421 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
422 UINT32 DebugPrintErrorLevel
;
424 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
425 CpuFeaturesData
= GetCpuFeaturesData ();
429 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
430 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
432 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
434 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
435 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
436 switch (RegisterTableEntry
->RegisterType
) {
439 DebugPrintErrorLevel
,
440 "Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
443 RegisterTableEntry
->Index
,
444 RegisterTableEntry
->ValidBitStart
,
445 RegisterTableEntry
->ValidBitLength
,
446 RegisterTableEntry
->Value
449 case ControlRegister
:
451 DebugPrintErrorLevel
,
452 "Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
455 RegisterTableEntry
->Index
,
456 RegisterTableEntry
->ValidBitStart
,
457 RegisterTableEntry
->ValidBitLength
,
458 RegisterTableEntry
->Value
463 DebugPrintErrorLevel
,
464 "Processor: %04d: Index %04d, MMIO : %08lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
467 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
468 RegisterTableEntry
->ValidBitStart
,
469 RegisterTableEntry
->ValidBitLength
,
470 RegisterTableEntry
->Value
475 DebugPrintErrorLevel
,
476 "Processor: %04d: Index %04d, CACHE: %08lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
479 RegisterTableEntry
->Index
,
480 RegisterTableEntry
->ValidBitStart
,
481 RegisterTableEntry
->ValidBitLength
,
482 RegisterTableEntry
->Value
487 DebugPrintErrorLevel
,
488 "Processor: %04d: Index %04d, SEMAP: %s\r\n",
491 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
502 Get the biggest dependence type.
503 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
505 @param[in] BeforeDep Before dependence type.
506 @param[in] AfterDep After dependence type.
507 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.
508 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.
510 @retval Return the biggest dependence type.
512 CPU_FEATURE_DEPENDENCE_TYPE
514 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
,
515 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep
,
516 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
,
517 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
520 CPU_FEATURE_DEPENDENCE_TYPE Bigger
;
522 Bigger
= MAX (BeforeDep
, AfterDep
);
523 Bigger
= MAX (Bigger
, NoneNeibBeforeDep
);
524 return MAX(Bigger
, NoneNeibAfterDep
);
528 Analysis register CPU features on each processor and save CPU setting in CPU register table.
530 @param[in] NumberOfCpus Number of processor in system
534 AnalysisProcessorFeatures (
535 IN UINTN NumberOfCpus
539 UINTN ProcessorNumber
;
540 CPU_FEATURES_ENTRY
*CpuFeature
;
541 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
542 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
543 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
545 CPU_FEATURES_DATA
*CpuFeaturesData
;
546 LIST_ENTRY
*NextEntry
;
547 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
549 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
550 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
551 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
;
552 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
;
554 CpuFeaturesData
= GetCpuFeaturesData ();
555 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
556 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
557 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
558 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
559 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
561 // Calculate the last capability on all processors
563 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
);
566 // Calculate the last setting
568 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
569 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
570 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, PcdGetPtr (PcdCpuFeaturesSetting
));
573 // Dump the last CPU feature list
576 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
577 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
578 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
579 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
580 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
)) {
581 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
)) {
582 DEBUG ((DEBUG_INFO
, "[Enable ] "));
584 DEBUG ((DEBUG_INFO
, "[Disable ] "));
587 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
589 DumpCpuFeature (CpuFeature
);
590 Entry
= Entry
->ForwardLink
;
592 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
593 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
);
594 DEBUG ((DEBUG_INFO
, "Origin PcdCpuFeaturesSetting:\n"));
595 DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting
));
596 DEBUG ((DEBUG_INFO
, "Final PcdCpuFeaturesSetting:\n"));
597 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
);
601 // Save PCDs and display CPU PCDs
603 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
604 SetSettingPcd (CpuFeaturesData
->SettingPcd
);
606 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
607 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
608 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
609 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
611 // Insert each feature into processor's order list
613 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
614 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
)) {
615 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
616 ASSERT (CpuFeatureInOrder
!= NULL
);
617 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
619 Entry
= Entry
->ForwardLink
;
622 // Go through ordered feature list to initialize CPU features
624 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
625 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
626 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
627 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
630 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
)) {
631 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
632 if (EFI_ERROR (Status
)) {
634 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
636 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
);
637 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
638 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
640 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
641 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
);
647 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
648 if (EFI_ERROR (Status
)) {
649 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
650 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
652 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
653 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
);
661 NextEntry
= Entry
->ForwardLink
;
662 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
663 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
666 // If feature has dependence with the next feature (ONLY care core/package dependency).
667 // and feature initialize succeed, add sync semaphere here.
669 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
670 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
672 // Check whether next feature has After type dependence with not neighborhood CPU
673 // Features in former CPU features.
675 NoneNeibAfterDep
= DetectNoneNeighborhoodFeatureScope(NextCpuFeatureInOrder
, FALSE
, &CpuInitOrder
->OrderList
);
677 BeforeDep
= NoneDepType
;
678 AfterDep
= NoneDepType
;
679 NoneNeibAfterDep
= NoneDepType
;
682 // Check whether current feature has Before type dependence with none neighborhood
683 // CPU features in after Cpu features.
685 NoneNeibBeforeDep
= DetectNoneNeighborhoodFeatureScope(CpuFeatureInOrder
, TRUE
, &CpuInitOrder
->OrderList
);
688 // Get the biggest dependence and add semaphore for it.
689 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
691 BeforeDep
= BiggestDep(BeforeDep
, AfterDep
, NoneNeibBeforeDep
, NoneNeibAfterDep
);
692 if (BeforeDep
> ThreadDepType
) {
693 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
697 Entry
= Entry
->ForwardLink
;
701 // Dump PcdCpuFeaturesSetting again because this value maybe updated
702 // again during initialize the features.
704 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
705 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
);
708 // Dump the RegisterTable
710 DumpRegisterTableOnProcessor (ProcessorNumber
);
715 Increment semaphore by 1.
717 @param Sem IN: 32-bit unsigned integer
721 LibReleaseSemaphore (
722 IN OUT
volatile UINT32
*Sem
725 InterlockedIncrement (Sem
);
729 Decrement the semaphore by 1 if it is not zero.
731 Performs an atomic decrement operation for semaphore.
732 The compare exchange operation must be performed using
735 @param Sem IN: 32-bit unsigned integer
739 LibWaitForSemaphore (
740 IN OUT
volatile UINT32
*Sem
747 } while (Value
== 0 ||
748 InterlockedCompareExchange32 (
756 Initialize the CPU registers from a register table.
758 @param[in] RegisterTable The register table for this AP.
759 @param[in] ApLocation AP location info for this ap.
760 @param[in] CpuStatus CPU status info for this CPU.
761 @param[in] CpuFlags Flags data structure used when program the register.
763 @note This service could be called by BSP/APs.
766 ProgramProcessorRegister (
767 IN CPU_REGISTER_TABLE
*RegisterTable
,
768 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
769 IN CPU_STATUS_INFORMATION
*CpuStatus
,
770 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
773 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
776 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
777 volatile UINT32
*SemaphorePtr
;
779 UINT32 PackageThreadsCount
;
780 UINT32 CurrentThread
;
781 UINTN ProcessorIndex
;
783 UINTN ValidThreadCount
;
784 UINT32
*ValidCoreCountPerPackage
;
787 // Traverse Register Table of this logical processor
789 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
791 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
793 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
797 // Wait for the AP to release the MSR spin lock.
799 while (!AcquireSpinLockOrFail (&CpuFlags
->ConsoleLogLock
)) {
802 ThreadIndex
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
+
803 ApLocation
->Core
* CpuStatus
->MaxThreadCount
+
807 "Processor = %08lu, Index %08lu, Type = %s!\n",
810 mRegisterTypeStr
[MIN ((REGISTER_TYPE
)RegisterTableEntry
->RegisterType
, InvalidReg
)]
812 ReleaseSpinLock (&CpuFlags
->ConsoleLogLock
);
816 // Check the type of specified register
818 switch (RegisterTableEntry
->RegisterType
) {
820 // The specified register is Control Register
822 case ControlRegister
:
823 switch (RegisterTableEntry
->Index
) {
825 Value
= AsmReadCr0 ();
826 Value
= (UINTN
) BitFieldWrite64 (
828 RegisterTableEntry
->ValidBitStart
,
829 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
830 RegisterTableEntry
->Value
835 Value
= AsmReadCr2 ();
836 Value
= (UINTN
) BitFieldWrite64 (
838 RegisterTableEntry
->ValidBitStart
,
839 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
840 RegisterTableEntry
->Value
845 Value
= AsmReadCr3 ();
846 Value
= (UINTN
) BitFieldWrite64 (
848 RegisterTableEntry
->ValidBitStart
,
849 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
850 RegisterTableEntry
->Value
855 Value
= AsmReadCr4 ();
856 Value
= (UINTN
) BitFieldWrite64 (
858 RegisterTableEntry
->ValidBitStart
,
859 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
860 RegisterTableEntry
->Value
866 // Do we need to support CR8?
874 // The specified register is Model Specific Register
877 if (RegisterTableEntry
->ValidBitLength
>= 64) {
879 // If length is not less than 64 bits, then directly write without reading
882 RegisterTableEntry
->Index
,
883 RegisterTableEntry
->Value
887 // Set the bit section according to bit start and length
889 AsmMsrBitFieldWrite64 (
890 RegisterTableEntry
->Index
,
891 RegisterTableEntry
->ValidBitStart
,
892 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
893 RegisterTableEntry
->Value
898 // MemoryMapped operations
901 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
902 MmioBitFieldWrite32 (
903 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
904 RegisterTableEntry
->ValidBitStart
,
905 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
906 (UINT32
)RegisterTableEntry
->Value
908 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
911 // Enable or disable cache
915 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
917 if (RegisterTableEntry
->Value
== 0) {
925 // Semaphore works logic like below:
927 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
928 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
930 // All threads (T0...Tn) waits in P() line and continues running
936 // V(0...n) V(0...n) ... V(0...n)
937 // n * P(0) n * P(1) ... n * P(n)
939 switch (RegisterTableEntry
->Value
) {
941 SemaphorePtr
= CpuFlags
->CoreSemaphoreCount
;
943 // Get Offset info for the first thread in the core which current thread belongs to.
945 FirstThread
= (ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
) * CpuStatus
->MaxThreadCount
;
946 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
948 // First Notify all threads in current Core that this thread has ready.
950 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
951 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
954 // Second, check whether all valid threads in current core have ready.
956 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
957 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
962 SemaphorePtr
= CpuFlags
->PackageSemaphoreCount
;
963 ValidCoreCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ValidCoreCountPerPackage
;
965 // Get Offset info for the first thread in the package which current thread belongs to.
967 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
969 // Get the possible threads count for current package.
971 PackageThreadsCount
= CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
;
972 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
974 // Get the valid thread count for current package.
976 ValidThreadCount
= CpuStatus
->MaxThreadCount
* ValidCoreCountPerPackage
[ApLocation
->Package
];
979 // Different packages may have different valid cores in them. If driver maintail clearly
980 // cores number in different packages, the logic will be much complicated.
981 // Here driver just simply records the max core number in all packages and use it as expect
982 // core number for all packages.
983 // In below two steps logic, first current thread will Release semaphore for each thread
984 // in current package. Maybe some threads are not valid in this package, but driver don't
985 // care. Second, driver will let current thread wait semaphore for all valid threads in
986 // current package. Because only the valid threads will do release semaphore for this
987 // thread, driver here only need to wait the valid thread count.
991 // First Notify ALL THREADS in current package that this thread has ready.
993 for (ProcessorIndex
= 0; ProcessorIndex
< PackageThreadsCount
; ProcessorIndex
++) {
994 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
997 // Second, check whether VALID THREADS (not all threads) in current package have ready.
999 for (ProcessorIndex
= 0; ProcessorIndex
< ValidThreadCount
; ProcessorIndex
++) {
1000 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1016 Programs registers for the calling processor.
1018 @param[in,out] Buffer The pointer to private data buffer.
1023 SetProcessorRegister (
1027 CPU_FEATURES_DATA
*CpuFeaturesData
;
1028 CPU_REGISTER_TABLE
*RegisterTable
;
1029 CPU_REGISTER_TABLE
*RegisterTables
;
1033 ACPI_CPU_DATA
*AcpiCpuData
;
1035 CpuFeaturesData
= (CPU_FEATURES_DATA
*) Buffer
;
1036 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1038 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->RegisterTable
;
1040 InitApicId
= GetInitialApicId ();
1041 RegisterTable
= NULL
;
1042 ProcIndex
= (UINTN
)-1;
1043 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1044 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1045 RegisterTable
= &RegisterTables
[Index
];
1050 ASSERT (RegisterTable
!= NULL
);
1052 ProgramProcessorRegister (
1054 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->ApLocation
+ ProcIndex
,
1055 &AcpiCpuData
->CpuStatus
,
1056 &CpuFeaturesData
->CpuFlags
1061 Performs CPU features detection.
1063 This service will invoke MP service to check CPU features'
1064 capabilities on BSP/APs.
1066 @note This service could be called by BSP only.
1074 CPU_FEATURES_DATA
*CpuFeaturesData
;
1076 CpuFeaturesData
= GetCpuFeaturesData();
1078 CpuInitDataInitialize ();
1081 // Wakeup all APs for data collection.
1083 StartupAPsWorker (CollectProcessorData
, NULL
);
1086 // Collect data on BSP
1088 CollectProcessorData (CpuFeaturesData
);
1090 AnalysisProcessorFeatures (CpuFeaturesData
->NumberOfCpus
);