2 CPU Register Table Library functions.
4 Copyright (c) 2017, 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 (PcdCpuFeaturesSupport
);
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 (PcdCpuFeaturesSupport
);
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 (PcdCpuFeaturesSupport
);
106 Data2
= DependentBitMask
;
107 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
108 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
116 Return feature dependence result.
118 @param[in] CpuFeature Pointer to CPU feature.
119 @param[in] Before Check before dependence or after.
120 @param[in] NextCpuFeatureMask Pointer to next CPU feature Mask.
122 @retval return the dependence result.
124 CPU_FEATURE_DEPENDENCE_TYPE
126 IN CPU_FEATURES_ENTRY
*CpuFeature
,
128 IN UINT8
*NextCpuFeatureMask
132 // if need to check before type dependence but the feature after current feature is not
133 // exist, means this before type dependence not valid, just return NoneDepType.
134 // Just like Feature A has a dependence of feature B, but Feature B not installed, so
135 // Feature A maybe insert to the last entry of the list. In this case, for below code,
136 // Featrure A has depend of feature B, but it is the last entry of the list, so the
137 // NextCpuFeatureMask is NULL, so the dependence for feature A here is useless and code
138 // just return NoneDepType.
140 if (NextCpuFeatureMask
== NULL
) {
145 if ((CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) &&
146 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->PackageBeforeFeatureBitMask
)) {
147 return PackageDepType
;
150 if ((CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) &&
151 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->CoreBeforeFeatureBitMask
)) {
155 if ((CpuFeature
->BeforeFeatureBitMask
!= NULL
) &&
156 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->BeforeFeatureBitMask
)) {
157 return ThreadDepType
;
163 if ((CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) &&
164 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->PackageAfterFeatureBitMask
)) {
165 return PackageDepType
;
168 if ((CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) &&
169 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->CoreAfterFeatureBitMask
)) {
173 if ((CpuFeature
->AfterFeatureBitMask
!= NULL
) &&
174 IsBitMaskMatchCheck (NextCpuFeatureMask
, CpuFeature
->AfterFeatureBitMask
)) {
175 return ThreadDepType
;
182 Base on dependence relationship to asjust feature dependence.
184 ONLY when the feature before(or after) the find feature also has
185 dependence with the find feature. In this case, driver need to base
186 on dependce relationship to decide how to insert current feature and
187 adjust the feature dependence.
189 @param[in, out] PreviousFeature CPU feature current before the find one.
190 @param[in, out] CurrentFeature Cpu feature need to adjust.
191 @param[in] FindFeature Cpu feature which current feature depends.
192 @param[in] Before Before or after dependence relationship.
194 @retval TRUE means the current feature dependence has been adjusted.
196 @retval FALSE means the previous feature dependence has been adjusted.
197 or previous feature has no dependence with the find one.
201 AdjustFeaturesDependence (
202 IN OUT CPU_FEATURES_ENTRY
*PreviousFeature
,
203 IN OUT CPU_FEATURES_ENTRY
*CurrentFeature
,
204 IN CPU_FEATURES_ENTRY
*FindFeature
,
208 CPU_FEATURE_DEPENDENCE_TYPE PreDependType
;
209 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType
;
211 PreDependType
= DetectFeatureScope(PreviousFeature
, Before
, FindFeature
->FeatureMask
);
212 CurrentDependType
= DetectFeatureScope(CurrentFeature
, Before
, FindFeature
->FeatureMask
);
215 // If previous feature has no dependence with the find featue.
218 if (PreDependType
== NoneDepType
) {
223 // If both feature have dependence, keep the one which needs use more
224 // processors and clear the dependence for the other one.
226 if (PreDependType
>= CurrentDependType
) {
234 Base on dependence relationship to asjust feature order.
236 @param[in] FeatureList Pointer to CPU feature list
237 @param[in, out] FindEntry The entry this feature depend on.
238 @param[in, out] CurrentEntry The entry for this feature.
239 @param[in] Before Before or after dependence relationship.
244 IN LIST_ENTRY
*FeatureList
,
245 IN OUT LIST_ENTRY
*FindEntry
,
246 IN OUT LIST_ENTRY
*CurrentEntry
,
250 LIST_ENTRY
*PreviousEntry
;
251 CPU_FEATURES_ENTRY
*PreviousFeature
;
252 CPU_FEATURES_ENTRY
*CurrentFeature
;
253 CPU_FEATURES_ENTRY
*FindFeature
;
256 // For CPU feature which has core or package type dependence, later code need to insert
257 // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.
258 // So if driver finds both feature A and B need to execute before feature C, driver will
259 // base on dependence type of feature A and B to update the logic here.
260 // For example, feature A has package type dependence and feature B has core type dependence,
261 // because package type dependence need to wait for more processors which has strong dependence
262 // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver
263 // will remove the feature dependence in feature B.
264 // Driver just needs to make sure before feature C been executed, feature A has finished its task
265 // in all all thread. Feature A finished in all threads also means feature B have finshed in all
269 PreviousEntry
= GetPreviousNode (FeatureList
, FindEntry
);
271 PreviousEntry
= GetNextNode (FeatureList
, FindEntry
);
274 CurrentFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
275 RemoveEntryList (CurrentEntry
);
277 if (IsNull (FeatureList
, PreviousEntry
)) {
279 // If not exist the previous or next entry, just insert the current entry.
282 InsertTailList (FindEntry
, CurrentEntry
);
284 InsertHeadList (FindEntry
, CurrentEntry
);
288 // If exist the previous or next entry, need to check it before insert curent entry.
290 PreviousFeature
= CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry
);
291 FindFeature
= CPU_FEATURE_ENTRY_FROM_LINK (FindEntry
);
293 if (AdjustFeaturesDependence (PreviousFeature
, CurrentFeature
, FindFeature
, Before
)) {
295 // Return TRUE means current feature dependence has been cleared and the previous
296 // feature dependence has been kept and used. So insert current feature before (or after)
297 // the previous feature.
300 InsertTailList (PreviousEntry
, CurrentEntry
);
302 InsertHeadList (PreviousEntry
, CurrentEntry
);
306 InsertTailList (FindEntry
, CurrentEntry
);
308 InsertHeadList (FindEntry
, CurrentEntry
);
315 Checks and adjusts current CPU features per dependency relationship.
317 @param[in] FeatureList Pointer to CPU feature list
318 @param[in] CurrentEntry Pointer to current checked CPU feature
319 @param[in] FeatureMask The feature bit mask.
321 @retval return Swapped info.
324 InsertToBeforeEntry (
325 IN LIST_ENTRY
*FeatureList
,
326 IN LIST_ENTRY
*CurrentEntry
,
327 IN UINT8
*FeatureMask
330 LIST_ENTRY
*CheckEntry
;
331 CPU_FEATURES_ENTRY
*CheckFeature
;
337 // Check all features dispatched before this entry
339 CheckEntry
= GetFirstNode (FeatureList
);
340 while (CheckEntry
!= CurrentEntry
) {
341 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
342 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
343 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, TRUE
);
347 CheckEntry
= CheckEntry
->ForwardLink
;
354 Checks and adjusts current CPU features per dependency relationship.
356 @param[in] FeatureList Pointer to CPU feature list
357 @param[in] CurrentEntry Pointer to current checked CPU feature
358 @param[in] FeatureMask The feature bit mask.
360 @retval return Swapped info.
364 IN LIST_ENTRY
*FeatureList
,
365 IN LIST_ENTRY
*CurrentEntry
,
366 IN UINT8
*FeatureMask
369 LIST_ENTRY
*CheckEntry
;
370 CPU_FEATURES_ENTRY
*CheckFeature
;
376 // Check all features dispatched after this entry
378 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
379 while (!IsNull (FeatureList
, CheckEntry
)) {
380 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
381 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
382 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, FALSE
);
386 CheckEntry
= CheckEntry
->ForwardLink
;
393 Checks and adjusts CPU features order per dependency relationship.
395 @param[in] FeatureList Pointer to CPU feature list
398 CheckCpuFeaturesDependency (
399 IN LIST_ENTRY
*FeatureList
402 LIST_ENTRY
*CurrentEntry
;
403 CPU_FEATURES_ENTRY
*CpuFeature
;
404 LIST_ENTRY
*CheckEntry
;
405 CPU_FEATURES_ENTRY
*CheckFeature
;
407 LIST_ENTRY
*TempEntry
;
408 LIST_ENTRY
*NextEntry
;
410 CurrentEntry
= GetFirstNode (FeatureList
);
411 while (!IsNull (FeatureList
, CurrentEntry
)) {
413 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
414 NextEntry
= CurrentEntry
->ForwardLink
;
415 if (CpuFeature
->BeforeAll
) {
417 // Check all features dispatched before this entry
419 CheckEntry
= GetFirstNode (FeatureList
);
420 while (CheckEntry
!= CurrentEntry
) {
421 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
422 if (!CheckFeature
->BeforeAll
) {
424 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
425 // insert currentEntry before Checked feature
427 RemoveEntryList (CurrentEntry
);
428 InsertTailList (CheckEntry
, CurrentEntry
);
432 CheckEntry
= CheckEntry
->ForwardLink
;
435 CurrentEntry
= NextEntry
;
440 if (CpuFeature
->AfterAll
) {
442 // Check all features dispatched after this entry
444 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
445 while (!IsNull (FeatureList
, CheckEntry
)) {
446 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
447 if (!CheckFeature
->AfterAll
) {
449 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
450 // insert currentEntry after Checked feature
452 TempEntry
= GetNextNode (FeatureList
, CurrentEntry
);
453 RemoveEntryList (CurrentEntry
);
454 InsertHeadList (CheckEntry
, CurrentEntry
);
455 CurrentEntry
= TempEntry
;
459 CheckEntry
= CheckEntry
->ForwardLink
;
462 CurrentEntry
= NextEntry
;
467 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
468 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->BeforeFeatureBitMask
);
474 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
475 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->AfterFeatureBitMask
);
481 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
482 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreBeforeFeatureBitMask
);
488 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
489 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreAfterFeatureBitMask
);
495 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
496 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageBeforeFeatureBitMask
);
502 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
503 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageAfterFeatureBitMask
);
509 CurrentEntry
= CurrentEntry
->ForwardLink
;
514 Worker function to register CPU Feature.
516 @param[in] CpuFeature Pointer to CPU feature entry
518 @retval RETURN_SUCCESS The CPU feature was successfully registered.
519 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
521 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
522 supported due to a circular dependency between
523 BEFORE and AFTER features.
526 RegisterCpuFeatureWorker (
527 IN CPU_FEATURES_ENTRY
*CpuFeature
531 CPU_FEATURES_DATA
*CpuFeaturesData
;
532 CPU_FEATURES_ENTRY
*CpuFeatureEntry
;
535 BOOLEAN FeatureExist
;
537 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
538 CpuFeaturesData
= GetCpuFeaturesData ();
539 if (CpuFeaturesData
->FeaturesCount
== 0) {
540 InitializeListHead (&CpuFeaturesData
->FeatureList
);
541 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.MemoryMappedLock
);
542 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.ConsoleLogLock
);
543 CpuFeaturesData
->BitMaskSize
= (UINT32
) BitMaskSize
;
545 ASSERT (CpuFeaturesData
->BitMaskSize
== BitMaskSize
);
547 FeatureExist
= FALSE
;
548 CpuFeatureEntry
= NULL
;
549 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
550 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
551 CpuFeatureEntry
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
552 if (IsCpuFeatureMatch (CpuFeature
->FeatureMask
, CpuFeatureEntry
->FeatureMask
)) {
554 // If this feature already registered
559 Entry
= Entry
->ForwardLink
;
563 DEBUG ((DEBUG_INFO
, "[NEW] "));
564 DumpCpuFeature (CpuFeature
);
565 InsertTailList (&CpuFeaturesData
->FeatureList
, &CpuFeature
->Link
);
566 CpuFeaturesData
->FeaturesCount
++;
568 DEBUG ((DEBUG_INFO
, "[OVERRIDE] "));
569 DumpCpuFeature (CpuFeature
);
570 ASSERT (CpuFeatureEntry
!= NULL
);
572 // Overwrite original parameters of CPU feature
574 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
575 CpuFeatureEntry
->GetConfigDataFunc
= CpuFeature
->GetConfigDataFunc
;
577 if (CpuFeature
->SupportFunc
!= NULL
) {
578 CpuFeatureEntry
->SupportFunc
= CpuFeature
->SupportFunc
;
580 if (CpuFeature
->InitializeFunc
!= NULL
) {
581 CpuFeatureEntry
->InitializeFunc
= CpuFeature
->InitializeFunc
;
583 if (CpuFeature
->FeatureName
!= NULL
) {
584 if (CpuFeatureEntry
->FeatureName
== NULL
) {
585 CpuFeatureEntry
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
586 ASSERT (CpuFeatureEntry
->FeatureName
!= NULL
);
588 Status
= AsciiStrCpyS (CpuFeatureEntry
->FeatureName
, CPU_FEATURE_NAME_SIZE
, CpuFeature
->FeatureName
);
589 ASSERT_EFI_ERROR (Status
);
590 FreePool (CpuFeature
->FeatureName
);
592 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
593 if (CpuFeatureEntry
->BeforeFeatureBitMask
!= NULL
) {
594 FreePool (CpuFeatureEntry
->BeforeFeatureBitMask
);
596 CpuFeatureEntry
->BeforeFeatureBitMask
= CpuFeature
->BeforeFeatureBitMask
;
598 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
599 if (CpuFeatureEntry
->AfterFeatureBitMask
!= NULL
) {
600 FreePool (CpuFeatureEntry
->AfterFeatureBitMask
);
602 CpuFeatureEntry
->AfterFeatureBitMask
= CpuFeature
->AfterFeatureBitMask
;
604 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
605 if (CpuFeatureEntry
->CoreBeforeFeatureBitMask
!= NULL
) {
606 FreePool (CpuFeatureEntry
->CoreBeforeFeatureBitMask
);
608 CpuFeatureEntry
->CoreBeforeFeatureBitMask
= CpuFeature
->CoreBeforeFeatureBitMask
;
610 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
611 if (CpuFeatureEntry
->CoreAfterFeatureBitMask
!= NULL
) {
612 FreePool (CpuFeatureEntry
->CoreAfterFeatureBitMask
);
614 CpuFeatureEntry
->CoreAfterFeatureBitMask
= CpuFeature
->CoreAfterFeatureBitMask
;
616 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
617 if (CpuFeatureEntry
->PackageBeforeFeatureBitMask
!= NULL
) {
618 FreePool (CpuFeatureEntry
->PackageBeforeFeatureBitMask
);
620 CpuFeatureEntry
->PackageBeforeFeatureBitMask
= CpuFeature
->PackageBeforeFeatureBitMask
;
622 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
623 if (CpuFeatureEntry
->PackageAfterFeatureBitMask
!= NULL
) {
624 FreePool (CpuFeatureEntry
->PackageAfterFeatureBitMask
);
626 CpuFeatureEntry
->PackageAfterFeatureBitMask
= CpuFeature
->PackageAfterFeatureBitMask
;
629 CpuFeatureEntry
->BeforeAll
= CpuFeature
->BeforeAll
;
630 CpuFeatureEntry
->AfterAll
= CpuFeature
->AfterAll
;
632 FreePool (CpuFeature
->FeatureMask
);
633 FreePool (CpuFeature
);
636 // Verify CPU features dependency can change CPU feature order
638 CheckCpuFeaturesDependency (&CpuFeaturesData
->FeatureList
);
639 return RETURN_SUCCESS
;
643 Sets CPU feature bit mask in CPU feature bit mask buffer.
645 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
646 @param[in] Feature The bit number of the CPU feature
647 @param[in] BitMaskSize CPU feature bit mask buffer size
650 SetCpuFeaturesBitMask (
651 IN UINT8
**FeaturesBitMask
,
656 UINT8
*CpuFeaturesBitMask
;
658 ASSERT (FeaturesBitMask
!= NULL
);
659 CpuFeaturesBitMask
= *FeaturesBitMask
;
660 if (CpuFeaturesBitMask
== NULL
) {
661 CpuFeaturesBitMask
= AllocateZeroPool (BitMaskSize
);
662 ASSERT (CpuFeaturesBitMask
!= NULL
);
663 *FeaturesBitMask
= CpuFeaturesBitMask
;
666 CpuFeaturesBitMask
+= (Feature
/ 8);
667 *CpuFeaturesBitMask
|= (UINT8
) (1 << (Feature
% 8));
671 Registers a CPU Feature.
673 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
675 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
676 is an optional parameter that may be NULL. If NULL,
677 then the most recently registered function for the
678 CPU feature is used. If no functions are registered
679 for a CPU feature, then the CPU configuration data
680 for the registered feature is NULL.
681 @param[in] SupportFunc CPU feature support function. This is an optional
682 parameter that may be NULL. If NULL, then the most
683 recently registered function for the CPU feature is
684 used. If no functions are registered for a CPU
685 feature, then the CPU feature is assumed to be
686 supported by all CPUs.
687 @param[in] InitializeFunc CPU feature initialize function. This is an optional
688 parameter that may be NULL. If NULL, then the most
689 recently registered function for the CPU feature is
690 used. If no functions are registered for a CPU
691 feature, then the CPU feature initialization is
693 @param[in] ... Variable argument list of UINT32 CPU feature value.
694 Values with no modifiers are the features provided
695 by the registered functions.
696 Values with CPU_FEATURE_BEFORE modifier are features
697 that must be initialized after the features provided
698 by the registered functions are used.
699 Values with CPU_FEATURE_AFTER modifier are features
700 that must be initialized before the features provided
701 by the registered functions are used.
702 The last argument in this variable argument list must
703 always be CPU_FEATURE_END.
705 @retval RETURN_SUCCESS The CPU feature was successfully registered.
706 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
708 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
709 supported due to a circular dependency between
710 BEFORE and AFTER features.
711 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration
712 not updated by Platform driver yet.
714 @note This service could be called by BSP only.
719 IN CHAR8
*FeatureName
, OPTIONAL
720 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc
, OPTIONAL
721 IN CPU_FEATURE_SUPPORT SupportFunc
, OPTIONAL
722 IN CPU_FEATURE_INITIALIZE InitializeFunc
, OPTIONAL
730 CPU_FEATURES_ENTRY
*CpuFeature
;
732 UINT8
*BeforeFeatureBitMask
;
733 UINT8
*AfterFeatureBitMask
;
734 UINT8
*CoreBeforeFeatureBitMask
;
735 UINT8
*CoreAfterFeatureBitMask
;
736 UINT8
*PackageBeforeFeatureBitMask
;
737 UINT8
*PackageAfterFeatureBitMask
;
742 BeforeFeatureBitMask
= NULL
;
743 AfterFeatureBitMask
= NULL
;
744 CoreBeforeFeatureBitMask
= NULL
;
745 CoreAfterFeatureBitMask
= NULL
;
746 PackageBeforeFeatureBitMask
= NULL
;
747 PackageAfterFeatureBitMask
= NULL
;
751 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
753 VA_START (Marker
, InitializeFunc
);
754 Feature
= VA_ARG (Marker
, UINT32
);
755 while (Feature
!= CPU_FEATURE_END
) {
756 ASSERT ((Feature
& (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
))
757 != (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
));
758 ASSERT ((Feature
& (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
))
759 != (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
));
760 ASSERT ((Feature
& (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
))
761 != (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
));
762 ASSERT ((Feature
& (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
))
763 != (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
));
764 if (Feature
< CPU_FEATURE_BEFORE
) {
765 BeforeAll
= ((Feature
& CPU_FEATURE_BEFORE_ALL
) != 0) ? TRUE
: FALSE
;
766 AfterAll
= ((Feature
& CPU_FEATURE_AFTER_ALL
) != 0) ? TRUE
: FALSE
;
767 Feature
&= ~(CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
);
768 ASSERT (FeatureMask
== NULL
);
769 SetCpuFeaturesBitMask (&FeatureMask
, Feature
, BitMaskSize
);
770 } else if ((Feature
& CPU_FEATURE_BEFORE
) != 0) {
771 SetCpuFeaturesBitMask (&BeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_BEFORE
, BitMaskSize
);
772 } else if ((Feature
& CPU_FEATURE_AFTER
) != 0) {
773 SetCpuFeaturesBitMask (&AfterFeatureBitMask
, Feature
& ~CPU_FEATURE_AFTER
, BitMaskSize
);
774 } else if ((Feature
& CPU_FEATURE_CORE_BEFORE
) != 0) {
775 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_BEFORE
, BitMaskSize
);
776 } else if ((Feature
& CPU_FEATURE_CORE_AFTER
) != 0) {
777 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_AFTER
, BitMaskSize
);
778 } else if ((Feature
& CPU_FEATURE_PACKAGE_BEFORE
) != 0) {
779 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_BEFORE
, BitMaskSize
);
780 } else if ((Feature
& CPU_FEATURE_PACKAGE_AFTER
) != 0) {
781 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_AFTER
, BitMaskSize
);
783 Feature
= VA_ARG (Marker
, UINT32
);
787 CpuFeature
= AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY
));
788 ASSERT (CpuFeature
!= NULL
);
789 CpuFeature
->Signature
= CPU_FEATURE_ENTRY_SIGNATURE
;
790 CpuFeature
->FeatureMask
= FeatureMask
;
791 CpuFeature
->BeforeFeatureBitMask
= BeforeFeatureBitMask
;
792 CpuFeature
->AfterFeatureBitMask
= AfterFeatureBitMask
;
793 CpuFeature
->CoreBeforeFeatureBitMask
= CoreBeforeFeatureBitMask
;
794 CpuFeature
->CoreAfterFeatureBitMask
= CoreAfterFeatureBitMask
;
795 CpuFeature
->PackageBeforeFeatureBitMask
= PackageBeforeFeatureBitMask
;
796 CpuFeature
->PackageAfterFeatureBitMask
= PackageAfterFeatureBitMask
;
797 CpuFeature
->BeforeAll
= BeforeAll
;
798 CpuFeature
->AfterAll
= AfterAll
;
799 CpuFeature
->GetConfigDataFunc
= GetConfigDataFunc
;
800 CpuFeature
->SupportFunc
= SupportFunc
;
801 CpuFeature
->InitializeFunc
= InitializeFunc
;
802 if (FeatureName
!= NULL
) {
803 CpuFeature
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
804 ASSERT (CpuFeature
->FeatureName
!= NULL
);
805 Status
= AsciiStrCpyS (CpuFeature
->FeatureName
, CPU_FEATURE_NAME_SIZE
, FeatureName
);
806 ASSERT_EFI_ERROR (Status
);
809 Status
= RegisterCpuFeatureWorker (CpuFeature
);
810 ASSERT_EFI_ERROR (Status
);
812 return RETURN_SUCCESS
;
816 Return ACPI_CPU_DATA data.
818 @return Pointer to ACPI_CPU_DATA data.
827 UINTN NumberOfEnabledProcessors
;
828 ACPI_CPU_DATA
*AcpiCpuData
;
830 CPU_REGISTER_TABLE
*RegisterTable
;
832 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
834 AcpiCpuData
= (ACPI_CPU_DATA
*) (UINTN
) PcdGet64 (PcdCpuS3DataAddress
);
835 if (AcpiCpuData
!= NULL
) {
839 AcpiCpuData
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA
)));
840 ASSERT (AcpiCpuData
!= NULL
);
843 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
845 Status
= PcdSet64S (PcdCpuS3DataAddress
, (UINT64
)(UINTN
)AcpiCpuData
);
846 ASSERT_EFI_ERROR (Status
);
848 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
849 AcpiCpuData
->NumberOfCpus
= (UINT32
)NumberOfCpus
;
852 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
854 TableSize
= 2 * NumberOfCpus
* sizeof (CPU_REGISTER_TABLE
);
855 RegisterTable
= AllocatePages (EFI_SIZE_TO_PAGES (TableSize
));
856 ASSERT (RegisterTable
!= NULL
);
858 for (Index
= 0; Index
< NumberOfCpus
; Index
++) {
859 Status
= GetProcessorInformation (Index
, &ProcessorInfoBuffer
);
860 ASSERT_EFI_ERROR (Status
);
862 RegisterTable
[Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
863 RegisterTable
[Index
].TableLength
= 0;
864 RegisterTable
[Index
].AllocatedSize
= 0;
865 RegisterTable
[Index
].RegisterTableEntry
= 0;
867 RegisterTable
[NumberOfCpus
+ Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
868 RegisterTable
[NumberOfCpus
+ Index
].TableLength
= 0;
869 RegisterTable
[NumberOfCpus
+ Index
].AllocatedSize
= 0;
870 RegisterTable
[NumberOfCpus
+ Index
].RegisterTableEntry
= 0;
872 AcpiCpuData
->RegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RegisterTable
;
873 AcpiCpuData
->PreSmmInitRegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(RegisterTable
+ NumberOfCpus
);
879 Enlarges CPU register table for each processor.
881 @param[in, out] RegisterTable Pointer processor's CPU register table
885 EnlargeRegisterTable (
886 IN OUT CPU_REGISTER_TABLE
*RegisterTable
889 EFI_PHYSICAL_ADDRESS Address
;
892 UsedPages
= RegisterTable
->AllocatedSize
/ EFI_PAGE_SIZE
;
893 Address
= (UINTN
)AllocatePages (UsedPages
+ 1);
894 ASSERT (Address
!= 0);
897 // If there are records existing in the register table, then copy its contents
898 // to new region and free the old one.
900 if (RegisterTable
->AllocatedSize
> 0) {
902 (VOID
*) (UINTN
) Address
,
903 (VOID
*) (UINTN
) RegisterTable
->RegisterTableEntry
,
904 RegisterTable
->AllocatedSize
907 FreePages ((VOID
*)(UINTN
)RegisterTable
->RegisterTableEntry
, UsedPages
);
911 // Adjust the allocated size and register table base address.
913 RegisterTable
->AllocatedSize
+= EFI_PAGE_SIZE
;
914 RegisterTable
->RegisterTableEntry
= Address
;
918 Add an entry in specified register table.
920 This function adds an entry in specified register table, with given register type,
921 register index, bit section and value.
923 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
924 If FALSE, entry will be added into register table
925 @param[in] ProcessorNumber The index of the CPU to add a register table entry
926 @param[in] RegisterType Type of the register to program
927 @param[in] Index Index of the register to program
928 @param[in] ValidBitStart Start of the bit section
929 @param[in] ValidBitLength Length of the bit section
930 @param[in] Value Value to write
933 CpuRegisterTableWriteWorker (
934 IN BOOLEAN PreSmmFlag
,
935 IN UINTN ProcessorNumber
,
936 IN REGISTER_TYPE RegisterType
,
938 IN UINT8 ValidBitStart
,
939 IN UINT8 ValidBitLength
,
943 CPU_FEATURES_DATA
*CpuFeaturesData
;
944 ACPI_CPU_DATA
*AcpiCpuData
;
945 CPU_REGISTER_TABLE
*RegisterTable
;
946 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
948 CpuFeaturesData
= GetCpuFeaturesData ();
949 if (CpuFeaturesData
->RegisterTable
== NULL
) {
950 AcpiCpuData
= GetAcpiCpuData ();
951 ASSERT ((AcpiCpuData
!= NULL
) && (AcpiCpuData
->RegisterTable
!= 0));
952 CpuFeaturesData
->RegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->RegisterTable
;
953 CpuFeaturesData
->PreSmmRegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->PreSmmInitRegisterTable
;
957 RegisterTable
= &CpuFeaturesData
->PreSmmRegisterTable
[ProcessorNumber
];
959 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
962 if (RegisterTable
->TableLength
== RegisterTable
->AllocatedSize
/ sizeof (CPU_REGISTER_TABLE_ENTRY
)) {
963 EnlargeRegisterTable (RegisterTable
);
967 // Append entry in the register table.
969 RegisterTableEntry
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
970 RegisterTableEntry
[RegisterTable
->TableLength
].RegisterType
= RegisterType
;
971 RegisterTableEntry
[RegisterTable
->TableLength
].Index
= (UINT32
) Index
;
972 RegisterTableEntry
[RegisterTable
->TableLength
].HighIndex
= (UINT32
) RShiftU64 (Index
, 32);
973 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitStart
= ValidBitStart
;
974 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitLength
= ValidBitLength
;
975 RegisterTableEntry
[RegisterTable
->TableLength
].Value
= Value
;
977 RegisterTable
->TableLength
++;
981 Adds an entry in specified register table.
983 This function adds an entry in specified register table, with given register type,
984 register index, bit section and value.
986 @param[in] ProcessorNumber The index of the CPU to add a register table entry
987 @param[in] RegisterType Type of the register to program
988 @param[in] Index Index of the register to program
989 @param[in] ValueMask Mask of bits in register to write
990 @param[in] Value Value to write
992 @note This service could be called by BSP only.
996 CpuRegisterTableWrite (
997 IN UINTN ProcessorNumber
,
998 IN REGISTER_TYPE RegisterType
,
1000 IN UINT64 ValueMask
,
1008 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1009 End
= (UINT8
)HighBitSet64 (ValueMask
);
1010 Length
= End
- Start
+ 1;
1011 CpuRegisterTableWriteWorker (FALSE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1015 Adds an entry in specified Pre-SMM register table.
1017 This function adds an entry in specified register table, with given register type,
1018 register index, bit section and value.
1020 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
1021 @param[in] RegisterType Type of the register to program
1022 @param[in] Index Index of the register to program
1023 @param[in] ValueMask Mask of bits in register to write
1024 @param[in] Value Value to write
1026 @note This service could be called by BSP only.
1030 PreSmmCpuRegisterTableWrite (
1031 IN UINTN ProcessorNumber
,
1032 IN REGISTER_TYPE RegisterType
,
1034 IN UINT64 ValueMask
,
1042 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1043 End
= (UINT8
)HighBitSet64 (ValueMask
);
1044 Length
= End
- Start
+ 1;
1045 CpuRegisterTableWriteWorker (TRUE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1049 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1051 @param[in] CpuBitMask CPU feature bit mask buffer
1052 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
1053 @param[in] Feature The bit number of the CPU feature
1055 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1056 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1060 IsCpuFeatureSetInCpuPcd (
1061 IN UINT8
*CpuBitMask
,
1062 IN UINTN CpuBitMaskSize
,
1066 if ((Feature
>> 3) >= CpuBitMaskSize
) {
1069 return ((*(CpuBitMask
+ (Feature
>> 3)) & (1 << (Feature
& 0x07))) != 0);
1073 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
1074 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
1075 associated with that feature should be optimized away if compiler
1076 optimizations are enabled.
1078 @param[in] Feature The bit number of the CPU feature to check in the PCD
1079 PcdCpuFeaturesSupport
1081 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1082 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1084 @note This service could be called by BSP only.
1088 IsCpuFeatureSupported (
1092 return IsCpuFeatureSetInCpuPcd (
1093 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSupport
),
1094 PcdGetSize (PcdCpuFeaturesSupport
),
1100 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1102 @param[in] Feature The bit number of the CPU feature to check in the PCD
1103 PcdCpuFeaturesSetting
1105 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1106 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1108 @note This service could be called by BSP only.
1112 IsCpuFeatureInSetting (
1116 return IsCpuFeatureSetInCpuPcd (
1117 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSetting
),
1118 PcdGetSize (PcdCpuFeaturesSetting
),
1124 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
1126 @param[in] Feature The bit number of the CPU feature to check in the PCD
1127 PcdCpuFeaturesCapability
1129 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
1130 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
1132 @note This service could be called by BSP only.
1136 IsCpuFeatureCapability (
1140 return IsCpuFeatureSetInCpuPcd (
1141 (UINT8
*)PcdGetPtr (PcdCpuFeaturesCapability
),
1142 PcdGetSize (PcdCpuFeaturesCapability
),
1149 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
1151 @param[in] Feature The bit number of the CPU feature to check in the PCD
1152 PcdCpuFeaturesUserConfiguration
1154 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
1155 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
1157 @note This service could be called by BSP only.
1161 IsCpuFeatureUserConfiguration (
1165 return IsCpuFeatureSetInCpuPcd (
1166 (UINT8
*)PcdGetPtr (PcdCpuFeaturesUserConfiguration
),
1167 PcdGetSize (PcdCpuFeaturesUserConfiguration
),
1174 Switches to assigned BSP after CPU features initialization.
1176 @param[in] ProcessorNumber The index of the CPU executing this function.
1178 @note This service could be called by BSP only.
1182 SwitchBspAfterFeaturesInitialize (
1183 IN UINTN ProcessorNumber
1186 CPU_FEATURES_DATA
*CpuFeaturesData
;
1188 CpuFeaturesData
= GetCpuFeaturesData ();
1189 CpuFeaturesData
->BspNumber
= ProcessorNumber
;