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
;
109 ACPI_CPU_DATA
*AcpiCpuData
;
110 CPU_STATUS_INFORMATION
*CpuStatus
;
111 UINT32
*ThreadCountPerPackage
;
112 UINT8
*ThreadCountPerCore
;
114 UINTN NumberOfEnabledProcessors
;
120 CpuFeaturesData
= GetCpuFeaturesData ();
123 // Initialize CpuFeaturesData->MpService as early as possile, so later function can use it.
125 CpuFeaturesData
->MpService
= GetMpService ();
127 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
129 CpuFeaturesData
->InitOrder
= AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
130 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
133 // Collect CPU Features information
135 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
136 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
137 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
138 ASSERT (CpuFeature
->InitializeFunc
!= NULL
);
139 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
140 CpuFeature
->ConfigData
= CpuFeature
->GetConfigDataFunc (NumberOfCpus
);
142 Entry
= Entry
->ForwardLink
;
145 CpuFeaturesData
->NumberOfCpus
= (UINT32
) NumberOfCpus
;
147 AcpiCpuData
= GetAcpiCpuData ();
148 ASSERT (AcpiCpuData
!= NULL
);
149 CpuFeaturesData
->AcpiCpuData
= AcpiCpuData
;
151 CpuStatus
= &AcpiCpuData
->CpuStatus
;
152 Location
= AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
);
153 ASSERT (Location
!= NULL
);
154 AcpiCpuData
->ApLocation
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Location
;
156 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
157 InitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
158 InitOrder
->FeaturesSupportedMask
= AllocateZeroPool (CpuFeaturesData
->BitMaskSize
);
159 ASSERT (InitOrder
->FeaturesSupportedMask
!= NULL
);
160 InitializeListHead (&InitOrder
->OrderList
);
161 Status
= GetProcessorInformation (ProcessorNumber
, &ProcessorInfoBuffer
);
162 ASSERT_EFI_ERROR (Status
);
164 &InitOrder
->CpuInfo
.ProcessorInfo
,
165 &ProcessorInfoBuffer
,
166 sizeof (EFI_PROCESSOR_INFORMATION
)
169 &Location
[ProcessorNumber
],
170 &ProcessorInfoBuffer
.Location
,
171 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
175 // Collect CPU package count info.
177 if (Package
< ProcessorInfoBuffer
.Location
.Package
) {
178 Package
= ProcessorInfoBuffer
.Location
.Package
;
181 // Collect CPU max core count info.
183 if (Core
< ProcessorInfoBuffer
.Location
.Core
) {
184 Core
= ProcessorInfoBuffer
.Location
.Core
;
187 // Collect CPU max thread count info.
189 if (Thread
< ProcessorInfoBuffer
.Location
.Thread
) {
190 Thread
= ProcessorInfoBuffer
.Location
.Thread
;
193 CpuStatus
->PackageCount
= Package
+ 1;
194 CpuStatus
->MaxCoreCount
= Core
+ 1;
195 CpuStatus
->MaxThreadCount
= Thread
+ 1;
196 DEBUG ((DEBUG_INFO
, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",
197 CpuStatus
->PackageCount
,
198 CpuStatus
->MaxCoreCount
,
199 CpuStatus
->MaxThreadCount
));
202 // Collect valid core count in each package because not all cores are valid.
204 ThreadCountPerPackage
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
);
205 ASSERT (ThreadCountPerPackage
!= NULL
);
206 CpuStatus
->ThreadCountPerPackage
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ThreadCountPerPackage
;
208 ThreadCountPerCore
= AllocateZeroPool (sizeof (UINT8
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
);
209 ASSERT (ThreadCountPerCore
!= NULL
);
210 CpuStatus
->ThreadCountPerCore
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ThreadCountPerCore
;
212 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
213 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
214 ThreadCountPerPackage
[Location
->Package
]++;
215 ThreadCountPerCore
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]++;
218 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
219 if (ThreadCountPerPackage
[PackageIndex
] != 0) {
220 DEBUG ((DEBUG_INFO
, "P%02d: Thread Count = %d\n", PackageIndex
, ThreadCountPerPackage
[PackageIndex
]));
221 for (CoreIndex
= 0; CoreIndex
< CpuStatus
->MaxCoreCount
; CoreIndex
++) {
222 if (ThreadCountPerCore
[PackageIndex
* CpuStatus
->MaxCoreCount
+ CoreIndex
] != 0) {
224 DEBUG_INFO
, " P%02d C%04d, Thread Count = %d\n", PackageIndex
, CoreIndex
,
225 ThreadCountPerCore
[PackageIndex
* CpuStatus
->MaxCoreCount
+ CoreIndex
]
232 CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
233 ASSERT (CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
!= NULL
);
234 CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
235 ASSERT (CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
!= NULL
);
238 // Initialize CpuFeaturesData->InitOrder[].CpuInfo.First
242 // Set First.Package for each thread belonging to the first package.
245 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
246 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
247 First
= MIN (Location
->Package
, First
);
249 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
250 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
251 if (Location
->Package
== First
) {
252 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Package
= 1;
257 // Set First.Die/Tile/Module for each thread assuming:
258 // single Die under each package, single Tile under each Die, single Module under each Tile
260 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
261 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Die
= 1;
262 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Tile
= 1;
263 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Module
= 1;
266 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
268 // Set First.Core for each thread in the first core of each package.
271 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
272 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
273 if (Location
->Package
== PackageIndex
) {
274 First
= MIN (Location
->Core
, First
);
278 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
279 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
280 if (Location
->Package
== PackageIndex
&& Location
->Core
== First
) {
281 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Core
= 1;
286 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
287 for (CoreIndex
= 0; CoreIndex
< CpuStatus
->MaxCoreCount
; CoreIndex
++) {
289 // Set First.Thread for the first thread of each core.
292 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
293 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
294 if (Location
->Package
== PackageIndex
&& Location
->Core
== CoreIndex
) {
295 First
= MIN (Location
->Thread
, First
);
299 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
300 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
301 if (Location
->Package
== PackageIndex
&& Location
->Core
== CoreIndex
&& Location
->Thread
== First
) {
302 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Thread
= 1;
310 Worker function to do OR operation on CPU feature supported bits mask buffer.
312 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
313 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
314 @param[in] BitMaskSize The CPU feature bits mask buffer size.
319 IN UINT8
*SupportedFeatureMask
,
320 IN UINT8
*OrFeatureBitMask
,
321 IN UINT32 BitMaskSize
328 Data1
= SupportedFeatureMask
;
329 Data2
= OrFeatureBitMask
;
330 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
331 *(Data1
++) |= *(Data2
++);
336 Worker function to do AND operation on CPU feature supported bits mask buffer.
338 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
339 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
340 @param[in] BitMaskSize CPU feature bits mask buffer size.
345 IN UINT8
*SupportedFeatureMask
,
346 IN CONST UINT8
*AndFeatureBitMask
,
347 IN UINT32 BitMaskSize
354 Data1
= SupportedFeatureMask
;
355 Data2
= AndFeatureBitMask
;
356 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
357 *(Data1
++) &= *(Data2
++);
362 Worker function to clean bit operation on CPU feature supported bits mask buffer.
364 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
365 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
366 @param[in] BitMaskSize CPU feature bits mask buffer size.
369 SupportedMaskCleanBit (
370 IN UINT8
*SupportedFeatureMask
,
371 IN UINT8
*AndFeatureBitMask
,
372 IN UINT32 BitMaskSize
379 Data1
= SupportedFeatureMask
;
380 Data2
= AndFeatureBitMask
;
381 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
382 *(Data1
++) &= ~(*(Data2
++));
387 Worker function to check if the compared CPU feature set in the CPU feature
388 supported bits mask buffer.
390 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
391 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
392 @param[in] BitMaskSize CPU feature bits mask buffer size.
394 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
396 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
401 IN UINT8
*SupportedFeatureMask
,
402 IN UINT8
*ComparedFeatureBitMask
,
403 IN UINT32 BitMaskSize
410 Data1
= SupportedFeatureMask
;
411 Data2
= ComparedFeatureBitMask
;
412 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
413 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
421 Collects processor data for calling processor.
423 @param[in,out] Buffer The pointer to private data buffer.
427 CollectProcessorData (
431 UINTN ProcessorNumber
;
432 CPU_FEATURES_ENTRY
*CpuFeature
;
433 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
435 CPU_FEATURES_DATA
*CpuFeaturesData
;
437 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
438 ProcessorNumber
= GetProcessorIndex (CpuFeaturesData
);
439 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
441 // collect processor information
443 FillProcessorInfo (CpuInfo
);
444 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
445 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
446 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
447 if (CpuFeature
->SupportFunc
== NULL
) {
449 // If SupportFunc is NULL, then the feature is supported.
452 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
453 CpuFeature
->FeatureMask
,
454 CpuFeaturesData
->BitMaskSize
456 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
458 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
459 CpuFeature
->FeatureMask
,
460 CpuFeaturesData
->BitMaskSize
463 Entry
= Entry
->ForwardLink
;
468 Dump the contents of a CPU register table.
470 @param[in] ProcessorNumber The index of the CPU to show the register table contents
472 @note This service could be called by BSP only.
475 DumpRegisterTableOnProcessor (
476 IN UINTN ProcessorNumber
479 CPU_FEATURES_DATA
*CpuFeaturesData
;
481 CPU_REGISTER_TABLE
*RegisterTable
;
482 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
483 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
484 UINT32 DebugPrintErrorLevel
;
486 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
487 CpuFeaturesData
= GetCpuFeaturesData ();
491 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
492 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
494 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
496 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
497 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
498 switch (RegisterTableEntry
->RegisterType
) {
501 DebugPrintErrorLevel
,
502 "Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
503 (UINT32
) ProcessorNumber
,
504 (UINT32
) FeatureIndex
,
505 RegisterTableEntry
->Index
,
506 RegisterTableEntry
->ValidBitStart
,
507 RegisterTableEntry
->ValidBitLength
,
508 RegisterTableEntry
->Value
511 case ControlRegister
:
513 DebugPrintErrorLevel
,
514 "Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
515 (UINT32
) ProcessorNumber
,
516 (UINT32
) FeatureIndex
,
517 RegisterTableEntry
->Index
,
518 RegisterTableEntry
->ValidBitStart
,
519 RegisterTableEntry
->ValidBitLength
,
520 RegisterTableEntry
->Value
525 DebugPrintErrorLevel
,
526 "Processor: %04d: Index %04d, MMIO : %016lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
527 (UINT32
) ProcessorNumber
,
528 (UINT32
) FeatureIndex
,
529 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
530 RegisterTableEntry
->ValidBitStart
,
531 RegisterTableEntry
->ValidBitLength
,
532 RegisterTableEntry
->Value
537 DebugPrintErrorLevel
,
538 "Processor: %04d: Index %04d, CACHE: %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
539 (UINT32
) ProcessorNumber
,
540 (UINT32
) FeatureIndex
,
541 RegisterTableEntry
->Index
,
542 RegisterTableEntry
->ValidBitStart
,
543 RegisterTableEntry
->ValidBitLength
,
544 RegisterTableEntry
->Value
549 DebugPrintErrorLevel
,
550 "Processor: %04d: Index %04d, SEMAP: %s\r\n",
551 (UINT32
) ProcessorNumber
,
552 (UINT32
) FeatureIndex
,
553 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
564 Get the biggest dependence type.
565 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
567 @param[in] BeforeDep Before dependence type.
568 @param[in] AfterDep After dependence type.
569 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.
570 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.
572 @retval Return the biggest dependence type.
574 CPU_FEATURE_DEPENDENCE_TYPE
576 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
,
577 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep
,
578 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
,
579 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
582 CPU_FEATURE_DEPENDENCE_TYPE Bigger
;
584 Bigger
= MAX (BeforeDep
, AfterDep
);
585 Bigger
= MAX (Bigger
, NoneNeibBeforeDep
);
586 return MAX(Bigger
, NoneNeibAfterDep
);
590 Analysis register CPU features on each processor and save CPU setting in CPU register table.
592 @param[in] NumberOfCpus Number of processor in system
596 AnalysisProcessorFeatures (
597 IN UINTN NumberOfCpus
601 UINTN ProcessorNumber
;
602 CPU_FEATURES_ENTRY
*CpuFeature
;
603 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
604 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
605 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
607 CPU_FEATURES_DATA
*CpuFeaturesData
;
608 LIST_ENTRY
*NextEntry
;
609 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
611 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
612 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
613 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
;
614 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
;
616 CpuFeaturesData
= GetCpuFeaturesData ();
617 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
618 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
619 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
620 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
621 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
623 // Calculate the last capability on all processors
625 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
, CpuFeaturesData
->BitMaskSize
);
628 // Calculate the last setting
630 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
631 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
632 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
635 // Dump the last CPU feature list
638 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
639 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
640 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
641 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
642 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
643 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
644 DEBUG ((DEBUG_INFO
, "[Enable ] "));
646 DEBUG ((DEBUG_INFO
, "[Disable ] "));
649 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
651 DumpCpuFeature (CpuFeature
, CpuFeaturesData
->BitMaskSize
);
652 Entry
= Entry
->ForwardLink
;
654 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
655 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
656 DEBUG ((DEBUG_INFO
, "Origin PcdCpuFeaturesSetting:\n"));
657 DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
658 DEBUG ((DEBUG_INFO
, "Final PcdCpuFeaturesSetting:\n"));
659 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
663 // Save PCDs and display CPU PCDs
665 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
666 SetSettingPcd (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
668 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
669 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
670 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
671 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
673 // Insert each feature into processor's order list
675 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
676 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
677 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
678 ASSERT (CpuFeatureInOrder
!= NULL
);
679 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
681 Entry
= Entry
->ForwardLink
;
684 // Go through ordered feature list to initialize CPU features
686 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
687 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
688 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
689 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
692 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
693 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
694 if (EFI_ERROR (Status
)) {
696 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
698 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
699 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
700 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
702 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
703 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
709 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
710 if (EFI_ERROR (Status
)) {
711 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
712 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
714 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
715 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
723 NextEntry
= Entry
->ForwardLink
;
724 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
725 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
728 // If feature has dependence with the next feature (ONLY care core/package dependency).
729 // and feature initialize succeed, add sync semaphere here.
731 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
732 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
734 // Check whether next feature has After type dependence with not neighborhood CPU
735 // Features in former CPU features.
737 NoneNeibAfterDep
= DetectNoneNeighborhoodFeatureScope(NextCpuFeatureInOrder
, FALSE
, &CpuInitOrder
->OrderList
);
739 BeforeDep
= NoneDepType
;
740 AfterDep
= NoneDepType
;
741 NoneNeibAfterDep
= NoneDepType
;
744 // Check whether current feature has Before type dependence with none neighborhood
745 // CPU features in after Cpu features.
747 NoneNeibBeforeDep
= DetectNoneNeighborhoodFeatureScope(CpuFeatureInOrder
, TRUE
, &CpuInitOrder
->OrderList
);
750 // Get the biggest dependence and add semaphore for it.
751 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
753 BeforeDep
= BiggestDep(BeforeDep
, AfterDep
, NoneNeibBeforeDep
, NoneNeibAfterDep
);
754 if (BeforeDep
> ThreadDepType
) {
755 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
759 Entry
= Entry
->ForwardLink
;
763 // Dump PcdCpuFeaturesSetting again because this value maybe updated
764 // again during initialize the features.
766 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
767 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
770 // Dump the RegisterTable
772 DumpRegisterTableOnProcessor (ProcessorNumber
);
777 Increment semaphore by 1.
779 @param Sem IN: 32-bit unsigned integer
783 LibReleaseSemaphore (
784 IN OUT
volatile UINT32
*Sem
787 InterlockedIncrement (Sem
);
791 Decrement the semaphore by 1 if it is not zero.
793 Performs an atomic decrement operation for semaphore.
794 The compare exchange operation must be performed using
797 @param Sem IN: 32-bit unsigned integer
801 LibWaitForSemaphore (
802 IN OUT
volatile UINT32
*Sem
809 } while (Value
== 0 ||
810 InterlockedCompareExchange32 (
818 Read / write CR value.
820 @param[in] CrIndex The CR index which need to read/write.
821 @param[in] Read Read or write. TRUE is read.
822 @param[in,out] CrValue CR value.
824 @retval EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.
830 IN OUT UINTN
*CrValue
836 *CrValue
= AsmReadCr0 ();
838 AsmWriteCr0 (*CrValue
);
843 *CrValue
= AsmReadCr2 ();
845 AsmWriteCr2 (*CrValue
);
850 *CrValue
= AsmReadCr3 ();
852 AsmWriteCr3 (*CrValue
);
857 *CrValue
= AsmReadCr4 ();
859 AsmWriteCr4 (*CrValue
);
863 return EFI_UNSUPPORTED
;;
870 Initialize the CPU registers from a register table.
872 @param[in] RegisterTable The register table for this AP.
873 @param[in] ApLocation AP location info for this ap.
874 @param[in] CpuStatus CPU status info for this CPU.
875 @param[in] CpuFlags Flags data structure used when program the register.
877 @note This service could be called by BSP/APs.
880 ProgramProcessorRegister (
881 IN CPU_REGISTER_TABLE
*RegisterTable
,
882 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
883 IN CPU_STATUS_INFORMATION
*CpuStatus
,
884 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
887 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
890 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
891 volatile UINT32
*SemaphorePtr
;
893 UINT32 CurrentThread
;
895 UINTN ProcessorIndex
;
896 UINT32
*ThreadCountPerPackage
;
897 UINT8
*ThreadCountPerCore
;
902 // Traverse Register Table of this logical processor
904 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
906 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
908 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
911 // Check the type of specified register
913 switch (RegisterTableEntry
->RegisterType
) {
915 // The specified register is Control Register
917 case ControlRegister
:
918 Status
= ReadWriteCr (RegisterTableEntry
->Index
, TRUE
, &Value
);
919 if (EFI_ERROR (Status
)) {
922 if (RegisterTableEntry
->TestThenWrite
) {
923 CurrentValue
= BitFieldRead64 (
925 RegisterTableEntry
->ValidBitStart
,
926 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
928 if (CurrentValue
== RegisterTableEntry
->Value
) {
932 Value
= (UINTN
) BitFieldWrite64 (
934 RegisterTableEntry
->ValidBitStart
,
935 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
936 RegisterTableEntry
->Value
938 ReadWriteCr (RegisterTableEntry
->Index
, FALSE
, &Value
);
942 // The specified register is Model Specific Register
945 if (RegisterTableEntry
->TestThenWrite
) {
946 Value
= (UINTN
)AsmReadMsr64 (RegisterTableEntry
->Index
);
947 if (RegisterTableEntry
->ValidBitLength
>= 64) {
948 if (Value
== RegisterTableEntry
->Value
) {
952 CurrentValue
= BitFieldRead64 (
954 RegisterTableEntry
->ValidBitStart
,
955 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
957 if (CurrentValue
== RegisterTableEntry
->Value
) {
963 if (RegisterTableEntry
->ValidBitLength
>= 64) {
965 // If length is not less than 64 bits, then directly write without reading
968 RegisterTableEntry
->Index
,
969 RegisterTableEntry
->Value
973 // Set the bit section according to bit start and length
975 AsmMsrBitFieldWrite64 (
976 RegisterTableEntry
->Index
,
977 RegisterTableEntry
->ValidBitStart
,
978 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
979 RegisterTableEntry
->Value
984 // MemoryMapped operations
987 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
988 MmioBitFieldWrite32 (
989 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
990 RegisterTableEntry
->ValidBitStart
,
991 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
992 (UINT32
)RegisterTableEntry
->Value
994 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
997 // Enable or disable cache
1001 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
1003 if (RegisterTableEntry
->Value
== 0) {
1011 // Semaphore works logic like below:
1013 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
1014 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
1016 // All threads (T0...Tn) waits in P() line and continues running
1022 // V(0...n) V(0...n) ... V(0...n)
1023 // n * P(0) n * P(1) ... n * P(n)
1025 switch (RegisterTableEntry
->Value
) {
1027 SemaphorePtr
= CpuFlags
->CoreSemaphoreCount
;
1028 ThreadCountPerCore
= (UINT8
*)(UINTN
)CpuStatus
->ThreadCountPerCore
;
1030 CurrentCore
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
;
1032 // Get Offset info for the first thread in the core which current thread belongs to.
1034 FirstThread
= CurrentCore
* CpuStatus
->MaxThreadCount
;
1035 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
1038 // Different cores may have different valid threads in them. If driver maintail clearly
1039 // thread index in different cores, the logic will be much complicated.
1040 // Here driver just simply records the max thread number in all cores and use it as expect
1041 // thread number for all cores.
1042 // In below two steps logic, first current thread will Release semaphore for each thread
1043 // in current core. Maybe some threads are not valid in this core, but driver don't
1044 // care. Second, driver will let current thread wait semaphore for all valid threads in
1045 // current core. Because only the valid threads will do release semaphore for this
1046 // thread, driver here only need to wait the valid thread count.
1050 // First Notify ALL THREADs in current Core that this thread is ready.
1052 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
1053 LibReleaseSemaphore (&SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1056 // Second, check whether all VALID THREADs (not all threads) in current core are ready.
1058 for (ProcessorIndex
= 0; ProcessorIndex
< ThreadCountPerCore
[CurrentCore
]; ProcessorIndex
++) {
1059 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1063 case PackageDepType
:
1064 SemaphorePtr
= CpuFlags
->PackageSemaphoreCount
;
1065 ThreadCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ThreadCountPerPackage
;
1067 // Get Offset info for the first thread in the package which current thread belongs to.
1069 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
1071 // Get the possible threads count for current package.
1073 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
1076 // Different packages may have different valid threads in them. If driver maintail clearly
1077 // thread index in different packages, the logic will be much complicated.
1078 // Here driver just simply records the max thread number in all packages and use it as expect
1079 // thread number for all packages.
1080 // In below two steps logic, first current thread will Release semaphore for each thread
1081 // in current package. Maybe some threads are not valid in this package, but driver don't
1082 // care. Second, driver will let current thread wait semaphore for all valid threads in
1083 // current package. Because only the valid threads will do release semaphore for this
1084 // thread, driver here only need to wait the valid thread count.
1088 // First Notify ALL THREADS in current package that this thread is ready.
1090 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
; ProcessorIndex
++) {
1091 LibReleaseSemaphore (&SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1094 // Second, check whether VALID THREADS (not all threads) in current package are ready.
1096 for (ProcessorIndex
= 0; ProcessorIndex
< ThreadCountPerPackage
[ApLocation
->Package
]; ProcessorIndex
++) {
1097 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1113 Programs registers for the calling processor.
1115 @param[in,out] Buffer The pointer to private data buffer.
1120 SetProcessorRegister (
1124 CPU_FEATURES_DATA
*CpuFeaturesData
;
1125 CPU_REGISTER_TABLE
*RegisterTable
;
1126 CPU_REGISTER_TABLE
*RegisterTables
;
1130 ACPI_CPU_DATA
*AcpiCpuData
;
1132 CpuFeaturesData
= (CPU_FEATURES_DATA
*) Buffer
;
1133 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1135 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->RegisterTable
;
1137 InitApicId
= GetInitialApicId ();
1138 RegisterTable
= NULL
;
1139 ProcIndex
= (UINTN
)-1;
1140 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1141 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1142 RegisterTable
= &RegisterTables
[Index
];
1147 ASSERT (RegisterTable
!= NULL
);
1149 ProgramProcessorRegister (
1151 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->ApLocation
+ ProcIndex
,
1152 &AcpiCpuData
->CpuStatus
,
1153 &CpuFeaturesData
->CpuFlags
1158 Performs CPU features detection.
1160 This service will invoke MP service to check CPU features'
1161 capabilities on BSP/APs.
1163 @note This service could be called by BSP only.
1171 CPU_FEATURES_DATA
*CpuFeaturesData
;
1173 CpuFeaturesData
= GetCpuFeaturesData();
1175 CpuInitDataInitialize ();
1177 if (CpuFeaturesData
->NumberOfCpus
> 1) {
1179 // Wakeup all APs for data collection.
1181 StartupAllAPsWorker (CollectProcessorData
, NULL
);
1185 // Collect data on BSP
1187 CollectProcessorData (CpuFeaturesData
);
1189 AnalysisProcessorFeatures (CpuFeaturesData
->NumberOfCpus
);