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
.SemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
273 ASSERT (CpuFeaturesData
->CpuFlags
.SemaphoreCount
!= NULL
);
276 // Get support and configuration PCDs
278 CpuFeaturesData
->SupportPcd
= GetSupportPcd ();
279 CpuFeaturesData
->ConfigurationPcd
= GetConfigurationPcd ();
283 Worker function to do OR operation on CPU feature supported bits mask buffer.
285 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
286 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
290 IN UINT8
*SupportedFeatureMask
,
291 IN UINT8
*OrFeatureBitMask
299 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
300 Data1
= SupportedFeatureMask
;
301 Data2
= OrFeatureBitMask
;
302 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
303 *(Data1
++) |= *(Data2
++);
308 Worker function to do AND operation on CPU feature supported bits mask buffer.
310 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
311 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
315 IN UINT8
*SupportedFeatureMask
,
316 IN UINT8
*AndFeatureBitMask
324 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
325 Data1
= SupportedFeatureMask
;
326 Data2
= AndFeatureBitMask
;
327 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
328 *(Data1
++) &= *(Data2
++);
333 Worker function to clean bit operation on CPU feature supported bits mask buffer.
335 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
336 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
339 SupportedMaskCleanBit (
340 IN UINT8
*SupportedFeatureMask
,
341 IN UINT8
*AndFeatureBitMask
349 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
350 Data1
= SupportedFeatureMask
;
351 Data2
= AndFeatureBitMask
;
352 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
353 *(Data1
++) &= ~(*(Data2
++));
358 Worker function to check if the compared CPU feature set in the CPU feature
359 supported bits mask buffer.
361 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
362 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
364 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
366 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
371 IN UINT8
*SupportedFeatureMask
,
372 IN UINT8
*ComparedFeatureBitMask
380 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
382 Data1
= SupportedFeatureMask
;
383 Data2
= ComparedFeatureBitMask
;
384 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
385 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
393 Collects processor data for calling processor.
395 @param[in,out] Buffer The pointer to private data buffer.
399 CollectProcessorData (
403 UINTN ProcessorNumber
;
404 CPU_FEATURES_ENTRY
*CpuFeature
;
405 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
407 CPU_FEATURES_DATA
*CpuFeaturesData
;
409 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
410 ProcessorNumber
= GetProcessorIndex ();
411 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
413 // collect processor information
415 FillProcessorInfo (CpuInfo
);
416 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
417 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
418 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
419 if (IsBitMaskMatch (CpuFeaturesData
->SupportPcd
, CpuFeature
->FeatureMask
)) {
420 if (CpuFeature
->SupportFunc
== NULL
) {
422 // If SupportFunc is NULL, then the feature is supported.
425 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
426 CpuFeature
->FeatureMask
428 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
430 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
431 CpuFeature
->FeatureMask
435 Entry
= Entry
->ForwardLink
;
440 Dump the contents of a CPU register table.
442 @param[in] ProcessorNumber The index of the CPU to show the register table contents
444 @note This service could be called by BSP only.
447 DumpRegisterTableOnProcessor (
448 IN UINTN ProcessorNumber
451 CPU_FEATURES_DATA
*CpuFeaturesData
;
453 CPU_REGISTER_TABLE
*RegisterTable
;
454 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
455 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
456 UINT32 DebugPrintErrorLevel
;
458 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
459 CpuFeaturesData
= GetCpuFeaturesData ();
463 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
464 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
466 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
468 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
469 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
470 switch (RegisterTableEntry
->RegisterType
) {
473 DebugPrintErrorLevel
,
474 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
476 RegisterTableEntry
->Index
,
477 RegisterTableEntry
->ValidBitStart
,
478 RegisterTableEntry
->ValidBitLength
,
479 RegisterTableEntry
->Value
482 case ControlRegister
:
484 DebugPrintErrorLevel
,
485 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
487 RegisterTableEntry
->Index
,
488 RegisterTableEntry
->ValidBitStart
,
489 RegisterTableEntry
->ValidBitLength
,
490 RegisterTableEntry
->Value
495 DebugPrintErrorLevel
,
496 "Processor: %d: MMIO: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
498 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
499 RegisterTableEntry
->ValidBitStart
,
500 RegisterTableEntry
->ValidBitLength
,
501 RegisterTableEntry
->Value
506 DebugPrintErrorLevel
,
507 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
509 RegisterTableEntry
->Index
,
510 RegisterTableEntry
->ValidBitStart
,
511 RegisterTableEntry
->ValidBitLength
,
512 RegisterTableEntry
->Value
517 DebugPrintErrorLevel
,
518 "Processor: %d: Semaphore: Scope Value: %s\r\n",
520 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
531 Analysis register CPU features on each processor and save CPU setting in CPU register table.
533 @param[in] NumberOfCpus Number of processor in system
537 AnalysisProcessorFeatures (
538 IN UINTN NumberOfCpus
542 UINTN ProcessorNumber
;
543 CPU_FEATURES_ENTRY
*CpuFeature
;
544 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
545 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
546 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
548 CPU_FEATURES_DATA
*CpuFeaturesData
;
549 LIST_ENTRY
*NextEntry
;
550 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
552 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
553 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
555 CpuFeaturesData
= GetCpuFeaturesData ();
556 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
557 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
558 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
559 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
560 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
562 // Calculate the last capability on all processors
564 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
);
567 // Calculate the last setting
570 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
571 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
572 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->ConfigurationPcd
);
575 // Save PCDs and display CPU PCDs
577 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
);
578 SetSettingPcd (CpuFeaturesData
->SettingPcd
);
581 // Dump the last CPU feature list
584 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
585 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
586 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
587 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
588 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
)) {
589 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
)) {
590 DEBUG ((DEBUG_INFO
, "[Enable ] "));
592 DEBUG ((DEBUG_INFO
, "[Disable ] "));
595 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
597 DumpCpuFeature (CpuFeature
);
598 Entry
= Entry
->ForwardLink
;
600 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesSupport:\n"));
601 DumpCpuFeatureMask (CpuFeaturesData
->SupportPcd
);
602 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesUserConfiguration:\n"));
603 DumpCpuFeatureMask (CpuFeaturesData
->ConfigurationPcd
);
604 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
605 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
);
606 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesSetting:\n"));
607 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
);
610 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
611 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
612 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
613 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
615 // Insert each feature into processor's order list
617 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
618 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
)) {
619 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
620 ASSERT (CpuFeatureInOrder
!= NULL
);
621 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
623 Entry
= Entry
->ForwardLink
;
626 // Go through ordered feature list to initialize CPU features
628 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
629 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
630 NextEntry
= Entry
->ForwardLink
;
631 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
632 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
633 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
634 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
636 NextCpuFeatureInOrder
= NULL
;
639 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
)) {
640 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
641 if (EFI_ERROR (Status
)) {
643 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
645 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
);
646 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
647 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
649 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
650 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
);
656 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
657 if (EFI_ERROR (Status
)) {
658 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
659 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
661 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
662 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
);
671 // If feature has dependence with the next feature (ONLY care core/package dependency).
672 // and feature initialize succeed, add sync semaphere here.
674 if (NextCpuFeatureInOrder
!= NULL
) {
675 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
676 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
678 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NULL
);
679 AfterDep
= NoneDepType
;
682 // Assume only one of the depend is valid.
684 ASSERT (!(BeforeDep
> ThreadDepType
&& AfterDep
> ThreadDepType
));
685 if (BeforeDep
> ThreadDepType
) {
686 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
688 if (AfterDep
> ThreadDepType
) {
689 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, AfterDep
);
693 Entry
= Entry
->ForwardLink
;
694 NextEntry
= Entry
->ForwardLink
;
698 // Dump PcdCpuFeaturesSetting again because this value maybe updated
699 // again during initialize the features.
701 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
702 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
);
705 // Dump the RegisterTable
707 DumpRegisterTableOnProcessor (ProcessorNumber
);
712 Increment semaphore by 1.
714 @param Sem IN: 32-bit unsigned integer
718 LibReleaseSemaphore (
719 IN OUT
volatile UINT32
*Sem
722 InterlockedIncrement (Sem
);
726 Decrement the semaphore by 1 if it is not zero.
728 Performs an atomic decrement operation for semaphore.
729 The compare exchange operation must be performed using
732 @param Sem IN: 32-bit unsigned integer
736 LibWaitForSemaphore (
737 IN OUT
volatile UINT32
*Sem
744 } while (Value
== 0 ||
745 InterlockedCompareExchange32 (
753 Initialize the CPU registers from a register table.
755 @param[in] RegisterTable The register table for this AP.
756 @param[in] ApLocation AP location info for this ap.
757 @param[in] CpuStatus CPU status info for this CPU.
758 @param[in] CpuFlags Flags data structure used when program the register.
760 @note This service could be called by BSP/APs.
763 ProgramProcessorRegister (
764 IN CPU_REGISTER_TABLE
*RegisterTable
,
765 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
766 IN CPU_STATUS_INFORMATION
*CpuStatus
,
767 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
770 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
773 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
774 volatile UINT32
*SemaphorePtr
;
776 UINT32 PackageThreadsCount
;
777 UINT32 CurrentThread
;
778 UINTN ProcessorIndex
;
780 UINTN ValidThreadCount
;
781 UINT32
*ValidCoreCountPerPackage
;
784 // Traverse Register Table of this logical processor
786 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
788 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
790 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
793 AcquireSpinLock (&CpuFlags
->ConsoleLogLock
);
794 ThreadIndex
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
+
795 ApLocation
->Core
* CpuStatus
->MaxThreadCount
+
799 "Processor = %lu, Entry Index %lu, Type = %s!\n",
802 mRegisterTypeStr
[MIN ((REGISTER_TYPE
)RegisterTableEntry
->RegisterType
, InvalidReg
)]
804 ReleaseSpinLock (&CpuFlags
->ConsoleLogLock
);
808 // Check the type of specified register
810 switch (RegisterTableEntry
->RegisterType
) {
812 // The specified register is Control Register
814 case ControlRegister
:
815 switch (RegisterTableEntry
->Index
) {
817 Value
= AsmReadCr0 ();
818 Value
= (UINTN
) BitFieldWrite64 (
820 RegisterTableEntry
->ValidBitStart
,
821 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
822 RegisterTableEntry
->Value
827 Value
= AsmReadCr2 ();
828 Value
= (UINTN
) BitFieldWrite64 (
830 RegisterTableEntry
->ValidBitStart
,
831 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
832 RegisterTableEntry
->Value
837 Value
= AsmReadCr3 ();
838 Value
= (UINTN
) BitFieldWrite64 (
840 RegisterTableEntry
->ValidBitStart
,
841 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
842 RegisterTableEntry
->Value
847 Value
= AsmReadCr4 ();
848 Value
= (UINTN
) BitFieldWrite64 (
850 RegisterTableEntry
->ValidBitStart
,
851 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
852 RegisterTableEntry
->Value
858 // Do we need to support CR8?
866 // The specified register is Model Specific Register
869 if (RegisterTableEntry
->ValidBitLength
>= 64) {
871 // If length is not less than 64 bits, then directly write without reading
874 RegisterTableEntry
->Index
,
875 RegisterTableEntry
->Value
879 // Set the bit section according to bit start and length
881 AsmMsrBitFieldWrite64 (
882 RegisterTableEntry
->Index
,
883 RegisterTableEntry
->ValidBitStart
,
884 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
885 RegisterTableEntry
->Value
890 // MemoryMapped operations
893 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
894 MmioBitFieldWrite32 (
895 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
896 RegisterTableEntry
->ValidBitStart
,
897 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
898 (UINT32
)RegisterTableEntry
->Value
900 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
903 // Enable or disable cache
907 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
909 if (RegisterTableEntry
->Value
== 0) {
917 // Semaphore works logic like below:
919 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
920 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
922 // All threads (T0...Tn) waits in P() line and continues running
928 // V(0...n) V(0...n) ... V(0...n)
929 // n * P(0) n * P(1) ... n * P(n)
931 SemaphorePtr
= CpuFlags
->SemaphoreCount
;
932 switch (RegisterTableEntry
->Value
) {
935 // Get Offset info for the first thread in the core which current thread belongs to.
937 FirstThread
= (ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
) * CpuStatus
->MaxThreadCount
;
938 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
940 // First Notify all threads in current Core that this thread has ready.
942 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
943 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
946 // Second, check whether all valid threads in current core have ready.
948 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
949 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
954 ValidCoreCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ValidCoreCountPerPackage
;
956 // Get Offset info for the first thread in the package which current thread belongs to.
958 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
960 // Get the possible threads count for current package.
962 PackageThreadsCount
= CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
;
963 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
965 // Get the valid thread count for current package.
967 ValidThreadCount
= CpuStatus
->MaxThreadCount
* ValidCoreCountPerPackage
[ApLocation
->Package
];
970 // Different packages may have different valid cores in them. If driver maintail clearly
971 // cores number in different packages, the logic will be much complicated.
972 // Here driver just simply records the max core number in all packages and use it as expect
973 // core number for all packages.
974 // In below two steps logic, first current thread will Release semaphore for each thread
975 // in current package. Maybe some threads are not valid in this package, but driver don't
976 // care. Second, driver will let current thread wait semaphore for all valid threads in
977 // current package. Because only the valid threads will do release semaphore for this
978 // thread, driver here only need to wait the valid thread count.
982 // First Notify ALL THREADS in current package that this thread has ready.
984 for (ProcessorIndex
= 0; ProcessorIndex
< PackageThreadsCount
; ProcessorIndex
++) {
985 LibReleaseSemaphore ((UINT32
*) &SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
988 // Second, check whether VALID THREADS (not all threads) in current package have ready.
990 for (ProcessorIndex
= 0; ProcessorIndex
< ValidThreadCount
; ProcessorIndex
++) {
991 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1007 Programs registers for the calling processor.
1009 @param[in,out] Buffer The pointer to private data buffer.
1014 SetProcessorRegister (
1018 CPU_FEATURES_DATA
*CpuFeaturesData
;
1019 CPU_REGISTER_TABLE
*RegisterTable
;
1020 CPU_REGISTER_TABLE
*RegisterTables
;
1024 ACPI_CPU_DATA
*AcpiCpuData
;
1026 CpuFeaturesData
= (CPU_FEATURES_DATA
*) Buffer
;
1027 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1029 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->RegisterTable
;
1031 InitApicId
= GetInitialApicId ();
1032 RegisterTable
= NULL
;
1033 ProcIndex
= (UINTN
)-1;
1034 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1035 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1036 RegisterTable
= &RegisterTables
[Index
];
1041 ASSERT (RegisterTable
!= NULL
);
1043 ProgramProcessorRegister (
1045 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->ApLocation
+ ProcIndex
,
1046 &AcpiCpuData
->CpuStatus
,
1047 &CpuFeaturesData
->CpuFlags
1052 Performs CPU features detection.
1054 This service will invoke MP service to check CPU features'
1055 capabilities on BSP/APs.
1057 @note This service could be called by BSP only.
1066 UINTN NumberOfEnabledProcessors
;
1067 CPU_FEATURES_DATA
*CpuFeaturesData
;
1069 CpuFeaturesData
= GetCpuFeaturesData();
1071 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
1073 CpuInitDataInitialize (NumberOfCpus
);
1076 // Wakeup all APs for data collection.
1078 StartupAPsWorker (CollectProcessorData
, NULL
);
1081 // Collect data on BSP
1083 CollectProcessorData (CpuFeaturesData
);
1085 AnalysisProcessorFeatures (NumberOfCpus
);