2 CPU Register Table Library functions.
4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "RegisterCpuFeatures.h"
12 Checks if two CPU feature bit masks are equal.
14 @param[in] FirstFeatureMask The first input CPU feature bit mask
15 @param[in] SecondFeatureMask The second input CPU feature bit mask
17 @retval TRUE Two CPU feature bit masks are equal.
18 @retval FALSE Two CPU feature bit masks are not equal.
22 IN UINT8
*FirstFeatureMask
,
23 IN UINT8
*SecondFeatureMask
28 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
29 if (CompareMem (FirstFeatureMask
, SecondFeatureMask
, BitMaskSize
) == 0) {
37 Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
39 @param[in] FeatureMask A pointer to the CPU feature bit mask.
50 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
51 Data8
= (UINT8
*) FeatureMask
;
52 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
53 DEBUG ((DEBUG_INFO
, " %02x ", *Data8
++));
55 DEBUG ((DEBUG_INFO
, "\n"));
59 Dump CPU feature name or CPU feature bit mask.
61 @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY
65 IN CPU_FEATURES_ENTRY
*CpuFeature
69 if (CpuFeature
->FeatureName
!= NULL
) {
70 DEBUG ((DEBUG_INFO
, "FeatureName: %a\n", CpuFeature
->FeatureName
));
72 DEBUG ((DEBUG_INFO
, "FeatureMask = "));
73 DumpCpuFeatureMask (CpuFeature
->FeatureMask
);
78 Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
80 @param[in] FeatureMask Pointer to CPU feature bit mask
81 @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer
83 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
84 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
88 IN UINT8
*FeatureMask
,
89 IN UINT8
*DependentBitMask
97 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
100 Data2
= DependentBitMask
;
101 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
102 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
110 Try to find the specify cpu featuren in former/after feature list.
112 @param[in] FeatureList Pointer to dependent CPU feature list
113 @param[in] CurrentEntry Pointer to current CPU feature entry.
114 @param[in] SearchFormer Find in former feature or after features.
115 @param[in] FeatureMask Pointer to CPU feature bit mask
117 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
118 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
122 IN LIST_ENTRY
*FeatureList
,
123 IN LIST_ENTRY
*CurrentEntry
,
124 IN BOOLEAN SearchFormer
,
125 IN UINT8
*FeatureMask
128 CPU_FEATURES_ENTRY
*CpuFeature
;
129 LIST_ENTRY
*NextEntry
;
132 // Check whether exist the not neighborhood entry first.
133 // If not exist, return FALSE means not found status.
136 NextEntry
= CurrentEntry
->BackLink
;
137 if (IsNull (FeatureList
, NextEntry
)) {
141 NextEntry
= NextEntry
->BackLink
;
142 if (IsNull (FeatureList
, NextEntry
)) {
146 NextEntry
= CurrentEntry
->BackLink
->BackLink
;
148 NextEntry
= CurrentEntry
->ForwardLink
;
149 if (IsNull (FeatureList
, NextEntry
)) {
153 NextEntry
= NextEntry
->ForwardLink
;
154 if (IsNull (FeatureList
, NextEntry
)) {
158 NextEntry
= CurrentEntry
->ForwardLink
->ForwardLink
;
161 while (!IsNull (FeatureList
, NextEntry
)) {
162 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (NextEntry
);
164 if (IsBitMaskMatchCheck (FeatureMask
, CpuFeature
->FeatureMask
)) {
169 NextEntry
= NextEntry
->BackLink
;
171 NextEntry
= NextEntry
->ForwardLink
;
179 Return feature dependence result.
181 @param[in] CpuFeature Pointer to CPU feature.
182 @param[in] Before Check before dependence or after.
183 @param[in] NextCpuFeatureMask Pointer to next CPU feature Mask.
185 @retval return the dependence result.
187 CPU_FEATURE_DEPENDENCE_TYPE
189 IN CPU_FEATURES_ENTRY
*CpuFeature
,
191 IN UINT8
*NextCpuFeatureMask
195 // if need to check before type dependence but the feature after current feature is not
196 // exist, means this before type dependence not valid, just return NoneDepType.
197 // Just like Feature A has a dependence of feature B, but Feature B not installed, so
198 // Feature A maybe insert to the last entry of the list. In this case, for below code,
199 // Featrure A has depend of feature B, but it is the last entry of the list, so the
200 // NextCpuFeatureMask is NULL, so the dependence for feature A here is useless and code
201 // just return NoneDepType.
203 if (NextCpuFeatureMask
== NULL
) {
208 if ((CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) &&
209 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->PackageBeforeFeatureBitMask
)) {
210 return PackageDepType
;
213 if ((CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) &&
214 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->CoreBeforeFeatureBitMask
)) {
218 if ((CpuFeature
->BeforeFeatureBitMask
!= NULL
) &&
219 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->BeforeFeatureBitMask
)) {
220 return ThreadDepType
;
226 if ((CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) &&
227 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->PackageAfterFeatureBitMask
)) {
228 return PackageDepType
;
231 if ((CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) &&
232 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->CoreAfterFeatureBitMask
)) {
236 if ((CpuFeature
->AfterFeatureBitMask
!= NULL
) &&
237 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->AfterFeatureBitMask
)) {
238 return ThreadDepType
;
245 Return feature dependence result.
247 @param[in] CpuFeature Pointer to CPU feature.
248 @param[in] Before Check before dependence or after.
249 @param[in] FeatureList Pointer to CPU feature list.
251 @retval return the dependence result.
253 CPU_FEATURE_DEPENDENCE_TYPE
254 DetectNoneNeighborhoodFeatureScope (
255 IN CPU_FEATURES_ENTRY
*CpuFeature
,
257 IN LIST_ENTRY
*FeatureList
261 if ((CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) &&
262 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, FALSE
, CpuFeature
->PackageBeforeFeatureBitMask
)) {
263 return PackageDepType
;
266 if ((CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) &&
267 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, FALSE
, CpuFeature
->CoreBeforeFeatureBitMask
)) {
271 if ((CpuFeature
->BeforeFeatureBitMask
!= NULL
) &&
272 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, FALSE
, CpuFeature
->BeforeFeatureBitMask
)) {
273 return ThreadDepType
;
279 if ((CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) &&
280 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, TRUE
, CpuFeature
->PackageAfterFeatureBitMask
)) {
281 return PackageDepType
;
284 if ((CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) &&
285 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, TRUE
, CpuFeature
->CoreAfterFeatureBitMask
)) {
289 if ((CpuFeature
->AfterFeatureBitMask
!= NULL
) &&
290 FindSpecifyFeature(FeatureList
, &CpuFeature
->Link
, TRUE
, CpuFeature
->AfterFeatureBitMask
)) {
291 return ThreadDepType
;
298 Base on dependence relationship to asjust feature dependence.
300 ONLY when the feature before(or after) the find feature also has
301 dependence with the find feature. In this case, driver need to base
302 on dependce relationship to decide how to insert current feature and
303 adjust the feature dependence.
305 @param[in, out] PreviousFeature CPU feature current before the find one.
306 @param[in, out] CurrentFeature Cpu feature need to adjust.
307 @param[in] FindFeature Cpu feature which current feature depends.
308 @param[in] Before Before or after dependence relationship.
310 @retval TRUE means the current feature dependence has been adjusted.
312 @retval FALSE means the previous feature dependence has been adjusted.
313 or previous feature has no dependence with the find one.
317 AdjustFeaturesDependence (
318 IN OUT CPU_FEATURES_ENTRY
*PreviousFeature
,
319 IN OUT CPU_FEATURES_ENTRY
*CurrentFeature
,
320 IN CPU_FEATURES_ENTRY
*FindFeature
,
324 CPU_FEATURE_DEPENDENCE_TYPE PreDependType
;
325 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType
;
327 PreDependType
= DetectFeatureScope(PreviousFeature
, Before
, FindFeature
->FeatureMask
);
328 CurrentDependType
= DetectFeatureScope(CurrentFeature
, Before
, FindFeature
->FeatureMask
);
331 // If previous feature has no dependence with the find featue.
334 if (PreDependType
== NoneDepType
) {
339 // If both feature have dependence, keep the one which needs use more
340 // processors and clear the dependence for the other one.
342 if (PreDependType
>= CurrentDependType
) {
350 Base on dependence relationship to asjust feature order.
352 @param[in] FeatureList Pointer to CPU feature list
353 @param[in, out] FindEntry The entry this feature depend on.
354 @param[in, out] CurrentEntry The entry for this feature.
355 @param[in] Before Before or after dependence relationship.
360 IN LIST_ENTRY
*FeatureList
,
361 IN OUT LIST_ENTRY
*FindEntry
,
362 IN OUT LIST_ENTRY
*CurrentEntry
,
366 LIST_ENTRY
*PreviousEntry
;
367 CPU_FEATURES_ENTRY
*PreviousFeature
;
368 CPU_FEATURES_ENTRY
*CurrentFeature
;
369 CPU_FEATURES_ENTRY
*FindFeature
;
372 // For CPU feature which has core or package type dependence, later code need to insert
373 // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.
374 // So if driver finds both feature A and B need to execute before feature C, driver will
375 // base on dependence type of feature A and B to update the logic here.
376 // For example, feature A has package type dependence and feature B has core type dependence,
377 // because package type dependence need to wait for more processors which has strong dependence
378 // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver
379 // will remove the feature dependence in feature B.
380 // Driver just needs to make sure before feature C been executed, feature A has finished its task
381 // in all all thread. Feature A finished in all threads also means feature B have finshed in all
385 PreviousEntry
= GetPreviousNode (FeatureList
, FindEntry
);
388 PreviousEntry
= GetNextNode (FeatureList
, FindEntry
);
391 CurrentFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
392 RemoveEntryList (CurrentEntry
);
394 if (IsNull (FeatureList
, PreviousEntry
)) {
396 // If not exist the previous or next entry, just insert the current entry.
399 InsertTailList (FindEntry
, CurrentEntry
);
401 InsertHeadList (FindEntry
, CurrentEntry
);
405 // If exist the previous or next entry, need to check it before insert curent entry.
407 PreviousFeature
= CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry
);
408 FindFeature
= CPU_FEATURE_ENTRY_FROM_LINK (FindEntry
);
410 if (AdjustFeaturesDependence (PreviousFeature
, CurrentFeature
, FindFeature
, Before
)) {
412 // Return TRUE means current feature dependence has been cleared and the previous
413 // feature dependence has been kept and used. So insert current feature before (or after)
414 // the previous feature.
417 InsertTailList (PreviousEntry
, CurrentEntry
);
419 InsertHeadList (PreviousEntry
, CurrentEntry
);
423 InsertTailList (FindEntry
, CurrentEntry
);
425 InsertHeadList (FindEntry
, CurrentEntry
);
433 Checks and adjusts current CPU features per dependency relationship.
435 @param[in] FeatureList Pointer to CPU feature list
436 @param[in] CurrentEntry Pointer to current checked CPU feature
437 @param[in] FeatureMask The feature bit mask.
439 @retval return Swapped info.
442 InsertToBeforeEntry (
443 IN LIST_ENTRY
*FeatureList
,
444 IN LIST_ENTRY
*CurrentEntry
,
445 IN UINT8
*FeatureMask
448 LIST_ENTRY
*CheckEntry
;
449 CPU_FEATURES_ENTRY
*CheckFeature
;
455 // Check all features dispatched before this entry
457 CheckEntry
= GetFirstNode (FeatureList
);
458 while (CheckEntry
!= CurrentEntry
) {
459 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
460 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
461 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, TRUE
);
465 CheckEntry
= CheckEntry
->ForwardLink
;
472 Checks and adjusts current CPU features per dependency relationship.
474 @param[in] FeatureList Pointer to CPU feature list
475 @param[in] CurrentEntry Pointer to current checked CPU feature
476 @param[in] FeatureMask The feature bit mask.
478 @retval return Swapped info.
482 IN LIST_ENTRY
*FeatureList
,
483 IN LIST_ENTRY
*CurrentEntry
,
484 IN UINT8
*FeatureMask
487 LIST_ENTRY
*CheckEntry
;
488 CPU_FEATURES_ENTRY
*CheckFeature
;
494 // Check all features dispatched after this entry
496 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
497 while (!IsNull (FeatureList
, CheckEntry
)) {
498 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
499 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
500 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, FALSE
);
504 CheckEntry
= CheckEntry
->ForwardLink
;
511 Checks and adjusts CPU features order per dependency relationship.
513 @param[in] FeatureList Pointer to CPU feature list
516 CheckCpuFeaturesDependency (
517 IN LIST_ENTRY
*FeatureList
520 LIST_ENTRY
*CurrentEntry
;
521 CPU_FEATURES_ENTRY
*CpuFeature
;
522 LIST_ENTRY
*CheckEntry
;
523 CPU_FEATURES_ENTRY
*CheckFeature
;
525 LIST_ENTRY
*TempEntry
;
526 LIST_ENTRY
*NextEntry
;
528 CurrentEntry
= GetFirstNode (FeatureList
);
529 while (!IsNull (FeatureList
, CurrentEntry
)) {
531 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
532 NextEntry
= CurrentEntry
->ForwardLink
;
533 if (CpuFeature
->BeforeAll
) {
535 // Check all features dispatched before this entry
537 CheckEntry
= GetFirstNode (FeatureList
);
538 while (CheckEntry
!= CurrentEntry
) {
539 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
540 if (!CheckFeature
->BeforeAll
) {
542 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
543 // insert currentEntry before Checked feature
545 RemoveEntryList (CurrentEntry
);
546 InsertTailList (CheckEntry
, CurrentEntry
);
550 CheckEntry
= CheckEntry
->ForwardLink
;
553 CurrentEntry
= NextEntry
;
558 if (CpuFeature
->AfterAll
) {
560 // Check all features dispatched after this entry
562 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
563 while (!IsNull (FeatureList
, CheckEntry
)) {
564 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
565 if (!CheckFeature
->AfterAll
) {
567 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
568 // insert currentEntry after Checked feature
570 TempEntry
= GetNextNode (FeatureList
, CurrentEntry
);
571 RemoveEntryList (CurrentEntry
);
572 InsertHeadList (CheckEntry
, CurrentEntry
);
573 CurrentEntry
= TempEntry
;
577 CheckEntry
= CheckEntry
->ForwardLink
;
580 CurrentEntry
= NextEntry
;
585 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
586 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->BeforeFeatureBitMask
);
592 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
593 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->AfterFeatureBitMask
);
599 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
600 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreBeforeFeatureBitMask
);
606 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
607 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreAfterFeatureBitMask
);
613 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
614 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageBeforeFeatureBitMask
);
620 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
621 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageAfterFeatureBitMask
);
627 CurrentEntry
= CurrentEntry
->ForwardLink
;
632 Worker function to register CPU Feature.
634 @param[in] CpuFeature Pointer to CPU feature entry
636 @retval RETURN_SUCCESS The CPU feature was successfully registered.
637 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
639 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
640 supported due to a circular dependency between
641 BEFORE and AFTER features.
644 RegisterCpuFeatureWorker (
645 IN CPU_FEATURES_ENTRY
*CpuFeature
649 CPU_FEATURES_DATA
*CpuFeaturesData
;
650 CPU_FEATURES_ENTRY
*CpuFeatureEntry
;
653 BOOLEAN FeatureExist
;
655 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
656 CpuFeaturesData
= GetCpuFeaturesData ();
657 if (CpuFeaturesData
->FeaturesCount
== 0) {
658 InitializeListHead (&CpuFeaturesData
->FeatureList
);
659 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.MemoryMappedLock
);
660 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.ConsoleLogLock
);
661 CpuFeaturesData
->BitMaskSize
= (UINT32
) BitMaskSize
;
663 ASSERT (CpuFeaturesData
->BitMaskSize
== BitMaskSize
);
665 FeatureExist
= FALSE
;
666 CpuFeatureEntry
= NULL
;
667 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
668 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
669 CpuFeatureEntry
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
670 if (IsCpuFeatureMatch (CpuFeature
->FeatureMask
, CpuFeatureEntry
->FeatureMask
)) {
672 // If this feature already registered
677 Entry
= Entry
->ForwardLink
;
681 DEBUG ((DEBUG_INFO
, "[NEW] "));
682 DumpCpuFeature (CpuFeature
);
683 InsertTailList (&CpuFeaturesData
->FeatureList
, &CpuFeature
->Link
);
684 CpuFeaturesData
->FeaturesCount
++;
686 DEBUG ((DEBUG_INFO
, "[OVERRIDE] "));
687 DumpCpuFeature (CpuFeature
);
688 ASSERT (CpuFeatureEntry
!= NULL
);
690 // Overwrite original parameters of CPU feature
692 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
693 CpuFeatureEntry
->GetConfigDataFunc
= CpuFeature
->GetConfigDataFunc
;
695 if (CpuFeature
->SupportFunc
!= NULL
) {
696 CpuFeatureEntry
->SupportFunc
= CpuFeature
->SupportFunc
;
698 if (CpuFeature
->InitializeFunc
!= NULL
) {
699 CpuFeatureEntry
->InitializeFunc
= CpuFeature
->InitializeFunc
;
701 if (CpuFeature
->FeatureName
!= NULL
) {
702 if (CpuFeatureEntry
->FeatureName
== NULL
) {
703 CpuFeatureEntry
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
704 ASSERT (CpuFeatureEntry
->FeatureName
!= NULL
);
706 Status
= AsciiStrCpyS (CpuFeatureEntry
->FeatureName
, CPU_FEATURE_NAME_SIZE
, CpuFeature
->FeatureName
);
707 ASSERT_EFI_ERROR (Status
);
708 FreePool (CpuFeature
->FeatureName
);
710 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
711 if (CpuFeatureEntry
->BeforeFeatureBitMask
!= NULL
) {
712 FreePool (CpuFeatureEntry
->BeforeFeatureBitMask
);
714 CpuFeatureEntry
->BeforeFeatureBitMask
= CpuFeature
->BeforeFeatureBitMask
;
716 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
717 if (CpuFeatureEntry
->AfterFeatureBitMask
!= NULL
) {
718 FreePool (CpuFeatureEntry
->AfterFeatureBitMask
);
720 CpuFeatureEntry
->AfterFeatureBitMask
= CpuFeature
->AfterFeatureBitMask
;
722 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
723 if (CpuFeatureEntry
->CoreBeforeFeatureBitMask
!= NULL
) {
724 FreePool (CpuFeatureEntry
->CoreBeforeFeatureBitMask
);
726 CpuFeatureEntry
->CoreBeforeFeatureBitMask
= CpuFeature
->CoreBeforeFeatureBitMask
;
728 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
729 if (CpuFeatureEntry
->CoreAfterFeatureBitMask
!= NULL
) {
730 FreePool (CpuFeatureEntry
->CoreAfterFeatureBitMask
);
732 CpuFeatureEntry
->CoreAfterFeatureBitMask
= CpuFeature
->CoreAfterFeatureBitMask
;
734 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
735 if (CpuFeatureEntry
->PackageBeforeFeatureBitMask
!= NULL
) {
736 FreePool (CpuFeatureEntry
->PackageBeforeFeatureBitMask
);
738 CpuFeatureEntry
->PackageBeforeFeatureBitMask
= CpuFeature
->PackageBeforeFeatureBitMask
;
740 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
741 if (CpuFeatureEntry
->PackageAfterFeatureBitMask
!= NULL
) {
742 FreePool (CpuFeatureEntry
->PackageAfterFeatureBitMask
);
744 CpuFeatureEntry
->PackageAfterFeatureBitMask
= CpuFeature
->PackageAfterFeatureBitMask
;
747 CpuFeatureEntry
->BeforeAll
= CpuFeature
->BeforeAll
;
748 CpuFeatureEntry
->AfterAll
= CpuFeature
->AfterAll
;
750 FreePool (CpuFeature
->FeatureMask
);
751 FreePool (CpuFeature
);
754 // Verify CPU features dependency can change CPU feature order
756 CheckCpuFeaturesDependency (&CpuFeaturesData
->FeatureList
);
757 return RETURN_SUCCESS
;
761 Sets CPU feature bit mask in CPU feature bit mask buffer.
763 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
764 @param[in] Feature The bit number of the CPU feature
765 @param[in] BitMaskSize CPU feature bit mask buffer size
768 SetCpuFeaturesBitMask (
769 IN UINT8
**FeaturesBitMask
,
774 UINT8
*CpuFeaturesBitMask
;
776 ASSERT (FeaturesBitMask
!= NULL
);
777 CpuFeaturesBitMask
= *FeaturesBitMask
;
778 if (CpuFeaturesBitMask
== NULL
) {
779 CpuFeaturesBitMask
= AllocateZeroPool (BitMaskSize
);
780 ASSERT (CpuFeaturesBitMask
!= NULL
);
781 *FeaturesBitMask
= CpuFeaturesBitMask
;
784 CpuFeaturesBitMask
+= (Feature
/ 8);
785 *CpuFeaturesBitMask
|= (UINT8
) (1 << (Feature
% 8));
789 Registers a CPU Feature.
791 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
793 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
794 is an optional parameter that may be NULL. If NULL,
795 then the most recently registered function for the
796 CPU feature is used. If no functions are registered
797 for a CPU feature, then the CPU configuration data
798 for the registered feature is NULL.
799 @param[in] SupportFunc CPU feature support function. This is an optional
800 parameter that may be NULL. If NULL, then the most
801 recently registered function for the CPU feature is
802 used. If no functions are registered for a CPU
803 feature, then the CPU feature is assumed to be
804 supported by all CPUs.
805 @param[in] InitializeFunc CPU feature initialize function. This is an optional
806 parameter that may be NULL. If NULL, then the most
807 recently registered function for the CPU feature is
808 used. If no functions are registered for a CPU
809 feature, then the CPU feature initialization is
811 @param[in] ... Variable argument list of UINT32 CPU feature value.
812 Values with no modifiers are the features provided
813 by the registered functions.
814 Values with CPU_FEATURE_BEFORE modifier are features
815 that must be initialized after the features provided
816 by the registered functions are used.
817 Values with CPU_FEATURE_AFTER modifier are features
818 that must be initialized before the features provided
819 by the registered functions are used.
820 The last argument in this variable argument list must
821 always be CPU_FEATURE_END.
823 @retval RETURN_SUCCESS The CPU feature was successfully registered.
824 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
826 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
827 supported due to a circular dependency between
828 BEFORE and AFTER features.
829 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration
830 not updated by Platform driver yet.
832 @note This service could be called by BSP only.
837 IN CHAR8
*FeatureName
, OPTIONAL
838 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc
, OPTIONAL
839 IN CPU_FEATURE_SUPPORT SupportFunc
, OPTIONAL
840 IN CPU_FEATURE_INITIALIZE InitializeFunc
, OPTIONAL
848 CPU_FEATURES_ENTRY
*CpuFeature
;
850 UINT8
*BeforeFeatureBitMask
;
851 UINT8
*AfterFeatureBitMask
;
852 UINT8
*CoreBeforeFeatureBitMask
;
853 UINT8
*CoreAfterFeatureBitMask
;
854 UINT8
*PackageBeforeFeatureBitMask
;
855 UINT8
*PackageAfterFeatureBitMask
;
860 BeforeFeatureBitMask
= NULL
;
861 AfterFeatureBitMask
= NULL
;
862 CoreBeforeFeatureBitMask
= NULL
;
863 CoreAfterFeatureBitMask
= NULL
;
864 PackageBeforeFeatureBitMask
= NULL
;
865 PackageAfterFeatureBitMask
= NULL
;
869 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
871 VA_START (Marker
, InitializeFunc
);
872 Feature
= VA_ARG (Marker
, UINT32
);
873 while (Feature
!= CPU_FEATURE_END
) {
874 ASSERT ((Feature
& (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
))
875 != (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
));
876 ASSERT ((Feature
& (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
))
877 != (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
));
878 ASSERT ((Feature
& (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
))
879 != (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
));
880 ASSERT ((Feature
& (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
))
881 != (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
));
882 if (Feature
< CPU_FEATURE_BEFORE
) {
883 BeforeAll
= ((Feature
& CPU_FEATURE_BEFORE_ALL
) != 0) ? TRUE
: FALSE
;
884 AfterAll
= ((Feature
& CPU_FEATURE_AFTER_ALL
) != 0) ? TRUE
: FALSE
;
885 Feature
&= ~(CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
);
886 ASSERT (FeatureMask
== NULL
);
887 SetCpuFeaturesBitMask (&FeatureMask
, Feature
, BitMaskSize
);
888 } else if ((Feature
& CPU_FEATURE_BEFORE
) != 0) {
889 SetCpuFeaturesBitMask (&BeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_BEFORE
, BitMaskSize
);
890 } else if ((Feature
& CPU_FEATURE_AFTER
) != 0) {
891 SetCpuFeaturesBitMask (&AfterFeatureBitMask
, Feature
& ~CPU_FEATURE_AFTER
, BitMaskSize
);
892 } else if ((Feature
& CPU_FEATURE_CORE_BEFORE
) != 0) {
893 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_BEFORE
, BitMaskSize
);
894 } else if ((Feature
& CPU_FEATURE_CORE_AFTER
) != 0) {
895 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_AFTER
, BitMaskSize
);
896 } else if ((Feature
& CPU_FEATURE_PACKAGE_BEFORE
) != 0) {
897 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_BEFORE
, BitMaskSize
);
898 } else if ((Feature
& CPU_FEATURE_PACKAGE_AFTER
) != 0) {
899 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_AFTER
, BitMaskSize
);
901 Feature
= VA_ARG (Marker
, UINT32
);
905 CpuFeature
= AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY
));
906 ASSERT (CpuFeature
!= NULL
);
907 CpuFeature
->Signature
= CPU_FEATURE_ENTRY_SIGNATURE
;
908 CpuFeature
->FeatureMask
= FeatureMask
;
909 CpuFeature
->BeforeFeatureBitMask
= BeforeFeatureBitMask
;
910 CpuFeature
->AfterFeatureBitMask
= AfterFeatureBitMask
;
911 CpuFeature
->CoreBeforeFeatureBitMask
= CoreBeforeFeatureBitMask
;
912 CpuFeature
->CoreAfterFeatureBitMask
= CoreAfterFeatureBitMask
;
913 CpuFeature
->PackageBeforeFeatureBitMask
= PackageBeforeFeatureBitMask
;
914 CpuFeature
->PackageAfterFeatureBitMask
= PackageAfterFeatureBitMask
;
915 CpuFeature
->BeforeAll
= BeforeAll
;
916 CpuFeature
->AfterAll
= AfterAll
;
917 CpuFeature
->GetConfigDataFunc
= GetConfigDataFunc
;
918 CpuFeature
->SupportFunc
= SupportFunc
;
919 CpuFeature
->InitializeFunc
= InitializeFunc
;
920 if (FeatureName
!= NULL
) {
921 CpuFeature
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
922 ASSERT (CpuFeature
->FeatureName
!= NULL
);
923 Status
= AsciiStrCpyS (CpuFeature
->FeatureName
, CPU_FEATURE_NAME_SIZE
, FeatureName
);
924 ASSERT_EFI_ERROR (Status
);
927 Status
= RegisterCpuFeatureWorker (CpuFeature
);
928 ASSERT_EFI_ERROR (Status
);
930 return RETURN_SUCCESS
;
934 Return ACPI_CPU_DATA data.
936 @return Pointer to ACPI_CPU_DATA data.
945 UINTN NumberOfEnabledProcessors
;
946 ACPI_CPU_DATA
*AcpiCpuData
;
948 CPU_REGISTER_TABLE
*RegisterTable
;
950 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
952 AcpiCpuData
= (ACPI_CPU_DATA
*) (UINTN
) PcdGet64 (PcdCpuS3DataAddress
);
953 if (AcpiCpuData
!= NULL
) {
957 AcpiCpuData
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA
)));
958 ASSERT (AcpiCpuData
!= NULL
);
961 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
963 Status
= PcdSet64S (PcdCpuS3DataAddress
, (UINT64
)(UINTN
)AcpiCpuData
);
964 ASSERT_EFI_ERROR (Status
);
966 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
967 AcpiCpuData
->NumberOfCpus
= (UINT32
)NumberOfCpus
;
970 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
972 TableSize
= 2 * NumberOfCpus
* sizeof (CPU_REGISTER_TABLE
);
973 RegisterTable
= AllocatePages (EFI_SIZE_TO_PAGES (TableSize
));
974 ASSERT (RegisterTable
!= NULL
);
976 for (Index
= 0; Index
< NumberOfCpus
; Index
++) {
977 Status
= GetProcessorInformation (Index
, &ProcessorInfoBuffer
);
978 ASSERT_EFI_ERROR (Status
);
980 RegisterTable
[Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
981 RegisterTable
[Index
].TableLength
= 0;
982 RegisterTable
[Index
].AllocatedSize
= 0;
983 RegisterTable
[Index
].RegisterTableEntry
= 0;
985 RegisterTable
[NumberOfCpus
+ Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
986 RegisterTable
[NumberOfCpus
+ Index
].TableLength
= 0;
987 RegisterTable
[NumberOfCpus
+ Index
].AllocatedSize
= 0;
988 RegisterTable
[NumberOfCpus
+ Index
].RegisterTableEntry
= 0;
990 AcpiCpuData
->RegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RegisterTable
;
991 AcpiCpuData
->PreSmmInitRegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(RegisterTable
+ NumberOfCpus
);
997 Enlarges CPU register table for each processor.
999 @param[in, out] RegisterTable Pointer processor's CPU register table
1003 EnlargeRegisterTable (
1004 IN OUT CPU_REGISTER_TABLE
*RegisterTable
1007 EFI_PHYSICAL_ADDRESS Address
;
1010 UsedPages
= RegisterTable
->AllocatedSize
/ EFI_PAGE_SIZE
;
1011 Address
= (UINTN
)AllocatePages (UsedPages
+ 1);
1012 ASSERT (Address
!= 0);
1015 // If there are records existing in the register table, then copy its contents
1016 // to new region and free the old one.
1018 if (RegisterTable
->AllocatedSize
> 0) {
1020 (VOID
*) (UINTN
) Address
,
1021 (VOID
*) (UINTN
) RegisterTable
->RegisterTableEntry
,
1022 RegisterTable
->AllocatedSize
1025 FreePages ((VOID
*)(UINTN
)RegisterTable
->RegisterTableEntry
, UsedPages
);
1029 // Adjust the allocated size and register table base address.
1031 RegisterTable
->AllocatedSize
+= EFI_PAGE_SIZE
;
1032 RegisterTable
->RegisterTableEntry
= Address
;
1036 Add an entry in specified register table.
1038 This function adds an entry in specified register table, with given register type,
1039 register index, bit section and value.
1041 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
1042 If FALSE, entry will be added into register table
1043 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1044 @param[in] RegisterType Type of the register to program
1045 @param[in] Index Index of the register to program
1046 @param[in] ValidBitStart Start of the bit section
1047 @param[in] ValidBitLength Length of the bit section
1048 @param[in] Value Value to write
1051 CpuRegisterTableWriteWorker (
1052 IN BOOLEAN PreSmmFlag
,
1053 IN UINTN ProcessorNumber
,
1054 IN REGISTER_TYPE RegisterType
,
1056 IN UINT8 ValidBitStart
,
1057 IN UINT8 ValidBitLength
,
1061 CPU_FEATURES_DATA
*CpuFeaturesData
;
1062 ACPI_CPU_DATA
*AcpiCpuData
;
1063 CPU_REGISTER_TABLE
*RegisterTable
;
1064 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
1066 CpuFeaturesData
= GetCpuFeaturesData ();
1067 if (CpuFeaturesData
->RegisterTable
== NULL
) {
1068 AcpiCpuData
= GetAcpiCpuData ();
1069 ASSERT ((AcpiCpuData
!= NULL
) && (AcpiCpuData
->RegisterTable
!= 0));
1070 CpuFeaturesData
->RegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->RegisterTable
;
1071 CpuFeaturesData
->PreSmmRegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->PreSmmInitRegisterTable
;
1075 RegisterTable
= &CpuFeaturesData
->PreSmmRegisterTable
[ProcessorNumber
];
1077 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
1080 if (RegisterTable
->TableLength
== RegisterTable
->AllocatedSize
/ sizeof (CPU_REGISTER_TABLE_ENTRY
)) {
1081 EnlargeRegisterTable (RegisterTable
);
1085 // Append entry in the register table.
1087 RegisterTableEntry
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
1088 RegisterTableEntry
[RegisterTable
->TableLength
].RegisterType
= RegisterType
;
1089 RegisterTableEntry
[RegisterTable
->TableLength
].Index
= (UINT32
) Index
;
1090 RegisterTableEntry
[RegisterTable
->TableLength
].HighIndex
= (UINT32
) RShiftU64 (Index
, 32);
1091 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitStart
= ValidBitStart
;
1092 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitLength
= ValidBitLength
;
1093 RegisterTableEntry
[RegisterTable
->TableLength
].Value
= Value
;
1095 RegisterTable
->TableLength
++;
1099 Adds an entry in specified register table.
1101 This function adds an entry in specified register table, with given register type,
1102 register index, bit section and value.
1104 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1105 @param[in] RegisterType Type of the register to program
1106 @param[in] Index Index of the register to program
1107 @param[in] ValueMask Mask of bits in register to write
1108 @param[in] Value Value to write
1110 @note This service could be called by BSP only.
1114 CpuRegisterTableWrite (
1115 IN UINTN ProcessorNumber
,
1116 IN REGISTER_TYPE RegisterType
,
1118 IN UINT64 ValueMask
,
1126 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1127 End
= (UINT8
)HighBitSet64 (ValueMask
);
1128 Length
= End
- Start
+ 1;
1129 CpuRegisterTableWriteWorker (FALSE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1133 Adds an entry in specified Pre-SMM register table.
1135 This function adds an entry in specified register table, with given register type,
1136 register index, bit section and value.
1138 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
1139 @param[in] RegisterType Type of the register to program
1140 @param[in] Index Index of the register to program
1141 @param[in] ValueMask Mask of bits in register to write
1142 @param[in] Value Value to write
1144 @note This service could be called by BSP only.
1148 PreSmmCpuRegisterTableWrite (
1149 IN UINTN ProcessorNumber
,
1150 IN REGISTER_TYPE RegisterType
,
1152 IN UINT64 ValueMask
,
1160 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1161 End
= (UINT8
)HighBitSet64 (ValueMask
);
1162 Length
= End
- Start
+ 1;
1163 CpuRegisterTableWriteWorker (TRUE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1167 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1169 @param[in] CpuBitMask CPU feature bit mask buffer
1170 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
1171 @param[in] Feature The bit number of the CPU feature
1173 @retval TRUE The CPU feature is set in CpuBitMask.
1174 @retval FALSE The CPU feature is not set in CpuBitMask.
1178 IsCpuFeatureSetInCpuPcd (
1179 IN UINT8
*CpuBitMask
,
1180 IN UINTN CpuBitMaskSize
,
1184 if ((Feature
>> 3) >= CpuBitMaskSize
) {
1187 return ((*(CpuBitMask
+ (Feature
>> 3)) & (1 << (Feature
& 0x07))) != 0);
1191 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
1192 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
1193 associated with that feature should be optimized away if compiler
1194 optimizations are enabled.
1196 @param[in] Feature The bit number of the CPU feature to check in the PCD
1197 PcdCpuFeaturesSupport
1199 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1200 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1202 @note This service could be called by BSP only.
1206 IsCpuFeatureSupported (
1210 return IsCpuFeatureSetInCpuPcd (
1211 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSupport
),
1212 PcdGetSize (PcdCpuFeaturesSupport
),
1218 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1220 @param[in] Feature The bit number of the CPU feature to check in the PCD
1221 PcdCpuFeaturesSetting
1223 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1224 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1226 @note This service could be called by BSP only.
1230 IsCpuFeatureInSetting (
1234 return IsCpuFeatureSetInCpuPcd (
1235 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSetting
),
1236 PcdGetSize (PcdCpuFeaturesSetting
),
1242 Switches to assigned BSP after CPU features initialization.
1244 @param[in] ProcessorNumber The index of the CPU executing this function.
1246 @note This service could be called by BSP only.
1250 SwitchBspAfterFeaturesInitialize (
1251 IN UINTN ProcessorNumber
1254 CPU_FEATURES_DATA
*CpuFeaturesData
;
1256 CpuFeaturesData
= GetCpuFeaturesData ();
1257 CpuFeaturesData
->BspNumber
= ProcessorNumber
;