2 CPU Register Table Library functions.
4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "RegisterCpuFeatures.h"
18 Checks if two CPU feature bit masks are equal.
20 @param[in] FirstFeatureMask The first input CPU feature bit mask
21 @param[in] SecondFeatureMask The second input CPU feature bit mask
23 @retval TRUE Two CPU feature bit masks are equal.
24 @retval FALSE Two CPU feature bit masks are not equal.
28 IN UINT8
*FirstFeatureMask
,
29 IN UINT8
*SecondFeatureMask
34 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
35 if (CompareMem (FirstFeatureMask
, SecondFeatureMask
, BitMaskSize
) == 0) {
43 Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
45 @param[in] FeatureMask A pointer to the CPU feature bit mask.
56 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
57 Data8
= (UINT8
*) FeatureMask
;
58 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
59 DEBUG ((DEBUG_INFO
, " %02x ", *Data8
++));
61 DEBUG ((DEBUG_INFO
, "\n"));
65 Dump CPU feature name or CPU feature bit mask.
67 @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY
71 IN CPU_FEATURES_ENTRY
*CpuFeature
75 if (CpuFeature
->FeatureName
!= NULL
) {
76 DEBUG ((DEBUG_INFO
, "FeatureName: %a\n", CpuFeature
->FeatureName
));
78 DEBUG ((DEBUG_INFO
, "FeatureMask = "));
79 DumpCpuFeatureMask (CpuFeature
->FeatureMask
);
84 Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
86 @param[in] FeatureMask Pointer to CPU feature bit mask
87 @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer
89 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
90 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
94 IN UINT8
*FeatureMask
,
95 IN UINT8
*DependentBitMask
103 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
106 Data2
= DependentBitMask
;
107 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
108 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
116 Try to find the specify cpu featuren in former/after feature list.
118 @param[in] FeatureList Pointer to dependent CPU feature list
119 @param[in] CurrentEntry Pointer to current CPU feature entry.
120 @param[in] SearchFormer Find in former feature or after features.
121 @param[in] FeatureMask Pointer to CPU feature bit mask
123 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
124 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
128 IN LIST_ENTRY
*FeatureList
,
129 IN LIST_ENTRY
*CurrentEntry
,
130 IN BOOLEAN SearchFormer
,
131 IN UINT8
*FeatureMask
134 CPU_FEATURES_ENTRY
*CpuFeature
;
135 LIST_ENTRY
*NextEntry
;
138 // Check whether exist the not neighborhood entry first.
139 // If not exist, return FALSE means not found status.
142 NextEntry
= CurrentEntry
->BackLink
;
143 if (IsNull (FeatureList
, NextEntry
)) {
147 NextEntry
= NextEntry
->BackLink
;
148 if (IsNull (FeatureList
, NextEntry
)) {
152 NextEntry
= CurrentEntry
->BackLink
->BackLink
;
154 NextEntry
= CurrentEntry
->ForwardLink
;
155 if (IsNull (FeatureList
, NextEntry
)) {
159 NextEntry
= NextEntry
->ForwardLink
;
160 if (IsNull (FeatureList
, NextEntry
)) {
164 NextEntry
= CurrentEntry
->ForwardLink
->ForwardLink
;
167 while (!IsNull (FeatureList
, NextEntry
)) {
168 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
170 if (IsBitMaskMatchCheck (FeatureMask
, CpuFeature
->FeatureMask
)) {
175 NextEntry
= NextEntry
->BackLink
;
177 NextEntry
= NextEntry
->ForwardLink
;
185 Return feature dependence result.
187 @param[in] CpuFeature Pointer to CPU feature.
188 @param[in] Before Check before dependence or after.
189 @param[in] NextCpuFeatureMask Pointer to next CPU feature Mask.
191 @retval return the dependence result.
193 CPU_FEATURE_DEPENDENCE_TYPE
195 IN CPU_FEATURES_ENTRY
*CpuFeature
,
197 IN UINT8
*NextCpuFeatureMask
201 // if need to check before type dependence but the feature after current feature is not
202 // exist, means this before type dependence not valid, just return NoneDepType.
203 // Just like Feature A has a dependence of feature B, but Feature B not installed, so
204 // Feature A maybe insert to the last entry of the list. In this case, for below code,
205 // Featrure A has depend of feature B, but it is the last entry of the list, so the
206 // NextCpuFeatureMask is NULL, so the dependence for feature A here is useless and code
207 // just return NoneDepType.
209 if (NextCpuFeatureMask
== NULL
) {
214 if ((CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) &&
215 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->PackageBeforeFeatureBitMask
)) {
216 return PackageDepType
;
219 if ((CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) &&
220 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->CoreBeforeFeatureBitMask
)) {
224 if ((CpuFeature
->BeforeFeatureBitMask
!= NULL
) &&
225 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->BeforeFeatureBitMask
)) {
226 return ThreadDepType
;
232 if ((CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) &&
233 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->PackageAfterFeatureBitMask
)) {
234 return PackageDepType
;
237 if ((CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) &&
238 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->CoreAfterFeatureBitMask
)) {
242 if ((CpuFeature
->AfterFeatureBitMask
!= NULL
) &&
243 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->AfterFeatureBitMask
)) {
244 return ThreadDepType
;
251 Return feature dependence result.
253 @param[in] CpuFeature Pointer to CPU feature.
254 @param[in] Before Check before dependence or after.
255 @param[in] FeatureList Pointer to CPU feature list.
257 @retval return the dependence result.
259 CPU_FEATURE_DEPENDENCE_TYPE
260 DetectNoneNeighborhoodFeatureScope (
261 IN CPU_FEATURES_ENTRY
*CpuFeature
,
263 IN LIST_ENTRY
*FeatureList
267 if ((CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) &&
268 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, FALSE
, CpuFeature
->PackageBeforeFeatureBitMask
)) {
269 return PackageDepType
;
272 if ((CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) &&
273 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, FALSE
, CpuFeature
->CoreBeforeFeatureBitMask
)) {
277 if ((CpuFeature
->BeforeFeatureBitMask
!= NULL
) &&
278 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, FALSE
, CpuFeature
->BeforeFeatureBitMask
)) {
279 return ThreadDepType
;
285 if ((CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) &&
286 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, TRUE
, CpuFeature
->PackageAfterFeatureBitMask
)) {
287 return PackageDepType
;
290 if ((CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) &&
291 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, TRUE
, CpuFeature
->CoreAfterFeatureBitMask
)) {
295 if ((CpuFeature
->AfterFeatureBitMask
!= NULL
) &&
296 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, TRUE
, CpuFeature
->AfterFeatureBitMask
)) {
297 return ThreadDepType
;
304 Base on dependence relationship to asjust feature dependence.
306 ONLY when the feature before(or after) the find feature also has
307 dependence with the find feature. In this case, driver need to base
308 on dependce relationship to decide how to insert current feature and
309 adjust the feature dependence.
311 @param[in, out] PreviousFeature CPU feature current before the find one.
312 @param[in, out] CurrentFeature Cpu feature need to adjust.
313 @param[in] FindFeature Cpu feature which current feature depends.
314 @param[in] Before Before or after dependence relationship.
316 @retval TRUE means the current feature dependence has been adjusted.
318 @retval FALSE means the previous feature dependence has been adjusted.
319 or previous feature has no dependence with the find one.
323 AdjustFeaturesDependence (
324 IN OUT CPU_FEATURES_ENTRY
*PreviousFeature
,
325 IN OUT CPU_FEATURES_ENTRY
*CurrentFeature
,
326 IN CPU_FEATURES_ENTRY
*FindFeature
,
330 CPU_FEATURE_DEPENDENCE_TYPE PreDependType
;
331 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType
;
333 PreDependType
= DetectFeatureScope(PreviousFeature
, Before
, FindFeature
->FeatureMask
);
334 CurrentDependType
= DetectFeatureScope(CurrentFeature
, Before
, FindFeature
->FeatureMask
);
337 // If previous feature has no dependence with the find featue.
340 if (PreDependType
== NoneDepType
) {
345 // If both feature have dependence, keep the one which needs use more
346 // processors and clear the dependence for the other one.
348 if (PreDependType
>= CurrentDependType
) {
356 Base on dependence relationship to asjust feature order.
358 @param[in] FeatureList Pointer to CPU feature list
359 @param[in, out] FindEntry The entry this feature depend on.
360 @param[in, out] CurrentEntry The entry for this feature.
361 @param[in] Before Before or after dependence relationship.
366 IN LIST_ENTRY
*FeatureList
,
367 IN OUT LIST_ENTRY
*FindEntry
,
368 IN OUT LIST_ENTRY
*CurrentEntry
,
372 LIST_ENTRY
*PreviousEntry
;
373 CPU_FEATURES_ENTRY
*PreviousFeature
;
374 CPU_FEATURES_ENTRY
*CurrentFeature
;
375 CPU_FEATURES_ENTRY
*FindFeature
;
378 // For CPU feature which has core or package type dependence, later code need to insert
379 // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.
380 // So if driver finds both feature A and B need to execute before feature C, driver will
381 // base on dependence type of feature A and B to update the logic here.
382 // For example, feature A has package type dependence and feature B has core type dependence,
383 // because package type dependence need to wait for more processors which has strong dependence
384 // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver
385 // will remove the feature dependence in feature B.
386 // Driver just needs to make sure before feature C been executed, feature A has finished its task
387 // in all all thread. Feature A finished in all threads also means feature B have finshed in all
391 PreviousEntry
= GetPreviousNode (FeatureList
, FindEntry
);
393 PreviousEntry
= GetNextNode (FeatureList
, FindEntry
);
396 CurrentFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
397 RemoveEntryList (CurrentEntry
);
399 if (IsNull (FeatureList
, PreviousEntry
)) {
401 // If not exist the previous or next entry, just insert the current entry.
404 InsertTailList (FindEntry
, CurrentEntry
);
406 InsertHeadList (FindEntry
, CurrentEntry
);
410 // If exist the previous or next entry, need to check it before insert curent entry.
412 PreviousFeature
= CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry
);
413 FindFeature
= CPU_FEATURE_ENTRY_FROM_LINK (FindEntry
);
415 if (AdjustFeaturesDependence (PreviousFeature
, CurrentFeature
, FindFeature
, Before
)) {
417 // Return TRUE means current feature dependence has been cleared and the previous
418 // feature dependence has been kept and used. So insert current feature before (or after)
419 // the previous feature.
422 InsertTailList (PreviousEntry
, CurrentEntry
);
424 InsertHeadList (PreviousEntry
, CurrentEntry
);
428 InsertTailList (FindEntry
, CurrentEntry
);
430 InsertHeadList (FindEntry
, CurrentEntry
);
437 Checks and adjusts current CPU features per dependency relationship.
439 @param[in] FeatureList Pointer to CPU feature list
440 @param[in] CurrentEntry Pointer to current checked CPU feature
441 @param[in] FeatureMask The feature bit mask.
443 @retval return Swapped info.
446 InsertToBeforeEntry (
447 IN LIST_ENTRY
*FeatureList
,
448 IN LIST_ENTRY
*CurrentEntry
,
449 IN UINT8
*FeatureMask
452 LIST_ENTRY
*CheckEntry
;
453 CPU_FEATURES_ENTRY
*CheckFeature
;
459 // Check all features dispatched before this entry
461 CheckEntry
= GetFirstNode (FeatureList
);
462 while (CheckEntry
!= CurrentEntry
) {
463 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
464 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
465 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, TRUE
);
469 CheckEntry
= CheckEntry
->ForwardLink
;
476 Checks and adjusts current CPU features per dependency relationship.
478 @param[in] FeatureList Pointer to CPU feature list
479 @param[in] CurrentEntry Pointer to current checked CPU feature
480 @param[in] FeatureMask The feature bit mask.
482 @retval return Swapped info.
486 IN LIST_ENTRY
*FeatureList
,
487 IN LIST_ENTRY
*CurrentEntry
,
488 IN UINT8
*FeatureMask
491 LIST_ENTRY
*CheckEntry
;
492 CPU_FEATURES_ENTRY
*CheckFeature
;
498 // Check all features dispatched after this entry
500 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
501 while (!IsNull (FeatureList
, CheckEntry
)) {
502 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
503 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
504 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, FALSE
);
508 CheckEntry
= CheckEntry
->ForwardLink
;
515 Checks and adjusts CPU features order per dependency relationship.
517 @param[in] FeatureList Pointer to CPU feature list
520 CheckCpuFeaturesDependency (
521 IN LIST_ENTRY
*FeatureList
524 LIST_ENTRY
*CurrentEntry
;
525 CPU_FEATURES_ENTRY
*CpuFeature
;
526 LIST_ENTRY
*CheckEntry
;
527 CPU_FEATURES_ENTRY
*CheckFeature
;
529 LIST_ENTRY
*TempEntry
;
530 LIST_ENTRY
*NextEntry
;
532 CurrentEntry
= GetFirstNode (FeatureList
);
533 while (!IsNull (FeatureList
, CurrentEntry
)) {
535 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
536 NextEntry
= CurrentEntry
->ForwardLink
;
537 if (CpuFeature
->BeforeAll
) {
539 // Check all features dispatched before this entry
541 CheckEntry
= GetFirstNode (FeatureList
);
542 while (CheckEntry
!= CurrentEntry
) {
543 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
544 if (!CheckFeature
->BeforeAll
) {
546 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
547 // insert currentEntry before Checked feature
549 RemoveEntryList (CurrentEntry
);
550 InsertTailList (CheckEntry
, CurrentEntry
);
554 CheckEntry
= CheckEntry
->ForwardLink
;
557 CurrentEntry
= NextEntry
;
562 if (CpuFeature
->AfterAll
) {
564 // Check all features dispatched after this entry
566 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
567 while (!IsNull (FeatureList
, CheckEntry
)) {
568 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
569 if (!CheckFeature
->AfterAll
) {
571 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
572 // insert currentEntry after Checked feature
574 TempEntry
= GetNextNode (FeatureList
, CurrentEntry
);
575 RemoveEntryList (CurrentEntry
);
576 InsertHeadList (CheckEntry
, CurrentEntry
);
577 CurrentEntry
= TempEntry
;
581 CheckEntry
= CheckEntry
->ForwardLink
;
584 CurrentEntry
= NextEntry
;
589 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
590 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->BeforeFeatureBitMask
);
596 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
597 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->AfterFeatureBitMask
);
603 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
604 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreBeforeFeatureBitMask
);
610 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
611 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreAfterFeatureBitMask
);
617 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
618 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageBeforeFeatureBitMask
);
624 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
625 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageAfterFeatureBitMask
);
631 CurrentEntry
= CurrentEntry
->ForwardLink
;
636 Worker function to register CPU Feature.
638 @param[in] CpuFeature Pointer to CPU feature entry
640 @retval RETURN_SUCCESS The CPU feature was successfully registered.
641 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
643 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
644 supported due to a circular dependency between
645 BEFORE and AFTER features.
648 RegisterCpuFeatureWorker (
649 IN CPU_FEATURES_ENTRY
*CpuFeature
653 CPU_FEATURES_DATA
*CpuFeaturesData
;
654 CPU_FEATURES_ENTRY
*CpuFeatureEntry
;
657 BOOLEAN FeatureExist
;
659 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
660 CpuFeaturesData
= GetCpuFeaturesData ();
661 if (CpuFeaturesData
->FeaturesCount
== 0) {
662 InitializeListHead (&CpuFeaturesData
->FeatureList
);
663 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.MemoryMappedLock
);
664 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.ConsoleLogLock
);
665 CpuFeaturesData
->BitMaskSize
= (UINT32
) BitMaskSize
;
667 ASSERT (CpuFeaturesData
->BitMaskSize
== BitMaskSize
);
669 FeatureExist
= FALSE
;
670 CpuFeatureEntry
= NULL
;
671 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
672 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
673 CpuFeatureEntry
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
674 if (IsCpuFeatureMatch (CpuFeature
->FeatureMask
, CpuFeatureEntry
->FeatureMask
)) {
676 // If this feature already registered
681 Entry
= Entry
->ForwardLink
;
685 DEBUG ((DEBUG_INFO
, "[NEW] "));
686 DumpCpuFeature (CpuFeature
);
687 InsertTailList (&CpuFeaturesData
->FeatureList
, &CpuFeature
->Link
);
688 CpuFeaturesData
->FeaturesCount
++;
690 DEBUG ((DEBUG_INFO
, "[OVERRIDE] "));
691 DumpCpuFeature (CpuFeature
);
692 ASSERT (CpuFeatureEntry
!= NULL
);
694 // Overwrite original parameters of CPU feature
696 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
697 CpuFeatureEntry
->GetConfigDataFunc
= CpuFeature
->GetConfigDataFunc
;
699 if (CpuFeature
->SupportFunc
!= NULL
) {
700 CpuFeatureEntry
->SupportFunc
= CpuFeature
->SupportFunc
;
702 if (CpuFeature
->InitializeFunc
!= NULL
) {
703 CpuFeatureEntry
->InitializeFunc
= CpuFeature
->InitializeFunc
;
705 if (CpuFeature
->FeatureName
!= NULL
) {
706 if (CpuFeatureEntry
->FeatureName
== NULL
) {
707 CpuFeatureEntry
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
708 ASSERT (CpuFeatureEntry
->FeatureName
!= NULL
);
710 Status
= AsciiStrCpyS (CpuFeatureEntry
->FeatureName
, CPU_FEATURE_NAME_SIZE
, CpuFeature
->FeatureName
);
711 ASSERT_EFI_ERROR (Status
);
712 FreePool (CpuFeature
->FeatureName
);
714 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
715 if (CpuFeatureEntry
->BeforeFeatureBitMask
!= NULL
) {
716 FreePool (CpuFeatureEntry
->BeforeFeatureBitMask
);
718 CpuFeatureEntry
->BeforeFeatureBitMask
= CpuFeature
->BeforeFeatureBitMask
;
720 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
721 if (CpuFeatureEntry
->AfterFeatureBitMask
!= NULL
) {
722 FreePool (CpuFeatureEntry
->AfterFeatureBitMask
);
724 CpuFeatureEntry
->AfterFeatureBitMask
= CpuFeature
->AfterFeatureBitMask
;
726 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
727 if (CpuFeatureEntry
->CoreBeforeFeatureBitMask
!= NULL
) {
728 FreePool (CpuFeatureEntry
->CoreBeforeFeatureBitMask
);
730 CpuFeatureEntry
->CoreBeforeFeatureBitMask
= CpuFeature
->CoreBeforeFeatureBitMask
;
732 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
733 if (CpuFeatureEntry
->CoreAfterFeatureBitMask
!= NULL
) {
734 FreePool (CpuFeatureEntry
->CoreAfterFeatureBitMask
);
736 CpuFeatureEntry
->CoreAfterFeatureBitMask
= CpuFeature
->CoreAfterFeatureBitMask
;
738 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
739 if (CpuFeatureEntry
->PackageBeforeFeatureBitMask
!= NULL
) {
740 FreePool (CpuFeatureEntry
->PackageBeforeFeatureBitMask
);
742 CpuFeatureEntry
->PackageBeforeFeatureBitMask
= CpuFeature
->PackageBeforeFeatureBitMask
;
744 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
745 if (CpuFeatureEntry
->PackageAfterFeatureBitMask
!= NULL
) {
746 FreePool (CpuFeatureEntry
->PackageAfterFeatureBitMask
);
748 CpuFeatureEntry
->PackageAfterFeatureBitMask
= CpuFeature
->PackageAfterFeatureBitMask
;
751 CpuFeatureEntry
->BeforeAll
= CpuFeature
->BeforeAll
;
752 CpuFeatureEntry
->AfterAll
= CpuFeature
->AfterAll
;
754 FreePool (CpuFeature
->FeatureMask
);
755 FreePool (CpuFeature
);
758 // Verify CPU features dependency can change CPU feature order
760 CheckCpuFeaturesDependency (&CpuFeaturesData
->FeatureList
);
761 return RETURN_SUCCESS
;
765 Sets CPU feature bit mask in CPU feature bit mask buffer.
767 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
768 @param[in] Feature The bit number of the CPU feature
769 @param[in] BitMaskSize CPU feature bit mask buffer size
772 SetCpuFeaturesBitMask (
773 IN UINT8
**FeaturesBitMask
,
778 UINT8
*CpuFeaturesBitMask
;
780 ASSERT (FeaturesBitMask
!= NULL
);
781 CpuFeaturesBitMask
= *FeaturesBitMask
;
782 if (CpuFeaturesBitMask
== NULL
) {
783 CpuFeaturesBitMask
= AllocateZeroPool (BitMaskSize
);
784 ASSERT (CpuFeaturesBitMask
!= NULL
);
785 *FeaturesBitMask
= CpuFeaturesBitMask
;
788 CpuFeaturesBitMask
+= (Feature
/ 8);
789 *CpuFeaturesBitMask
|= (UINT8
) (1 << (Feature
% 8));
793 Registers a CPU Feature.
795 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
797 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
798 is an optional parameter that may be NULL. If NULL,
799 then the most recently registered function for the
800 CPU feature is used. If no functions are registered
801 for a CPU feature, then the CPU configuration data
802 for the registered feature is NULL.
803 @param[in] SupportFunc CPU feature support function. This is an optional
804 parameter that may be NULL. If NULL, then the most
805 recently registered function for the CPU feature is
806 used. If no functions are registered for a CPU
807 feature, then the CPU feature is assumed to be
808 supported by all CPUs.
809 @param[in] InitializeFunc CPU feature initialize function. This is an optional
810 parameter that may be NULL. If NULL, then the most
811 recently registered function for the CPU feature is
812 used. If no functions are registered for a CPU
813 feature, then the CPU feature initialization is
815 @param[in] ... Variable argument list of UINT32 CPU feature value.
816 Values with no modifiers are the features provided
817 by the registered functions.
818 Values with CPU_FEATURE_BEFORE modifier are features
819 that must be initialized after the features provided
820 by the registered functions are used.
821 Values with CPU_FEATURE_AFTER modifier are features
822 that must be initialized before the features provided
823 by the registered functions are used.
824 The last argument in this variable argument list must
825 always be CPU_FEATURE_END.
827 @retval RETURN_SUCCESS The CPU feature was successfully registered.
828 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
830 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
831 supported due to a circular dependency between
832 BEFORE and AFTER features.
833 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration
834 not updated by Platform driver yet.
836 @note This service could be called by BSP only.
841 IN CHAR8
*FeatureName
, OPTIONAL
842 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc
, OPTIONAL
843 IN CPU_FEATURE_SUPPORT SupportFunc
, OPTIONAL
844 IN CPU_FEATURE_INITIALIZE InitializeFunc
, OPTIONAL
852 CPU_FEATURES_ENTRY
*CpuFeature
;
854 UINT8
*BeforeFeatureBitMask
;
855 UINT8
*AfterFeatureBitMask
;
856 UINT8
*CoreBeforeFeatureBitMask
;
857 UINT8
*CoreAfterFeatureBitMask
;
858 UINT8
*PackageBeforeFeatureBitMask
;
859 UINT8
*PackageAfterFeatureBitMask
;
864 BeforeFeatureBitMask
= NULL
;
865 AfterFeatureBitMask
= NULL
;
866 CoreBeforeFeatureBitMask
= NULL
;
867 CoreAfterFeatureBitMask
= NULL
;
868 PackageBeforeFeatureBitMask
= NULL
;
869 PackageAfterFeatureBitMask
= NULL
;
873 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
875 VA_START (Marker
, InitializeFunc
);
876 Feature
= VA_ARG (Marker
, UINT32
);
877 while (Feature
!= CPU_FEATURE_END
) {
878 ASSERT ((Feature
& (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
))
879 != (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
));
880 ASSERT ((Feature
& (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
))
881 != (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
));
882 ASSERT ((Feature
& (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
))
883 != (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
));
884 ASSERT ((Feature
& (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
))
885 != (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
));
886 if (Feature
< CPU_FEATURE_BEFORE
) {
887 BeforeAll
= ((Feature
& CPU_FEATURE_BEFORE_ALL
) != 0) ? TRUE
: FALSE
;
888 AfterAll
= ((Feature
& CPU_FEATURE_AFTER_ALL
) != 0) ? TRUE
: FALSE
;
889 Feature
&= ~(CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
);
890 ASSERT (FeatureMask
== NULL
);
891 SetCpuFeaturesBitMask (&FeatureMask
, Feature
, BitMaskSize
);
892 } else if ((Feature
& CPU_FEATURE_BEFORE
) != 0) {
893 SetCpuFeaturesBitMask (&BeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_BEFORE
, BitMaskSize
);
894 } else if ((Feature
& CPU_FEATURE_AFTER
) != 0) {
895 SetCpuFeaturesBitMask (&AfterFeatureBitMask
, Feature
& ~CPU_FEATURE_AFTER
, BitMaskSize
);
896 } else if ((Feature
& CPU_FEATURE_CORE_BEFORE
) != 0) {
897 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_BEFORE
, BitMaskSize
);
898 } else if ((Feature
& CPU_FEATURE_CORE_AFTER
) != 0) {
899 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_AFTER
, BitMaskSize
);
900 } else if ((Feature
& CPU_FEATURE_PACKAGE_BEFORE
) != 0) {
901 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_BEFORE
, BitMaskSize
);
902 } else if ((Feature
& CPU_FEATURE_PACKAGE_AFTER
) != 0) {
903 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_AFTER
, BitMaskSize
);
905 Feature
= VA_ARG (Marker
, UINT32
);
909 CpuFeature
= AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY
));
910 ASSERT (CpuFeature
!= NULL
);
911 CpuFeature
->Signature
= CPU_FEATURE_ENTRY_SIGNATURE
;
912 CpuFeature
->FeatureMask
= FeatureMask
;
913 CpuFeature
->BeforeFeatureBitMask
= BeforeFeatureBitMask
;
914 CpuFeature
->AfterFeatureBitMask
= AfterFeatureBitMask
;
915 CpuFeature
->CoreBeforeFeatureBitMask
= CoreBeforeFeatureBitMask
;
916 CpuFeature
->CoreAfterFeatureBitMask
= CoreAfterFeatureBitMask
;
917 CpuFeature
->PackageBeforeFeatureBitMask
= PackageBeforeFeatureBitMask
;
918 CpuFeature
->PackageAfterFeatureBitMask
= PackageAfterFeatureBitMask
;
919 CpuFeature
->BeforeAll
= BeforeAll
;
920 CpuFeature
->AfterAll
= AfterAll
;
921 CpuFeature
->GetConfigDataFunc
= GetConfigDataFunc
;
922 CpuFeature
->SupportFunc
= SupportFunc
;
923 CpuFeature
->InitializeFunc
= InitializeFunc
;
924 if (FeatureName
!= NULL
) {
925 CpuFeature
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
926 ASSERT (CpuFeature
->FeatureName
!= NULL
);
927 Status
= AsciiStrCpyS (CpuFeature
->FeatureName
, CPU_FEATURE_NAME_SIZE
, FeatureName
);
928 ASSERT_EFI_ERROR (Status
);
931 Status
= RegisterCpuFeatureWorker (CpuFeature
);
932 ASSERT_EFI_ERROR (Status
);
934 return RETURN_SUCCESS
;
938 Return ACPI_CPU_DATA data.
940 @return Pointer to ACPI_CPU_DATA data.
949 UINTN NumberOfEnabledProcessors
;
950 ACPI_CPU_DATA
*AcpiCpuData
;
952 CPU_REGISTER_TABLE
*RegisterTable
;
954 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
956 AcpiCpuData
= (ACPI_CPU_DATA
*) (UINTN
) PcdGet64 (PcdCpuS3DataAddress
);
957 if (AcpiCpuData
!= NULL
) {
961 AcpiCpuData
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA
)));
962 ASSERT (AcpiCpuData
!= NULL
);
965 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
967 Status
= PcdSet64S (PcdCpuS3DataAddress
, (UINT64
)(UINTN
)AcpiCpuData
);
968 ASSERT_EFI_ERROR (Status
);
970 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
971 AcpiCpuData
->NumberOfCpus
= (UINT32
)NumberOfCpus
;
974 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
976 TableSize
= 2 * NumberOfCpus
* sizeof (CPU_REGISTER_TABLE
);
977 RegisterTable
= AllocatePages (EFI_SIZE_TO_PAGES (TableSize
));
978 ASSERT (RegisterTable
!= NULL
);
980 for (Index
= 0; Index
< NumberOfCpus
; Index
++) {
981 Status
= GetProcessorInformation (Index
, &ProcessorInfoBuffer
);
982 ASSERT_EFI_ERROR (Status
);
984 RegisterTable
[Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
985 RegisterTable
[Index
].TableLength
= 0;
986 RegisterTable
[Index
].AllocatedSize
= 0;
987 RegisterTable
[Index
].RegisterTableEntry
= 0;
989 RegisterTable
[NumberOfCpus
+ Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
990 RegisterTable
[NumberOfCpus
+ Index
].TableLength
= 0;
991 RegisterTable
[NumberOfCpus
+ Index
].AllocatedSize
= 0;
992 RegisterTable
[NumberOfCpus
+ Index
].RegisterTableEntry
= 0;
994 AcpiCpuData
->RegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RegisterTable
;
995 AcpiCpuData
->PreSmmInitRegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(RegisterTable
+ NumberOfCpus
);
1001 Enlarges CPU register table for each processor.
1003 @param[in, out] RegisterTable Pointer processor's CPU register table
1007 EnlargeRegisterTable (
1008 IN OUT CPU_REGISTER_TABLE
*RegisterTable
1011 EFI_PHYSICAL_ADDRESS Address
;
1014 UsedPages
= RegisterTable
->AllocatedSize
/ EFI_PAGE_SIZE
;
1015 Address
= (UINTN
)AllocatePages (UsedPages
+ 1);
1016 ASSERT (Address
!= 0);
1019 // If there are records existing in the register table, then copy its contents
1020 // to new region and free the old one.
1022 if (RegisterTable
->AllocatedSize
> 0) {
1024 (VOID
*) (UINTN
) Address
,
1025 (VOID
*) (UINTN
) RegisterTable
->RegisterTableEntry
,
1026 RegisterTable
->AllocatedSize
1029 FreePages ((VOID
*)(UINTN
)RegisterTable
->RegisterTableEntry
, UsedPages
);
1033 // Adjust the allocated size and register table base address.
1035 RegisterTable
->AllocatedSize
+= EFI_PAGE_SIZE
;
1036 RegisterTable
->RegisterTableEntry
= Address
;
1040 Add an entry in specified register table.
1042 This function adds an entry in specified register table, with given register type,
1043 register index, bit section and value.
1045 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
1046 If FALSE, entry will be added into register table
1047 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1048 @param[in] RegisterType Type of the register to program
1049 @param[in] Index Index of the register to program
1050 @param[in] ValidBitStart Start of the bit section
1051 @param[in] ValidBitLength Length of the bit section
1052 @param[in] Value Value to write
1055 CpuRegisterTableWriteWorker (
1056 IN BOOLEAN PreSmmFlag
,
1057 IN UINTN ProcessorNumber
,
1058 IN REGISTER_TYPE RegisterType
,
1060 IN UINT8 ValidBitStart
,
1061 IN UINT8 ValidBitLength
,
1065 CPU_FEATURES_DATA
*CpuFeaturesData
;
1066 ACPI_CPU_DATA
*AcpiCpuData
;
1067 CPU_REGISTER_TABLE
*RegisterTable
;
1068 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
1070 CpuFeaturesData
= GetCpuFeaturesData ();
1071 if (CpuFeaturesData
->RegisterTable
== NULL
) {
1072 AcpiCpuData
= GetAcpiCpuData ();
1073 ASSERT ((AcpiCpuData
!= NULL
) && (AcpiCpuData
->RegisterTable
!= 0));
1074 CpuFeaturesData
->RegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->RegisterTable
;
1075 CpuFeaturesData
->PreSmmRegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->PreSmmInitRegisterTable
;
1079 RegisterTable
= &CpuFeaturesData
->PreSmmRegisterTable
[ProcessorNumber
];
1081 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
1084 if (RegisterTable
->TableLength
== RegisterTable
->AllocatedSize
/ sizeof (CPU_REGISTER_TABLE_ENTRY
)) {
1085 EnlargeRegisterTable (RegisterTable
);
1089 // Append entry in the register table.
1091 RegisterTableEntry
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
1092 RegisterTableEntry
[RegisterTable
->TableLength
].RegisterType
= RegisterType
;
1093 RegisterTableEntry
[RegisterTable
->TableLength
].Index
= (UINT32
) Index
;
1094 RegisterTableEntry
[RegisterTable
->TableLength
].HighIndex
= (UINT32
) RShiftU64 (Index
, 32);
1095 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitStart
= ValidBitStart
;
1096 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitLength
= ValidBitLength
;
1097 RegisterTableEntry
[RegisterTable
->TableLength
].Value
= Value
;
1099 RegisterTable
->TableLength
++;
1103 Adds an entry in specified register table.
1105 This function adds an entry in specified register table, with given register type,
1106 register index, bit section and value.
1108 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1109 @param[in] RegisterType Type of the register to program
1110 @param[in] Index Index of the register to program
1111 @param[in] ValueMask Mask of bits in register to write
1112 @param[in] Value Value to write
1114 @note This service could be called by BSP only.
1118 CpuRegisterTableWrite (
1119 IN UINTN ProcessorNumber
,
1120 IN REGISTER_TYPE RegisterType
,
1122 IN UINT64 ValueMask
,
1130 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1131 End
= (UINT8
)HighBitSet64 (ValueMask
);
1132 Length
= End
- Start
+ 1;
1133 CpuRegisterTableWriteWorker (FALSE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1137 Adds an entry in specified Pre-SMM register table.
1139 This function adds an entry in specified register table, with given register type,
1140 register index, bit section and value.
1142 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
1143 @param[in] RegisterType Type of the register to program
1144 @param[in] Index Index of the register to program
1145 @param[in] ValueMask Mask of bits in register to write
1146 @param[in] Value Value to write
1148 @note This service could be called by BSP only.
1152 PreSmmCpuRegisterTableWrite (
1153 IN UINTN ProcessorNumber
,
1154 IN REGISTER_TYPE RegisterType
,
1156 IN UINT64 ValueMask
,
1164 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1165 End
= (UINT8
)HighBitSet64 (ValueMask
);
1166 Length
= End
- Start
+ 1;
1167 CpuRegisterTableWriteWorker (TRUE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1171 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1173 @param[in] CpuBitMask CPU feature bit mask buffer
1174 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
1175 @param[in] Feature The bit number of the CPU feature
1177 @retval TRUE The CPU feature is set in CpuBitMask.
1178 @retval FALSE The CPU feature is not set in CpuBitMask.
1182 IsCpuFeatureSetInCpuPcd (
1183 IN UINT8
*CpuBitMask
,
1184 IN UINTN CpuBitMaskSize
,
1188 if ((Feature
>> 3) >= CpuBitMaskSize
) {
1191 return ((*(CpuBitMask
+ (Feature
>> 3)) & (1 << (Feature
& 0x07))) != 0);
1195 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
1196 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
1197 associated with that feature should be optimized away if compiler
1198 optimizations are enabled.
1200 @param[in] Feature The bit number of the CPU feature to check in the PCD
1201 PcdCpuFeaturesSupport
1203 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1204 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1206 @note This service could be called by BSP only.
1210 IsCpuFeatureSupported (
1214 return IsCpuFeatureSetInCpuPcd (
1215 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSupport
),
1216 PcdGetSize (PcdCpuFeaturesSupport
),
1222 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1224 @param[in] Feature The bit number of the CPU feature to check in the PCD
1225 PcdCpuFeaturesSetting
1227 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1228 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1230 @note This service could be called by BSP only.
1234 IsCpuFeatureInSetting (
1238 return IsCpuFeatureSetInCpuPcd (
1239 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSetting
),
1240 PcdGetSize (PcdCpuFeaturesSetting
),
1246 Switches to assigned BSP after CPU features initialization.
1248 @param[in] ProcessorNumber The index of the CPU executing this function.
1250 @note This service could be called by BSP only.
1254 SwitchBspAfterFeaturesInitialize (
1255 IN UINTN ProcessorNumber
1258 CPU_FEATURES_DATA
*CpuFeaturesData
;
1260 CpuFeaturesData
= GetCpuFeaturesData ();
1261 CpuFeaturesData
->BspNumber
= ProcessorNumber
;