2 CPU Features Initialize functions.
4 Copyright (c) 2017 - 2021, 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
;
112 ACPI_CPU_DATA
*AcpiCpuData
;
113 CPU_STATUS_INFORMATION
*CpuStatus
;
114 UINT32
*ThreadCountPerPackage
;
115 UINT8
*ThreadCountPerCore
;
117 UINTN NumberOfEnabledProcessors
;
123 CpuFeaturesData
= GetCpuFeaturesData ();
126 // Initialize CpuFeaturesData->MpService as early as possile, so later function can use it.
128 CpuFeaturesData
->MpService
= GetMpService ();
130 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
132 CpuFeaturesData
->InitOrder
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
));
133 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
134 ZeroMem (CpuFeaturesData
->InitOrder
, sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
137 // Collect CPU Features information
139 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
140 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
141 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
142 ASSERT (CpuFeature
->InitializeFunc
!= NULL
);
143 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
144 CpuFeature
->ConfigData
= CpuFeature
->GetConfigDataFunc (NumberOfCpus
);
147 Entry
= Entry
->ForwardLink
;
150 CpuFeaturesData
->NumberOfCpus
= (UINT32
)NumberOfCpus
;
152 AcpiCpuData
= GetAcpiCpuData ();
153 ASSERT (AcpiCpuData
!= NULL
);
154 CpuFeaturesData
->AcpiCpuData
= AcpiCpuData
;
156 CpuStatus
= &AcpiCpuData
->CpuFeatureInitData
.CpuStatus
;
157 Location
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
));
158 ASSERT (Location
!= NULL
);
159 ZeroMem (Location
, sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
);
160 AcpiCpuData
->CpuFeatureInitData
.ApLocation
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Location
;
162 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
163 InitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
164 InitOrder
->FeaturesSupportedMask
= AllocateZeroPool (CpuFeaturesData
->BitMaskSize
);
165 ASSERT (InitOrder
->FeaturesSupportedMask
!= NULL
);
166 InitializeListHead (&InitOrder
->OrderList
);
167 Status
= GetProcessorInformation (ProcessorNumber
, &ProcessorInfoBuffer
);
168 ASSERT_EFI_ERROR (Status
);
170 &InitOrder
->CpuInfo
.ProcessorInfo
,
171 &ProcessorInfoBuffer
,
172 sizeof (EFI_PROCESSOR_INFORMATION
)
175 &Location
[ProcessorNumber
],
176 &ProcessorInfoBuffer
.Location
,
177 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
181 // Collect CPU package count info.
183 if (Package
< ProcessorInfoBuffer
.Location
.Package
) {
184 Package
= ProcessorInfoBuffer
.Location
.Package
;
188 // Collect CPU max core count info.
190 if (Core
< ProcessorInfoBuffer
.Location
.Core
) {
191 Core
= ProcessorInfoBuffer
.Location
.Core
;
195 // Collect CPU max thread count info.
197 if (Thread
< ProcessorInfoBuffer
.Location
.Thread
) {
198 Thread
= ProcessorInfoBuffer
.Location
.Thread
;
202 CpuStatus
->PackageCount
= Package
+ 1;
203 CpuStatus
->MaxCoreCount
= Core
+ 1;
204 CpuStatus
->MaxThreadCount
= Thread
+ 1;
207 "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",
208 CpuStatus
->PackageCount
,
209 CpuStatus
->MaxCoreCount
,
210 CpuStatus
->MaxThreadCount
214 // Collect valid core count in each package because not all cores are valid.
216 ThreadCountPerPackage
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (UINT32
) * CpuStatus
->PackageCount
));
217 ASSERT (ThreadCountPerPackage
!= NULL
);
218 ZeroMem (ThreadCountPerPackage
, sizeof (UINT32
) * CpuStatus
->PackageCount
);
219 CpuStatus
->ThreadCountPerPackage
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ThreadCountPerPackage
;
221 ThreadCountPerCore
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (UINT8
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
));
222 ASSERT (ThreadCountPerCore
!= NULL
);
223 ZeroMem (ThreadCountPerCore
, sizeof (UINT8
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
);
224 CpuStatus
->ThreadCountPerCore
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ThreadCountPerCore
;
226 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
227 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
228 ThreadCountPerPackage
[Location
->Package
]++;
229 ThreadCountPerCore
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]++;
232 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
233 if (ThreadCountPerPackage
[PackageIndex
] != 0) {
234 DEBUG ((DEBUG_INFO
, "P%02d: Thread Count = %d\n", PackageIndex
, ThreadCountPerPackage
[PackageIndex
]));
235 for (CoreIndex
= 0; CoreIndex
< CpuStatus
->MaxCoreCount
; CoreIndex
++) {
236 if (ThreadCountPerCore
[PackageIndex
* CpuStatus
->MaxCoreCount
+ CoreIndex
] != 0) {
239 " P%02d C%04d, Thread Count = %d\n",
242 ThreadCountPerCore
[PackageIndex
* CpuStatus
->MaxCoreCount
+ CoreIndex
]
249 CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
250 ASSERT (CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
!= NULL
);
251 CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
252 ASSERT (CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
!= NULL
);
255 // Initialize CpuFeaturesData->InitOrder[].CpuInfo.First
256 // Use AllocatePages () instead of AllocatePool () because pool cannot be freed in PEI phase but page can.
258 Pages
= EFI_SIZE_TO_PAGES (CpuStatus
->PackageCount
* sizeof (UINT32
) + CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* sizeof (UINT32
));
259 FirstCore
= AllocatePages (Pages
);
260 ASSERT (FirstCore
!= NULL
);
261 FirstThread
= FirstCore
+ CpuStatus
->PackageCount
;
264 // Set FirstPackage, FirstCore[], FirstThread[] to maximum package ID, core ID, thread ID.
266 FirstPackage
= MAX_UINT32
;
267 SetMem32 (FirstCore
, CpuStatus
->PackageCount
* sizeof (UINT32
), MAX_UINT32
);
268 SetMem32 (FirstThread
, CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* sizeof (UINT32
), MAX_UINT32
);
270 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
271 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
274 // Save the minimum package ID in the platform.
276 FirstPackage
= MIN (Location
->Package
, FirstPackage
);
279 // Save the minimum core ID per package.
281 FirstCore
[Location
->Package
] = MIN (Location
->Core
, FirstCore
[Location
->Package
]);
284 // Save the minimum thread ID per core.
286 FirstThread
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
] = MIN (
288 FirstThread
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]
293 // Update the First field.
295 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
296 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
298 if (Location
->Package
== FirstPackage
) {
299 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Package
= 1;
303 // Set First.Die/Tile/Module for each thread assuming:
304 // single Die under each package, single Tile under each Die, single Module under each Tile
306 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Die
= 1;
307 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Tile
= 1;
308 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Module
= 1;
310 if (Location
->Core
== FirstCore
[Location
->Package
]) {
311 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Core
= 1;
314 if (Location
->Thread
== FirstThread
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]) {
315 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Thread
= 1;
319 FreePages (FirstCore
, Pages
);
323 Worker function to do OR operation on CPU feature supported bits mask buffer.
325 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
326 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
327 @param[in] BitMaskSize The CPU feature bits mask buffer size.
332 IN UINT8
*SupportedFeatureMask
,
333 IN UINT8
*OrFeatureBitMask
,
334 IN UINT32 BitMaskSize
341 Data1
= SupportedFeatureMask
;
342 Data2
= OrFeatureBitMask
;
343 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
344 *(Data1
++) |= *(Data2
++);
349 Worker function to do AND operation on CPU feature supported bits mask buffer.
351 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
352 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
353 @param[in] BitMaskSize CPU feature bits mask buffer size.
358 IN UINT8
*SupportedFeatureMask
,
359 IN CONST UINT8
*AndFeatureBitMask
,
360 IN UINT32 BitMaskSize
367 Data1
= SupportedFeatureMask
;
368 Data2
= AndFeatureBitMask
;
369 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
370 *(Data1
++) &= *(Data2
++);
375 Worker function to clean bit operation on CPU feature supported bits mask buffer.
377 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
378 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
379 @param[in] BitMaskSize CPU feature bits mask buffer size.
382 SupportedMaskCleanBit (
383 IN UINT8
*SupportedFeatureMask
,
384 IN UINT8
*AndFeatureBitMask
,
385 IN UINT32 BitMaskSize
392 Data1
= SupportedFeatureMask
;
393 Data2
= AndFeatureBitMask
;
394 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
395 *(Data1
++) &= ~(*(Data2
++));
400 Worker function to check if the compared CPU feature set in the CPU feature
401 supported bits mask buffer.
403 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
404 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
405 @param[in] BitMaskSize CPU feature bits mask buffer size.
407 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
409 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
414 IN UINT8
*SupportedFeatureMask
,
415 IN UINT8
*ComparedFeatureBitMask
,
416 IN UINT32 BitMaskSize
423 Data1
= SupportedFeatureMask
;
424 Data2
= ComparedFeatureBitMask
;
425 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
426 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
435 Collects processor data for calling processor.
437 @param[in,out] Buffer The pointer to private data buffer.
441 CollectProcessorData (
445 UINTN ProcessorNumber
;
446 CPU_FEATURES_ENTRY
*CpuFeature
;
447 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
449 CPU_FEATURES_DATA
*CpuFeaturesData
;
451 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
452 ProcessorNumber
= GetProcessorIndex (CpuFeaturesData
);
453 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
455 // collect processor information
457 FillProcessorInfo (CpuInfo
);
458 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
459 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
460 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
461 if (CpuFeature
->SupportFunc
== NULL
) {
463 // If SupportFunc is NULL, then the feature is supported.
466 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
467 CpuFeature
->FeatureMask
,
468 CpuFeaturesData
->BitMaskSize
470 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
472 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
473 CpuFeature
->FeatureMask
,
474 CpuFeaturesData
->BitMaskSize
478 Entry
= Entry
->ForwardLink
;
483 Dump the contents of a CPU register table.
485 @param[in] ProcessorNumber The index of the CPU to show the register table contents
487 @note This service could be called by BSP only.
490 DumpRegisterTableOnProcessor (
491 IN UINTN ProcessorNumber
494 CPU_FEATURES_DATA
*CpuFeaturesData
;
496 CPU_REGISTER_TABLE
*RegisterTable
;
497 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
498 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
499 UINT32 DebugPrintErrorLevel
;
501 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
502 CpuFeaturesData
= GetCpuFeaturesData ();
506 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
507 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
509 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*)(UINTN
)RegisterTable
->RegisterTableEntry
;
511 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
512 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
513 switch (RegisterTableEntry
->RegisterType
) {
516 DebugPrintErrorLevel
,
517 "Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
518 (UINT32
)ProcessorNumber
,
519 (UINT32
)FeatureIndex
,
520 RegisterTableEntry
->Index
,
521 RegisterTableEntry
->ValidBitStart
,
522 RegisterTableEntry
->ValidBitLength
,
523 RegisterTableEntry
->Value
526 case ControlRegister
:
528 DebugPrintErrorLevel
,
529 "Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
530 (UINT32
)ProcessorNumber
,
531 (UINT32
)FeatureIndex
,
532 RegisterTableEntry
->Index
,
533 RegisterTableEntry
->ValidBitStart
,
534 RegisterTableEntry
->ValidBitLength
,
535 RegisterTableEntry
->Value
540 DebugPrintErrorLevel
,
541 "Processor: %04d: Index %04d, MMIO : %016lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
542 (UINT32
)ProcessorNumber
,
543 (UINT32
)FeatureIndex
,
544 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
545 RegisterTableEntry
->ValidBitStart
,
546 RegisterTableEntry
->ValidBitLength
,
547 RegisterTableEntry
->Value
552 DebugPrintErrorLevel
,
553 "Processor: %04d: Index %04d, CACHE: %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
554 (UINT32
)ProcessorNumber
,
555 (UINT32
)FeatureIndex
,
556 RegisterTableEntry
->Index
,
557 RegisterTableEntry
->ValidBitStart
,
558 RegisterTableEntry
->ValidBitLength
,
559 RegisterTableEntry
->Value
564 DebugPrintErrorLevel
,
565 "Processor: %04d: Index %04d, SEMAP: %s\r\n",
566 (UINT32
)ProcessorNumber
,
567 (UINT32
)FeatureIndex
,
568 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
579 Get the biggest dependence type.
580 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
582 @param[in] BeforeDep Before dependence type.
583 @param[in] AfterDep After dependence type.
584 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.
585 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.
587 @retval Return the biggest dependence type.
589 CPU_FEATURE_DEPENDENCE_TYPE
591 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
,
592 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep
,
593 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
,
594 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
597 CPU_FEATURE_DEPENDENCE_TYPE Bigger
;
599 Bigger
= MAX (BeforeDep
, AfterDep
);
600 Bigger
= MAX (Bigger
, NoneNeibBeforeDep
);
601 return MAX (Bigger
, NoneNeibAfterDep
);
605 Analysis register CPU features on each processor and save CPU setting in CPU register table.
607 @param[in] NumberOfCpus Number of processor in system
611 AnalysisProcessorFeatures (
612 IN UINTN NumberOfCpus
616 UINTN ProcessorNumber
;
617 CPU_FEATURES_ENTRY
*CpuFeature
;
618 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
619 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
620 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
622 CPU_FEATURES_DATA
*CpuFeaturesData
;
623 LIST_ENTRY
*NextEntry
;
624 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
626 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
627 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
628 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
;
629 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
;
631 CpuFeaturesData
= GetCpuFeaturesData ();
632 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
633 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
634 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
635 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
636 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
638 // Calculate the last capability on all processors
640 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
, CpuFeaturesData
->BitMaskSize
);
644 // Calculate the last setting
646 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
647 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
648 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
651 // Dump the last CPU feature list
654 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
655 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
656 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
657 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
658 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
659 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
660 DEBUG ((DEBUG_INFO
, "[Enable ] "));
662 DEBUG ((DEBUG_INFO
, "[Disable ] "));
665 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
668 DumpCpuFeature (CpuFeature
, CpuFeaturesData
->BitMaskSize
);
669 Entry
= Entry
->ForwardLink
;
672 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
673 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
674 DEBUG ((DEBUG_INFO
, "Origin PcdCpuFeaturesSetting:\n"));
675 DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
676 DEBUG ((DEBUG_INFO
, "Final PcdCpuFeaturesSetting:\n"));
677 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
681 // Save PCDs and display CPU PCDs
683 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
684 SetSettingPcd (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
686 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
687 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
688 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
689 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
691 // Insert each feature into processor's order list
693 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
694 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
695 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
696 ASSERT (CpuFeatureInOrder
!= NULL
);
697 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
700 Entry
= Entry
->ForwardLink
;
704 // Go through ordered feature list to initialize CPU features
706 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
707 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
708 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
709 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
712 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
713 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
714 if (EFI_ERROR (Status
)) {
716 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
718 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
719 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
720 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
722 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
723 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
729 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
730 if (EFI_ERROR (Status
)) {
731 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
732 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
734 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
735 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
743 NextEntry
= Entry
->ForwardLink
;
744 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
745 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
748 // If feature has dependence with the next feature (ONLY care core/package dependency).
749 // and feature initialize succeed, add sync semaphere here.
751 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
752 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
754 // Check whether next feature has After type dependence with not neighborhood CPU
755 // Features in former CPU features.
757 NoneNeibAfterDep
= DetectNoneNeighborhoodFeatureScope (NextCpuFeatureInOrder
, FALSE
, &CpuInitOrder
->OrderList
);
759 BeforeDep
= NoneDepType
;
760 AfterDep
= NoneDepType
;
761 NoneNeibAfterDep
= NoneDepType
;
765 // Check whether current feature has Before type dependence with none neighborhood
766 // CPU features in after Cpu features.
768 NoneNeibBeforeDep
= DetectNoneNeighborhoodFeatureScope (CpuFeatureInOrder
, TRUE
, &CpuInitOrder
->OrderList
);
771 // Get the biggest dependence and add semaphore for it.
772 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
774 BeforeDep
= BiggestDep (BeforeDep
, AfterDep
, NoneNeibBeforeDep
, NoneNeibAfterDep
);
775 if (BeforeDep
> ThreadDepType
) {
776 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
780 Entry
= Entry
->ForwardLink
;
784 // Dump PcdCpuFeaturesSetting again because this value maybe updated
785 // again during initialize the features.
787 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
788 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
791 // Dump the RegisterTable
793 DumpRegisterTableOnProcessor (ProcessorNumber
);
798 Increment semaphore by 1.
800 @param Sem IN: 32-bit unsigned integer
804 LibReleaseSemaphore (
805 IN OUT
volatile UINT32
*Sem
808 InterlockedIncrement (Sem
);
812 Decrement the semaphore by 1 if it is not zero.
814 Performs an atomic decrement operation for semaphore.
815 The compare exchange operation must be performed using
818 @param Sem IN: 32-bit unsigned integer
822 LibWaitForSemaphore (
823 IN OUT
volatile UINT32
*Sem
830 } while (Value
== 0 ||
831 InterlockedCompareExchange32 (
839 Read / write CR value.
841 @param[in] CrIndex The CR index which need to read/write.
842 @param[in] Read Read or write. TRUE is read.
843 @param[in,out] CrValue CR value.
845 @retval EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.
851 IN OUT UINTN
*CrValue
857 *CrValue
= AsmReadCr0 ();
859 AsmWriteCr0 (*CrValue
);
865 *CrValue
= AsmReadCr2 ();
867 AsmWriteCr2 (*CrValue
);
873 *CrValue
= AsmReadCr3 ();
875 AsmWriteCr3 (*CrValue
);
881 *CrValue
= AsmReadCr4 ();
883 AsmWriteCr4 (*CrValue
);
888 return EFI_UNSUPPORTED
;
895 Initialize the CPU registers from a register table.
897 @param[in] RegisterTable The register table for this AP.
898 @param[in] ApLocation AP location info for this ap.
899 @param[in] CpuStatus CPU status info for this CPU.
900 @param[in] CpuFlags Flags data structure used when program the register.
902 @note This service could be called by BSP/APs.
905 ProgramProcessorRegister (
906 IN CPU_REGISTER_TABLE
*RegisterTable
,
907 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
908 IN CPU_STATUS_INFORMATION
*CpuStatus
,
909 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
912 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
915 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
916 volatile UINT32
*SemaphorePtr
;
918 UINT32 CurrentThread
;
920 UINTN ProcessorIndex
;
921 UINT32
*ThreadCountPerPackage
;
922 UINT8
*ThreadCountPerCore
;
927 // Traverse Register Table of this logical processor
929 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*)(UINTN
)RegisterTable
->RegisterTableEntry
;
931 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
932 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
935 // Check the type of specified register
937 switch (RegisterTableEntry
->RegisterType
) {
939 // The specified register is Control Register
941 case ControlRegister
:
942 Status
= ReadWriteCr (RegisterTableEntry
->Index
, TRUE
, &Value
);
943 if (EFI_ERROR (Status
)) {
947 if (RegisterTableEntry
->TestThenWrite
) {
948 CurrentValue
= BitFieldRead64 (
950 RegisterTableEntry
->ValidBitStart
,
951 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
953 if (CurrentValue
== RegisterTableEntry
->Value
) {
958 Value
= (UINTN
)BitFieldWrite64 (
960 RegisterTableEntry
->ValidBitStart
,
961 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
962 RegisterTableEntry
->Value
964 ReadWriteCr (RegisterTableEntry
->Index
, FALSE
, &Value
);
968 // The specified register is Model Specific Register
971 if (RegisterTableEntry
->TestThenWrite
) {
972 Value
= (UINTN
)AsmReadMsr64 (RegisterTableEntry
->Index
);
973 if (RegisterTableEntry
->ValidBitLength
>= 64) {
974 if (Value
== RegisterTableEntry
->Value
) {
978 CurrentValue
= BitFieldRead64 (
980 RegisterTableEntry
->ValidBitStart
,
981 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
983 if (CurrentValue
== RegisterTableEntry
->Value
) {
989 if (RegisterTableEntry
->ValidBitLength
>= 64) {
991 // If length is not less than 64 bits, then directly write without reading
994 RegisterTableEntry
->Index
,
995 RegisterTableEntry
->Value
999 // Set the bit section according to bit start and length
1001 AsmMsrBitFieldWrite64 (
1002 RegisterTableEntry
->Index
,
1003 RegisterTableEntry
->ValidBitStart
,
1004 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
1005 RegisterTableEntry
->Value
1011 // MemoryMapped operations
1014 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
1015 MmioBitFieldWrite32 (
1016 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
1017 RegisterTableEntry
->ValidBitStart
,
1018 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
1019 (UINT32
)RegisterTableEntry
->Value
1021 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
1024 // Enable or disable cache
1028 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
1030 if (RegisterTableEntry
->Value
== 0) {
1039 // Semaphore works logic like below:
1041 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
1042 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
1044 // All threads (T0...Tn) waits in P() line and continues running
1050 // V(0...n) V(0...n) ... V(0...n)
1051 // n * P(0) n * P(1) ... n * P(n)
1053 switch (RegisterTableEntry
->Value
) {
1055 SemaphorePtr
= CpuFlags
->CoreSemaphoreCount
;
1056 ThreadCountPerCore
= (UINT8
*)(UINTN
)CpuStatus
->ThreadCountPerCore
;
1058 CurrentCore
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
;
1060 // Get Offset info for the first thread in the core which current thread belongs to.
1062 FirstThread
= CurrentCore
* CpuStatus
->MaxThreadCount
;
1063 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
1066 // Different cores may have different valid threads in them. If driver maintail clearly
1067 // thread index in different cores, the logic will be much complicated.
1068 // Here driver just simply records the max thread number in all cores and use it as expect
1069 // thread number for all cores.
1070 // In below two steps logic, first current thread will Release semaphore for each thread
1071 // in current core. Maybe some threads are not valid in this core, but driver don't
1072 // care. Second, driver will let current thread wait semaphore for all valid threads in
1073 // current core. Because only the valid threads will do release semaphore for this
1074 // thread, driver here only need to wait the valid thread count.
1078 // First Notify ALL THREADs in current Core that this thread is ready.
1080 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
1081 LibReleaseSemaphore (&SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1085 // Second, check whether all VALID THREADs (not all threads) in current core are ready.
1087 for (ProcessorIndex
= 0; ProcessorIndex
< ThreadCountPerCore
[CurrentCore
]; ProcessorIndex
++) {
1088 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1093 case PackageDepType
:
1094 SemaphorePtr
= CpuFlags
->PackageSemaphoreCount
;
1095 ThreadCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ThreadCountPerPackage
;
1097 // Get Offset info for the first thread in the package which current thread belongs to.
1099 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
1101 // Get the possible threads count for current package.
1103 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
1106 // Different packages may have different valid threads in them. If driver maintail clearly
1107 // thread index in different packages, the logic will be much complicated.
1108 // Here driver just simply records the max thread number in all packages and use it as expect
1109 // thread number for all packages.
1110 // In below two steps logic, first current thread will Release semaphore for each thread
1111 // in current package. Maybe some threads are not valid in this package, but driver don't
1112 // care. Second, driver will let current thread wait semaphore for all valid threads in
1113 // current package. Because only the valid threads will do release semaphore for this
1114 // thread, driver here only need to wait the valid thread count.
1118 // First Notify ALL THREADS in current package that this thread is ready.
1120 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
; ProcessorIndex
++) {
1121 LibReleaseSemaphore (&SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1125 // Second, check whether VALID THREADS (not all threads) in current package are ready.
1127 for (ProcessorIndex
= 0; ProcessorIndex
< ThreadCountPerPackage
[ApLocation
->Package
]; ProcessorIndex
++) {
1128 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1146 Programs registers for the calling processor.
1148 @param[in,out] Buffer The pointer to private data buffer.
1153 SetProcessorRegister (
1157 CPU_FEATURES_DATA
*CpuFeaturesData
;
1158 CPU_REGISTER_TABLE
*RegisterTable
;
1159 CPU_REGISTER_TABLE
*RegisterTables
;
1163 ACPI_CPU_DATA
*AcpiCpuData
;
1165 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
1166 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1168 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->CpuFeatureInitData
.RegisterTable
;
1170 InitApicId
= GetInitialApicId ();
1171 RegisterTable
= NULL
;
1172 ProcIndex
= (UINTN
)-1;
1173 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1174 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1175 RegisterTable
= &RegisterTables
[Index
];
1181 ASSERT (RegisterTable
!= NULL
);
1183 ProgramProcessorRegister (
1185 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->CpuFeatureInitData
.ApLocation
+ ProcIndex
,
1186 &AcpiCpuData
->CpuFeatureInitData
.CpuStatus
,
1187 &CpuFeaturesData
->CpuFlags
1192 Performs CPU features detection.
1194 This service will invoke MP service to check CPU features'
1195 capabilities on BSP/APs.
1197 @note This service could be called by BSP only.
1205 CPU_FEATURES_DATA
*CpuFeaturesData
;
1207 CpuFeaturesData
= GetCpuFeaturesData ();
1209 CpuInitDataInitialize ();
1211 if (CpuFeaturesData
->NumberOfCpus
> 1) {
1213 // Wakeup all APs for data collection.
1215 StartupAllAPsWorker (CollectProcessorData
, NULL
);
1219 // Collect data on BSP
1221 CollectProcessorData (CpuFeaturesData
);
1223 AnalysisProcessorFeatures (CpuFeaturesData
->NumberOfCpus
);