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
);
146 Entry
= Entry
->ForwardLink
;
149 CpuFeaturesData
->NumberOfCpus
= (UINT32
) NumberOfCpus
;
151 AcpiCpuData
= GetAcpiCpuData ();
152 ASSERT (AcpiCpuData
!= NULL
);
153 CpuFeaturesData
->AcpiCpuData
= AcpiCpuData
;
155 CpuStatus
= &AcpiCpuData
->CpuFeatureInitData
.CpuStatus
;
156 Location
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
));
157 ASSERT (Location
!= NULL
);
158 ZeroMem (Location
, sizeof (EFI_CPU_PHYSICAL_LOCATION
) * NumberOfCpus
);
159 AcpiCpuData
->CpuFeatureInitData
.ApLocation
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Location
;
161 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
162 InitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
163 InitOrder
->FeaturesSupportedMask
= AllocateZeroPool (CpuFeaturesData
->BitMaskSize
);
164 ASSERT (InitOrder
->FeaturesSupportedMask
!= NULL
);
165 InitializeListHead (&InitOrder
->OrderList
);
166 Status
= GetProcessorInformation (ProcessorNumber
, &ProcessorInfoBuffer
);
167 ASSERT_EFI_ERROR (Status
);
169 &InitOrder
->CpuInfo
.ProcessorInfo
,
170 &ProcessorInfoBuffer
,
171 sizeof (EFI_PROCESSOR_INFORMATION
)
174 &Location
[ProcessorNumber
],
175 &ProcessorInfoBuffer
.Location
,
176 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
180 // Collect CPU package count info.
182 if (Package
< ProcessorInfoBuffer
.Location
.Package
) {
183 Package
= ProcessorInfoBuffer
.Location
.Package
;
186 // Collect CPU max core count info.
188 if (Core
< ProcessorInfoBuffer
.Location
.Core
) {
189 Core
= ProcessorInfoBuffer
.Location
.Core
;
192 // Collect CPU max thread count info.
194 if (Thread
< ProcessorInfoBuffer
.Location
.Thread
) {
195 Thread
= ProcessorInfoBuffer
.Location
.Thread
;
198 CpuStatus
->PackageCount
= Package
+ 1;
199 CpuStatus
->MaxCoreCount
= Core
+ 1;
200 CpuStatus
->MaxThreadCount
= Thread
+ 1;
201 DEBUG ((DEBUG_INFO
, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",
202 CpuStatus
->PackageCount
,
203 CpuStatus
->MaxCoreCount
,
204 CpuStatus
->MaxThreadCount
));
207 // Collect valid core count in each package because not all cores are valid.
209 ThreadCountPerPackage
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (UINT32
) * CpuStatus
->PackageCount
));
210 ASSERT (ThreadCountPerPackage
!= NULL
);
211 ZeroMem (ThreadCountPerPackage
, sizeof (UINT32
) * CpuStatus
->PackageCount
);
212 CpuStatus
->ThreadCountPerPackage
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ThreadCountPerPackage
;
214 ThreadCountPerCore
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (UINT8
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
));
215 ASSERT (ThreadCountPerCore
!= NULL
);
216 ZeroMem (ThreadCountPerCore
, sizeof (UINT8
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
);
217 CpuStatus
->ThreadCountPerCore
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ThreadCountPerCore
;
219 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
220 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
221 ThreadCountPerPackage
[Location
->Package
]++;
222 ThreadCountPerCore
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]++;
225 for (PackageIndex
= 0; PackageIndex
< CpuStatus
->PackageCount
; PackageIndex
++) {
226 if (ThreadCountPerPackage
[PackageIndex
] != 0) {
227 DEBUG ((DEBUG_INFO
, "P%02d: Thread Count = %d\n", PackageIndex
, ThreadCountPerPackage
[PackageIndex
]));
228 for (CoreIndex
= 0; CoreIndex
< CpuStatus
->MaxCoreCount
; CoreIndex
++) {
229 if (ThreadCountPerCore
[PackageIndex
* CpuStatus
->MaxCoreCount
+ CoreIndex
] != 0) {
231 DEBUG_INFO
, " P%02d C%04d, Thread Count = %d\n", PackageIndex
, CoreIndex
,
232 ThreadCountPerCore
[PackageIndex
* CpuStatus
->MaxCoreCount
+ CoreIndex
]
239 CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
240 ASSERT (CpuFeaturesData
->CpuFlags
.CoreSemaphoreCount
!= NULL
);
241 CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
= AllocateZeroPool (sizeof (UINT32
) * CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
);
242 ASSERT (CpuFeaturesData
->CpuFlags
.PackageSemaphoreCount
!= NULL
);
245 // Initialize CpuFeaturesData->InitOrder[].CpuInfo.First
246 // Use AllocatePages () instead of AllocatePool () because pool cannot be freed in PEI phase but page can.
248 Pages
= EFI_SIZE_TO_PAGES (CpuStatus
->PackageCount
* sizeof (UINT32
) + CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* sizeof (UINT32
));
249 FirstCore
= AllocatePages (Pages
);
250 ASSERT (FirstCore
!= NULL
);
251 FirstThread
= FirstCore
+ CpuStatus
->PackageCount
;
254 // Set FirstPackage, FirstCore[], FirstThread[] to maximum package ID, core ID, thread ID.
256 FirstPackage
= MAX_UINT32
;
257 SetMem32 (FirstCore
, CpuStatus
->PackageCount
* sizeof (UINT32
), MAX_UINT32
);
258 SetMem32 (FirstThread
, CpuStatus
->PackageCount
* CpuStatus
->MaxCoreCount
* sizeof (UINT32
), MAX_UINT32
);
260 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
261 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
264 // Save the minimum package ID in the platform.
266 FirstPackage
= MIN (Location
->Package
, FirstPackage
);
269 // Save the minimum core ID per package.
271 FirstCore
[Location
->Package
] = MIN (Location
->Core
, FirstCore
[Location
->Package
]);
274 // Save the minimum thread ID per core.
276 FirstThread
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
] = MIN (
278 FirstThread
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]
283 // Update the First field.
285 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
286 Location
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.ProcessorInfo
.Location
;
288 if (Location
->Package
== FirstPackage
) {
289 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Package
= 1;
293 // Set First.Die/Tile/Module for each thread assuming:
294 // single Die under each package, single Tile under each Die, single Module under each Tile
296 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Die
= 1;
297 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Tile
= 1;
298 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Module
= 1;
300 if (Location
->Core
== FirstCore
[Location
->Package
]) {
301 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Core
= 1;
303 if (Location
->Thread
== FirstThread
[Location
->Package
* CpuStatus
->MaxCoreCount
+ Location
->Core
]) {
304 CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
.First
.Thread
= 1;
308 FreePages (FirstCore
, Pages
);
312 Worker function to do OR operation on CPU feature supported bits mask buffer.
314 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
315 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
316 @param[in] BitMaskSize The CPU feature bits mask buffer size.
321 IN UINT8
*SupportedFeatureMask
,
322 IN UINT8
*OrFeatureBitMask
,
323 IN UINT32 BitMaskSize
330 Data1
= SupportedFeatureMask
;
331 Data2
= OrFeatureBitMask
;
332 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
333 *(Data1
++) |= *(Data2
++);
338 Worker function to do AND operation on CPU feature supported bits mask buffer.
340 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
341 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
342 @param[in] BitMaskSize CPU feature bits mask buffer size.
347 IN UINT8
*SupportedFeatureMask
,
348 IN CONST UINT8
*AndFeatureBitMask
,
349 IN UINT32 BitMaskSize
356 Data1
= SupportedFeatureMask
;
357 Data2
= AndFeatureBitMask
;
358 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
359 *(Data1
++) &= *(Data2
++);
364 Worker function to clean bit operation on CPU feature supported bits mask buffer.
366 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
367 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation
368 @param[in] BitMaskSize CPU feature bits mask buffer size.
371 SupportedMaskCleanBit (
372 IN UINT8
*SupportedFeatureMask
,
373 IN UINT8
*AndFeatureBitMask
,
374 IN UINT32 BitMaskSize
381 Data1
= SupportedFeatureMask
;
382 Data2
= AndFeatureBitMask
;
383 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
384 *(Data1
++) &= ~(*(Data2
++));
389 Worker function to check if the compared CPU feature set in the CPU feature
390 supported bits mask buffer.
392 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
393 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
394 @param[in] BitMaskSize CPU feature bits mask buffer size.
396 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
398 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
403 IN UINT8
*SupportedFeatureMask
,
404 IN UINT8
*ComparedFeatureBitMask
,
405 IN UINT32 BitMaskSize
412 Data1
= SupportedFeatureMask
;
413 Data2
= ComparedFeatureBitMask
;
414 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
415 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
423 Collects processor data for calling processor.
425 @param[in,out] Buffer The pointer to private data buffer.
429 CollectProcessorData (
433 UINTN ProcessorNumber
;
434 CPU_FEATURES_ENTRY
*CpuFeature
;
435 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
437 CPU_FEATURES_DATA
*CpuFeaturesData
;
439 CpuFeaturesData
= (CPU_FEATURES_DATA
*)Buffer
;
440 ProcessorNumber
= GetProcessorIndex (CpuFeaturesData
);
441 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
443 // collect processor information
445 FillProcessorInfo (CpuInfo
);
446 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
447 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
448 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
449 if (CpuFeature
->SupportFunc
== NULL
) {
451 // If SupportFunc is NULL, then the feature is supported.
454 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
455 CpuFeature
->FeatureMask
,
456 CpuFeaturesData
->BitMaskSize
458 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
460 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
461 CpuFeature
->FeatureMask
,
462 CpuFeaturesData
->BitMaskSize
465 Entry
= Entry
->ForwardLink
;
470 Dump the contents of a CPU register table.
472 @param[in] ProcessorNumber The index of the CPU to show the register table contents
474 @note This service could be called by BSP only.
477 DumpRegisterTableOnProcessor (
478 IN UINTN ProcessorNumber
481 CPU_FEATURES_DATA
*CpuFeaturesData
;
483 CPU_REGISTER_TABLE
*RegisterTable
;
484 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
485 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
486 UINT32 DebugPrintErrorLevel
;
488 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
489 CpuFeaturesData
= GetCpuFeaturesData ();
493 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
494 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
496 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
498 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
499 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
500 switch (RegisterTableEntry
->RegisterType
) {
503 DebugPrintErrorLevel
,
504 "Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
505 (UINT32
) ProcessorNumber
,
506 (UINT32
) FeatureIndex
,
507 RegisterTableEntry
->Index
,
508 RegisterTableEntry
->ValidBitStart
,
509 RegisterTableEntry
->ValidBitLength
,
510 RegisterTableEntry
->Value
513 case ControlRegister
:
515 DebugPrintErrorLevel
,
516 "Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
517 (UINT32
) ProcessorNumber
,
518 (UINT32
) FeatureIndex
,
519 RegisterTableEntry
->Index
,
520 RegisterTableEntry
->ValidBitStart
,
521 RegisterTableEntry
->ValidBitLength
,
522 RegisterTableEntry
->Value
527 DebugPrintErrorLevel
,
528 "Processor: %04d: Index %04d, MMIO : %016lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
529 (UINT32
) ProcessorNumber
,
530 (UINT32
) FeatureIndex
,
531 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
532 RegisterTableEntry
->ValidBitStart
,
533 RegisterTableEntry
->ValidBitLength
,
534 RegisterTableEntry
->Value
539 DebugPrintErrorLevel
,
540 "Processor: %04d: Index %04d, CACHE: %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",
541 (UINT32
) ProcessorNumber
,
542 (UINT32
) FeatureIndex
,
543 RegisterTableEntry
->Index
,
544 RegisterTableEntry
->ValidBitStart
,
545 RegisterTableEntry
->ValidBitLength
,
546 RegisterTableEntry
->Value
551 DebugPrintErrorLevel
,
552 "Processor: %04d: Index %04d, SEMAP: %s\r\n",
553 (UINT32
) ProcessorNumber
,
554 (UINT32
) FeatureIndex
,
555 mDependTypeStr
[MIN ((UINT32
)RegisterTableEntry
->Value
, InvalidDepType
)]
566 Get the biggest dependence type.
567 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
569 @param[in] BeforeDep Before dependence type.
570 @param[in] AfterDep After dependence type.
571 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.
572 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.
574 @retval Return the biggest dependence type.
576 CPU_FEATURE_DEPENDENCE_TYPE
578 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
,
579 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep
,
580 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
,
581 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
584 CPU_FEATURE_DEPENDENCE_TYPE Bigger
;
586 Bigger
= MAX (BeforeDep
, AfterDep
);
587 Bigger
= MAX (Bigger
, NoneNeibBeforeDep
);
588 return MAX(Bigger
, NoneNeibAfterDep
);
592 Analysis register CPU features on each processor and save CPU setting in CPU register table.
594 @param[in] NumberOfCpus Number of processor in system
598 AnalysisProcessorFeatures (
599 IN UINTN NumberOfCpus
603 UINTN ProcessorNumber
;
604 CPU_FEATURES_ENTRY
*CpuFeature
;
605 CPU_FEATURES_ENTRY
*CpuFeatureInOrder
;
606 CPU_FEATURES_INIT_ORDER
*CpuInitOrder
;
607 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
609 CPU_FEATURES_DATA
*CpuFeaturesData
;
610 LIST_ENTRY
*NextEntry
;
611 CPU_FEATURES_ENTRY
*NextCpuFeatureInOrder
;
613 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep
;
614 CPU_FEATURE_DEPENDENCE_TYPE AfterDep
;
615 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep
;
616 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep
;
618 CpuFeaturesData
= GetCpuFeaturesData ();
619 CpuFeaturesData
->CapabilityPcd
= AllocatePool (CpuFeaturesData
->BitMaskSize
);
620 ASSERT (CpuFeaturesData
->CapabilityPcd
!= NULL
);
621 SetMem (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
, 0xFF);
622 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
623 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
625 // Calculate the last capability on all processors
627 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcd
, CpuInitOrder
->FeaturesSupportedMask
, CpuFeaturesData
->BitMaskSize
);
630 // Calculate the last setting
632 CpuFeaturesData
->SettingPcd
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcd
);
633 ASSERT (CpuFeaturesData
->SettingPcd
!= NULL
);
634 SupportedMaskAnd (CpuFeaturesData
->SettingPcd
, PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
637 // Dump the last CPU feature list
640 DEBUG ((DEBUG_INFO
, "Last CPU features list...\n"));
641 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
642 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
643 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
644 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
645 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
646 DEBUG ((DEBUG_INFO
, "[Enable ] "));
648 DEBUG ((DEBUG_INFO
, "[Disable ] "));
651 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
653 DumpCpuFeature (CpuFeature
, CpuFeaturesData
->BitMaskSize
);
654 Entry
= Entry
->ForwardLink
;
656 DEBUG ((DEBUG_INFO
, "PcdCpuFeaturesCapability:\n"));
657 DumpCpuFeatureMask (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
658 DEBUG ((DEBUG_INFO
, "Origin PcdCpuFeaturesSetting:\n"));
659 DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting
), CpuFeaturesData
->BitMaskSize
);
660 DEBUG ((DEBUG_INFO
, "Final PcdCpuFeaturesSetting:\n"));
661 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
665 // Save PCDs and display CPU PCDs
667 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
);
668 SetSettingPcd (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
670 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
671 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
672 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
673 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
675 // Insert each feature into processor's order list
677 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
678 if (IsBitMaskMatch (CpuFeature
->FeatureMask
, CpuFeaturesData
->CapabilityPcd
, CpuFeaturesData
->BitMaskSize
)) {
679 CpuFeatureInOrder
= AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY
), CpuFeature
);
680 ASSERT (CpuFeatureInOrder
!= NULL
);
681 InsertTailList (&CpuInitOrder
->OrderList
, &CpuFeatureInOrder
->Link
);
683 Entry
= Entry
->ForwardLink
;
686 // Go through ordered feature list to initialize CPU features
688 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
689 Entry
= GetFirstNode (&CpuInitOrder
->OrderList
);
690 while (!IsNull (&CpuInitOrder
->OrderList
, Entry
)) {
691 CpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
694 if (IsBitMaskMatch (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
)) {
695 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, TRUE
);
696 if (EFI_ERROR (Status
)) {
698 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.
700 SupportedMaskCleanBit (CpuFeaturesData
->SettingPcd
, CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
701 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
702 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
704 DEBUG ((DEBUG_WARN
, "Warning :: Failed to enable Feature: Mask = "));
705 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
711 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
712 if (EFI_ERROR (Status
)) {
713 if (CpuFeatureInOrder
->FeatureName
!= NULL
) {
714 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder
->FeatureName
));
716 DEBUG ((DEBUG_WARN
, "Warning :: Failed to disable Feature: Mask = "));
717 DumpCpuFeatureMask (CpuFeatureInOrder
->FeatureMask
, CpuFeaturesData
->BitMaskSize
);
725 NextEntry
= Entry
->ForwardLink
;
726 if (!IsNull (&CpuInitOrder
->OrderList
, NextEntry
)) {
727 NextCpuFeatureInOrder
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
730 // If feature has dependence with the next feature (ONLY care core/package dependency).
731 // and feature initialize succeed, add sync semaphere here.
733 BeforeDep
= DetectFeatureScope (CpuFeatureInOrder
, TRUE
, NextCpuFeatureInOrder
->FeatureMask
);
734 AfterDep
= DetectFeatureScope (NextCpuFeatureInOrder
, FALSE
, CpuFeatureInOrder
->FeatureMask
);
736 // Check whether next feature has After type dependence with not neighborhood CPU
737 // Features in former CPU features.
739 NoneNeibAfterDep
= DetectNoneNeighborhoodFeatureScope(NextCpuFeatureInOrder
, FALSE
, &CpuInitOrder
->OrderList
);
741 BeforeDep
= NoneDepType
;
742 AfterDep
= NoneDepType
;
743 NoneNeibAfterDep
= NoneDepType
;
746 // Check whether current feature has Before type dependence with none neighborhood
747 // CPU features in after Cpu features.
749 NoneNeibBeforeDep
= DetectNoneNeighborhoodFeatureScope(CpuFeatureInOrder
, TRUE
, &CpuInitOrder
->OrderList
);
752 // Get the biggest dependence and add semaphore for it.
753 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.
755 BeforeDep
= BiggestDep(BeforeDep
, AfterDep
, NoneNeibBeforeDep
, NoneNeibAfterDep
);
756 if (BeforeDep
> ThreadDepType
) {
757 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber
, Semaphore
, 0, BeforeDep
);
761 Entry
= Entry
->ForwardLink
;
765 // Dump PcdCpuFeaturesSetting again because this value maybe updated
766 // again during initialize the features.
768 DEBUG ((DEBUG_INFO
, "Dump final value for PcdCpuFeaturesSetting:\n"));
769 DumpCpuFeatureMask (CpuFeaturesData
->SettingPcd
, CpuFeaturesData
->BitMaskSize
);
772 // Dump the RegisterTable
774 DumpRegisterTableOnProcessor (ProcessorNumber
);
779 Increment semaphore by 1.
781 @param Sem IN: 32-bit unsigned integer
785 LibReleaseSemaphore (
786 IN OUT
volatile UINT32
*Sem
789 InterlockedIncrement (Sem
);
793 Decrement the semaphore by 1 if it is not zero.
795 Performs an atomic decrement operation for semaphore.
796 The compare exchange operation must be performed using
799 @param Sem IN: 32-bit unsigned integer
803 LibWaitForSemaphore (
804 IN OUT
volatile UINT32
*Sem
811 } while (Value
== 0 ||
812 InterlockedCompareExchange32 (
820 Read / write CR value.
822 @param[in] CrIndex The CR index which need to read/write.
823 @param[in] Read Read or write. TRUE is read.
824 @param[in,out] CrValue CR value.
826 @retval EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.
832 IN OUT UINTN
*CrValue
838 *CrValue
= AsmReadCr0 ();
840 AsmWriteCr0 (*CrValue
);
845 *CrValue
= AsmReadCr2 ();
847 AsmWriteCr2 (*CrValue
);
852 *CrValue
= AsmReadCr3 ();
854 AsmWriteCr3 (*CrValue
);
859 *CrValue
= AsmReadCr4 ();
861 AsmWriteCr4 (*CrValue
);
865 return EFI_UNSUPPORTED
;;
872 Initialize the CPU registers from a register table.
874 @param[in] RegisterTable The register table for this AP.
875 @param[in] ApLocation AP location info for this ap.
876 @param[in] CpuStatus CPU status info for this CPU.
877 @param[in] CpuFlags Flags data structure used when program the register.
879 @note This service could be called by BSP/APs.
882 ProgramProcessorRegister (
883 IN CPU_REGISTER_TABLE
*RegisterTable
,
884 IN EFI_CPU_PHYSICAL_LOCATION
*ApLocation
,
885 IN CPU_STATUS_INFORMATION
*CpuStatus
,
886 IN PROGRAM_CPU_REGISTER_FLAGS
*CpuFlags
889 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
892 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
893 volatile UINT32
*SemaphorePtr
;
895 UINT32 CurrentThread
;
897 UINTN ProcessorIndex
;
898 UINT32
*ThreadCountPerPackage
;
899 UINT8
*ThreadCountPerCore
;
904 // Traverse Register Table of this logical processor
906 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
908 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
910 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
913 // Check the type of specified register
915 switch (RegisterTableEntry
->RegisterType
) {
917 // The specified register is Control Register
919 case ControlRegister
:
920 Status
= ReadWriteCr (RegisterTableEntry
->Index
, TRUE
, &Value
);
921 if (EFI_ERROR (Status
)) {
924 if (RegisterTableEntry
->TestThenWrite
) {
925 CurrentValue
= BitFieldRead64 (
927 RegisterTableEntry
->ValidBitStart
,
928 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
930 if (CurrentValue
== RegisterTableEntry
->Value
) {
934 Value
= (UINTN
) BitFieldWrite64 (
936 RegisterTableEntry
->ValidBitStart
,
937 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
938 RegisterTableEntry
->Value
940 ReadWriteCr (RegisterTableEntry
->Index
, FALSE
, &Value
);
944 // The specified register is Model Specific Register
947 if (RegisterTableEntry
->TestThenWrite
) {
948 Value
= (UINTN
)AsmReadMsr64 (RegisterTableEntry
->Index
);
949 if (RegisterTableEntry
->ValidBitLength
>= 64) {
950 if (Value
== RegisterTableEntry
->Value
) {
954 CurrentValue
= BitFieldRead64 (
956 RegisterTableEntry
->ValidBitStart
,
957 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1
959 if (CurrentValue
== RegisterTableEntry
->Value
) {
965 if (RegisterTableEntry
->ValidBitLength
>= 64) {
967 // If length is not less than 64 bits, then directly write without reading
970 RegisterTableEntry
->Index
,
971 RegisterTableEntry
->Value
975 // Set the bit section according to bit start and length
977 AsmMsrBitFieldWrite64 (
978 RegisterTableEntry
->Index
,
979 RegisterTableEntry
->ValidBitStart
,
980 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
981 RegisterTableEntry
->Value
986 // MemoryMapped operations
989 AcquireSpinLock (&CpuFlags
->MemoryMappedLock
);
990 MmioBitFieldWrite32 (
991 (UINTN
)(RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32)),
992 RegisterTableEntry
->ValidBitStart
,
993 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
994 (UINT32
)RegisterTableEntry
->Value
996 ReleaseSpinLock (&CpuFlags
->MemoryMappedLock
);
999 // Enable or disable cache
1003 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
1005 if (RegisterTableEntry
->Value
== 0) {
1013 // Semaphore works logic like below:
1015 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
1016 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
1018 // All threads (T0...Tn) waits in P() line and continues running
1024 // V(0...n) V(0...n) ... V(0...n)
1025 // n * P(0) n * P(1) ... n * P(n)
1027 switch (RegisterTableEntry
->Value
) {
1029 SemaphorePtr
= CpuFlags
->CoreSemaphoreCount
;
1030 ThreadCountPerCore
= (UINT8
*)(UINTN
)CpuStatus
->ThreadCountPerCore
;
1032 CurrentCore
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
+ ApLocation
->Core
;
1034 // Get Offset info for the first thread in the core which current thread belongs to.
1036 FirstThread
= CurrentCore
* CpuStatus
->MaxThreadCount
;
1037 CurrentThread
= FirstThread
+ ApLocation
->Thread
;
1040 // Different cores may have different valid threads in them. If driver maintail clearly
1041 // thread index in different cores, the logic will be much complicated.
1042 // Here driver just simply records the max thread number in all cores and use it as expect
1043 // thread number for all cores.
1044 // In below two steps logic, first current thread will Release semaphore for each thread
1045 // in current core. Maybe some threads are not valid in this core, but driver don't
1046 // care. Second, driver will let current thread wait semaphore for all valid threads in
1047 // current core. Because only the valid threads will do release semaphore for this
1048 // thread, driver here only need to wait the valid thread count.
1052 // First Notify ALL THREADs in current Core that this thread is ready.
1054 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
; ProcessorIndex
++) {
1055 LibReleaseSemaphore (&SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1058 // Second, check whether all VALID THREADs (not all threads) in current core are ready.
1060 for (ProcessorIndex
= 0; ProcessorIndex
< ThreadCountPerCore
[CurrentCore
]; ProcessorIndex
++) {
1061 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1065 case PackageDepType
:
1066 SemaphorePtr
= CpuFlags
->PackageSemaphoreCount
;
1067 ThreadCountPerPackage
= (UINT32
*)(UINTN
)CpuStatus
->ThreadCountPerPackage
;
1069 // Get Offset info for the first thread in the package which current thread belongs to.
1071 FirstThread
= ApLocation
->Package
* CpuStatus
->MaxCoreCount
* CpuStatus
->MaxThreadCount
;
1073 // Get the possible threads count for current package.
1075 CurrentThread
= FirstThread
+ CpuStatus
->MaxThreadCount
* ApLocation
->Core
+ ApLocation
->Thread
;
1078 // Different packages may have different valid threads in them. If driver maintail clearly
1079 // thread index in different packages, the logic will be much complicated.
1080 // Here driver just simply records the max thread number in all packages and use it as expect
1081 // thread number for all packages.
1082 // In below two steps logic, first current thread will Release semaphore for each thread
1083 // in current package. Maybe some threads are not valid in this package, but driver don't
1084 // care. Second, driver will let current thread wait semaphore for all valid threads in
1085 // current package. Because only the valid threads will do release semaphore for this
1086 // thread, driver here only need to wait the valid thread count.
1090 // First Notify ALL THREADS in current package that this thread is ready.
1092 for (ProcessorIndex
= 0; ProcessorIndex
< CpuStatus
->MaxThreadCount
* CpuStatus
->MaxCoreCount
; ProcessorIndex
++) {
1093 LibReleaseSemaphore (&SemaphorePtr
[FirstThread
+ ProcessorIndex
]);
1096 // Second, check whether VALID THREADS (not all threads) in current package are ready.
1098 for (ProcessorIndex
= 0; ProcessorIndex
< ThreadCountPerPackage
[ApLocation
->Package
]; ProcessorIndex
++) {
1099 LibWaitForSemaphore (&SemaphorePtr
[CurrentThread
]);
1115 Programs registers for the calling processor.
1117 @param[in,out] Buffer The pointer to private data buffer.
1122 SetProcessorRegister (
1126 CPU_FEATURES_DATA
*CpuFeaturesData
;
1127 CPU_REGISTER_TABLE
*RegisterTable
;
1128 CPU_REGISTER_TABLE
*RegisterTables
;
1132 ACPI_CPU_DATA
*AcpiCpuData
;
1134 CpuFeaturesData
= (CPU_FEATURES_DATA
*) Buffer
;
1135 AcpiCpuData
= CpuFeaturesData
->AcpiCpuData
;
1137 RegisterTables
= (CPU_REGISTER_TABLE
*)(UINTN
)AcpiCpuData
->CpuFeatureInitData
.RegisterTable
;
1139 InitApicId
= GetInitialApicId ();
1140 RegisterTable
= NULL
;
1141 ProcIndex
= (UINTN
)-1;
1142 for (Index
= 0; Index
< AcpiCpuData
->NumberOfCpus
; Index
++) {
1143 if (RegisterTables
[Index
].InitialApicId
== InitApicId
) {
1144 RegisterTable
= &RegisterTables
[Index
];
1149 ASSERT (RegisterTable
!= NULL
);
1151 ProgramProcessorRegister (
1153 (EFI_CPU_PHYSICAL_LOCATION
*)(UINTN
)AcpiCpuData
->CpuFeatureInitData
.ApLocation
+ ProcIndex
,
1154 &AcpiCpuData
->CpuFeatureInitData
.CpuStatus
,
1155 &CpuFeaturesData
->CpuFlags
1160 Performs CPU features detection.
1162 This service will invoke MP service to check CPU features'
1163 capabilities on BSP/APs.
1165 @note This service could be called by BSP only.
1173 CPU_FEATURES_DATA
*CpuFeaturesData
;
1175 CpuFeaturesData
= GetCpuFeaturesData();
1177 CpuInitDataInitialize ();
1179 if (CpuFeaturesData
->NumberOfCpus
> 1) {
1181 // Wakeup all APs for data collection.
1183 StartupAllAPsWorker (CollectProcessorData
, NULL
);
1187 // Collect data on BSP
1189 CollectProcessorData (CpuFeaturesData
);
1191 AnalysisProcessorFeatures (CpuFeaturesData
->NumberOfCpus
);