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.
121 @retval return the dependence result.
123 CPU_FEATURE_DEPENDENCE_TYPE
125 IN CPU_FEATURES_ENTRY
*CpuFeature
,
130 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
131 return PackageDepType
;
134 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
138 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
139 return ThreadDepType
;
145 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
146 return PackageDepType
;
149 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
153 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
154 return ThreadDepType
;
161 Clear dependence for the specified type.
163 @param[in] CurrentFeature Cpu feature need to clear.
164 @param[in] Before Before or after dependence relationship.
169 IN CPU_FEATURES_ENTRY
*CpuFeature
,
174 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
175 FreePool (CpuFeature
->BeforeFeatureBitMask
);
176 CpuFeature
->BeforeFeatureBitMask
= NULL
;
178 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
179 FreePool (CpuFeature
->CoreBeforeFeatureBitMask
);
180 CpuFeature
->CoreBeforeFeatureBitMask
= NULL
;
182 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
183 FreePool (CpuFeature
->PackageBeforeFeatureBitMask
);
184 CpuFeature
->PackageBeforeFeatureBitMask
= NULL
;
187 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
188 FreePool (CpuFeature
->PackageAfterFeatureBitMask
);
189 CpuFeature
->PackageAfterFeatureBitMask
= NULL
;
191 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
192 FreePool (CpuFeature
->CoreAfterFeatureBitMask
);
193 CpuFeature
->CoreAfterFeatureBitMask
= NULL
;
195 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
196 FreePool (CpuFeature
->AfterFeatureBitMask
);
197 CpuFeature
->AfterFeatureBitMask
= NULL
;
203 Base on dependence relationship to asjust feature dependence.
205 ONLY when the feature before(or after) the find feature also has
206 dependence with the find feature. In this case, driver need to base
207 on dependce relationship to decide how to insert current feature and
208 adjust the feature dependence.
210 @param[in] PreviousFeature CPU feature current before the find one.
211 @param[in] CurrentFeature Cpu feature need to adjust.
212 @param[in] Before Before or after dependence relationship.
214 @retval TRUE means the current feature dependence has been adjusted.
216 @retval FALSE means the previous feature dependence has been adjusted.
217 or previous feature has no dependence with the find one.
221 AdjustFeaturesDependence (
222 IN OUT CPU_FEATURES_ENTRY
*PreviousFeature
,
223 IN OUT CPU_FEATURES_ENTRY
*CurrentFeature
,
227 CPU_FEATURE_DEPENDENCE_TYPE PreDependType
;
228 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType
;
230 PreDependType
= DetectFeatureScope(PreviousFeature
, Before
);
231 CurrentDependType
= DetectFeatureScope(CurrentFeature
, Before
);
234 // If previous feature has no dependence with the find featue.
237 if (PreDependType
== NoneDepType
) {
242 // If both feature have dependence, keep the one which needs use more
243 // processors and clear the dependence for the other one.
245 if (PreDependType
>= CurrentDependType
) {
246 ClearFeatureScope (CurrentFeature
, Before
);
249 ClearFeatureScope (PreviousFeature
, Before
);
255 Base on dependence relationship to asjust feature order.
257 @param[in] FeatureList Pointer to CPU feature list
258 @param[in] FindEntry The entry this feature depend on.
259 @param[in] CurrentEntry The entry for this feature.
260 @param[in] Before Before or after dependence relationship.
265 IN LIST_ENTRY
*FeatureList
,
266 IN OUT LIST_ENTRY
*FindEntry
,
267 IN OUT LIST_ENTRY
*CurrentEntry
,
271 LIST_ENTRY
*PreviousEntry
;
272 CPU_FEATURES_ENTRY
*PreviousFeature
;
273 CPU_FEATURES_ENTRY
*CurrentFeature
;
276 // For CPU feature which has core or package type dependence, later code need to insert
277 // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.
278 // So if driver finds both feature A and B need to execute before feature C, driver will
279 // base on dependence type of feature A and B to update the logic here.
280 // For example, feature A has package type dependence and feature B has core type dependence,
281 // because package type dependence need to wait for more processors which has strong dependence
282 // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver
283 // will remove the feature dependence in feature B.
284 // Driver just needs to make sure before feature C been executed, feature A has finished its task
285 // in all all thread. Feature A finished in all threads also means feature B have finshed in all
289 PreviousEntry
= GetPreviousNode (FeatureList
, FindEntry
);
291 PreviousEntry
= GetNextNode (FeatureList
, FindEntry
);
294 CurrentFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
295 RemoveEntryList (CurrentEntry
);
297 if (IsNull (FeatureList
, PreviousEntry
)) {
299 // If not exist the previous or next entry, just insert the current entry.
302 InsertTailList (FindEntry
, CurrentEntry
);
304 InsertHeadList (FindEntry
, CurrentEntry
);
308 // If exist the previous or next entry, need to check it before insert curent entry.
310 PreviousFeature
= CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry
);
312 if (AdjustFeaturesDependence (PreviousFeature
, CurrentFeature
, Before
)) {
314 // Return TRUE means current feature dependence has been cleared and the previous
315 // feature dependence has been kept and used. So insert current feature before (or after)
316 // the previous feature.
319 InsertTailList (PreviousEntry
, CurrentEntry
);
321 InsertHeadList (PreviousEntry
, CurrentEntry
);
325 InsertTailList (FindEntry
, CurrentEntry
);
327 InsertHeadList (FindEntry
, CurrentEntry
);
334 Checks and adjusts current CPU features per dependency relationship.
336 @param[in] FeatureList Pointer to CPU feature list
337 @param[in] CurrentEntry Pointer to current checked CPU feature
338 @param[in] FeatureMask The feature bit mask.
340 @retval return Swapped info.
343 InsertToBeforeEntry (
344 IN LIST_ENTRY
*FeatureList
,
345 IN LIST_ENTRY
*CurrentEntry
,
346 IN UINT8
*FeatureMask
349 LIST_ENTRY
*CheckEntry
;
350 CPU_FEATURES_ENTRY
*CheckFeature
;
356 // Check all features dispatched before this entry
358 CheckEntry
= GetFirstNode (FeatureList
);
359 while (CheckEntry
!= CurrentEntry
) {
360 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
361 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
362 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, TRUE
);
366 CheckEntry
= CheckEntry
->ForwardLink
;
373 Checks and adjusts current CPU features per dependency relationship.
375 @param[in] FeatureList Pointer to CPU feature list
376 @param[in] CurrentEntry Pointer to current checked CPU feature
377 @param[in] FeatureMask The feature bit mask.
379 @retval return Swapped info.
383 IN LIST_ENTRY
*FeatureList
,
384 IN LIST_ENTRY
*CurrentEntry
,
385 IN UINT8
*FeatureMask
388 LIST_ENTRY
*CheckEntry
;
389 CPU_FEATURES_ENTRY
*CheckFeature
;
395 // Check all features dispatched after this entry
397 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
398 while (!IsNull (FeatureList
, CheckEntry
)) {
399 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
400 if (IsBitMaskMatchCheck (CheckFeature
->FeatureMask
, FeatureMask
)) {
401 AdjustEntry (FeatureList
, CheckEntry
, CurrentEntry
, FALSE
);
405 CheckEntry
= CheckEntry
->ForwardLink
;
412 Checks and adjusts CPU features order per dependency relationship.
414 @param[in] FeatureList Pointer to CPU feature list
417 CheckCpuFeaturesDependency (
418 IN LIST_ENTRY
*FeatureList
421 LIST_ENTRY
*CurrentEntry
;
422 CPU_FEATURES_ENTRY
*CpuFeature
;
423 LIST_ENTRY
*CheckEntry
;
424 CPU_FEATURES_ENTRY
*CheckFeature
;
426 LIST_ENTRY
*TempEntry
;
427 LIST_ENTRY
*NextEntry
;
429 CurrentEntry
= GetFirstNode (FeatureList
);
430 while (!IsNull (FeatureList
, CurrentEntry
)) {
432 CpuFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry
);
433 NextEntry
= CurrentEntry
->ForwardLink
;
434 if (CpuFeature
->BeforeAll
) {
436 // Check all features dispatched before this entry
438 CheckEntry
= GetFirstNode (FeatureList
);
439 while (CheckEntry
!= CurrentEntry
) {
440 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
441 if (!CheckFeature
->BeforeAll
) {
443 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
444 // insert currentEntry before Checked feature
446 RemoveEntryList (CurrentEntry
);
447 InsertTailList (CheckEntry
, CurrentEntry
);
451 CheckEntry
= CheckEntry
->ForwardLink
;
454 CurrentEntry
= NextEntry
;
459 if (CpuFeature
->AfterAll
) {
461 // Check all features dispatched after this entry
463 CheckEntry
= GetNextNode (FeatureList
, CurrentEntry
);
464 while (!IsNull (FeatureList
, CheckEntry
)) {
465 CheckFeature
= CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry
);
466 if (!CheckFeature
->AfterAll
) {
468 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
469 // insert currentEntry after Checked feature
471 TempEntry
= GetNextNode (FeatureList
, CurrentEntry
);
472 RemoveEntryList (CurrentEntry
);
473 InsertHeadList (CheckEntry
, CurrentEntry
);
474 CurrentEntry
= TempEntry
;
478 CheckEntry
= CheckEntry
->ForwardLink
;
481 CurrentEntry
= NextEntry
;
486 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
487 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->BeforeFeatureBitMask
);
489 CurrentEntry
= NextEntry
;
494 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
495 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->AfterFeatureBitMask
);
497 CurrentEntry
= NextEntry
;
502 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
503 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreBeforeFeatureBitMask
);
505 CurrentEntry
= NextEntry
;
510 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
511 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->CoreAfterFeatureBitMask
);
513 CurrentEntry
= NextEntry
;
518 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
519 Swapped
= InsertToBeforeEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageBeforeFeatureBitMask
);
521 CurrentEntry
= NextEntry
;
526 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
527 Swapped
= InsertToAfterEntry (FeatureList
, CurrentEntry
, CpuFeature
->PackageAfterFeatureBitMask
);
529 CurrentEntry
= NextEntry
;
534 CurrentEntry
= CurrentEntry
->ForwardLink
;
539 Worker function to register CPU Feature.
541 @param[in] CpuFeature Pointer to CPU feature entry
543 @retval RETURN_SUCCESS The CPU feature was successfully registered.
544 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
546 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
547 supported due to a circular dependency between
548 BEFORE and AFTER features.
551 RegisterCpuFeatureWorker (
552 IN CPU_FEATURES_ENTRY
*CpuFeature
556 CPU_FEATURES_DATA
*CpuFeaturesData
;
557 CPU_FEATURES_ENTRY
*CpuFeatureEntry
;
560 BOOLEAN FeatureExist
;
562 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
563 CpuFeaturesData
= GetCpuFeaturesData ();
564 if (CpuFeaturesData
->FeaturesCount
== 0) {
565 InitializeListHead (&CpuFeaturesData
->FeatureList
);
566 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.MemoryMappedLock
);
567 InitializeSpinLock (&CpuFeaturesData
->CpuFlags
.ConsoleLogLock
);
568 CpuFeaturesData
->BitMaskSize
= (UINT32
) BitMaskSize
;
570 ASSERT (CpuFeaturesData
->BitMaskSize
== BitMaskSize
);
572 FeatureExist
= FALSE
;
573 CpuFeatureEntry
= NULL
;
574 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
575 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
576 CpuFeatureEntry
= CPU_FEATURE_ENTRY_FROM_LINK (Entry
);
577 if (IsCpuFeatureMatch (CpuFeature
->FeatureMask
, CpuFeatureEntry
->FeatureMask
)) {
579 // If this feature already registered
584 Entry
= Entry
->ForwardLink
;
588 DEBUG ((DEBUG_INFO
, "[NEW] "));
589 DumpCpuFeature (CpuFeature
);
590 InsertTailList (&CpuFeaturesData
->FeatureList
, &CpuFeature
->Link
);
591 CpuFeaturesData
->FeaturesCount
++;
593 DEBUG ((DEBUG_INFO
, "[OVERRIDE] "));
594 DumpCpuFeature (CpuFeature
);
595 ASSERT (CpuFeatureEntry
!= NULL
);
597 // Overwrite original parameters of CPU feature
599 if (CpuFeature
->GetConfigDataFunc
!= NULL
) {
600 CpuFeatureEntry
->GetConfigDataFunc
= CpuFeature
->GetConfigDataFunc
;
602 if (CpuFeature
->SupportFunc
!= NULL
) {
603 CpuFeatureEntry
->SupportFunc
= CpuFeature
->SupportFunc
;
605 if (CpuFeature
->InitializeFunc
!= NULL
) {
606 CpuFeatureEntry
->InitializeFunc
= CpuFeature
->InitializeFunc
;
608 if (CpuFeature
->FeatureName
!= NULL
) {
609 if (CpuFeatureEntry
->FeatureName
== NULL
) {
610 CpuFeatureEntry
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
611 ASSERT (CpuFeatureEntry
->FeatureName
!= NULL
);
613 Status
= AsciiStrCpyS (CpuFeatureEntry
->FeatureName
, CPU_FEATURE_NAME_SIZE
, CpuFeature
->FeatureName
);
614 ASSERT_EFI_ERROR (Status
);
615 FreePool (CpuFeature
->FeatureName
);
617 if (CpuFeature
->BeforeFeatureBitMask
!= NULL
) {
618 if (CpuFeatureEntry
->BeforeFeatureBitMask
!= NULL
) {
619 FreePool (CpuFeatureEntry
->BeforeFeatureBitMask
);
621 CpuFeatureEntry
->BeforeFeatureBitMask
= CpuFeature
->BeforeFeatureBitMask
;
623 if (CpuFeature
->AfterFeatureBitMask
!= NULL
) {
624 if (CpuFeatureEntry
->AfterFeatureBitMask
!= NULL
) {
625 FreePool (CpuFeatureEntry
->AfterFeatureBitMask
);
627 CpuFeatureEntry
->AfterFeatureBitMask
= CpuFeature
->AfterFeatureBitMask
;
629 if (CpuFeature
->CoreBeforeFeatureBitMask
!= NULL
) {
630 if (CpuFeatureEntry
->CoreBeforeFeatureBitMask
!= NULL
) {
631 FreePool (CpuFeatureEntry
->CoreBeforeFeatureBitMask
);
633 CpuFeatureEntry
->CoreBeforeFeatureBitMask
= CpuFeature
->CoreBeforeFeatureBitMask
;
635 if (CpuFeature
->CoreAfterFeatureBitMask
!= NULL
) {
636 if (CpuFeatureEntry
->CoreAfterFeatureBitMask
!= NULL
) {
637 FreePool (CpuFeatureEntry
->CoreAfterFeatureBitMask
);
639 CpuFeatureEntry
->CoreAfterFeatureBitMask
= CpuFeature
->CoreAfterFeatureBitMask
;
641 if (CpuFeature
->PackageBeforeFeatureBitMask
!= NULL
) {
642 if (CpuFeatureEntry
->PackageBeforeFeatureBitMask
!= NULL
) {
643 FreePool (CpuFeatureEntry
->PackageBeforeFeatureBitMask
);
645 CpuFeatureEntry
->PackageBeforeFeatureBitMask
= CpuFeature
->PackageBeforeFeatureBitMask
;
647 if (CpuFeature
->PackageAfterFeatureBitMask
!= NULL
) {
648 if (CpuFeatureEntry
->PackageAfterFeatureBitMask
!= NULL
) {
649 FreePool (CpuFeatureEntry
->PackageAfterFeatureBitMask
);
651 CpuFeatureEntry
->PackageAfterFeatureBitMask
= CpuFeature
->PackageAfterFeatureBitMask
;
654 CpuFeatureEntry
->BeforeAll
= CpuFeature
->BeforeAll
;
655 CpuFeatureEntry
->AfterAll
= CpuFeature
->AfterAll
;
657 FreePool (CpuFeature
->FeatureMask
);
658 FreePool (CpuFeature
);
661 // Verify CPU features dependency can change CPU feature order
663 CheckCpuFeaturesDependency (&CpuFeaturesData
->FeatureList
);
664 return RETURN_SUCCESS
;
668 Sets CPU feature bit mask in CPU feature bit mask buffer.
670 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
671 @param[in] Feature The bit number of the CPU feature
672 @param[in] BitMaskSize CPU feature bit mask buffer size
675 SetCpuFeaturesBitMask (
676 IN UINT8
**FeaturesBitMask
,
681 UINT8
*CpuFeaturesBitMask
;
683 ASSERT (FeaturesBitMask
!= NULL
);
684 CpuFeaturesBitMask
= *FeaturesBitMask
;
685 if (CpuFeaturesBitMask
== NULL
) {
686 CpuFeaturesBitMask
= AllocateZeroPool (BitMaskSize
);
687 ASSERT (CpuFeaturesBitMask
!= NULL
);
688 *FeaturesBitMask
= CpuFeaturesBitMask
;
691 CpuFeaturesBitMask
+= (Feature
/ 8);
692 *CpuFeaturesBitMask
|= (UINT8
) (1 << (Feature
% 8));
696 Registers a CPU Feature.
698 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
700 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
701 is an optional parameter that may be NULL. If NULL,
702 then the most recently registered function for the
703 CPU feature is used. If no functions are registered
704 for a CPU feature, then the CPU configuration data
705 for the registered feature is NULL.
706 @param[in] SupportFunc CPU feature support function. This is an optional
707 parameter that may be NULL. If NULL, then the most
708 recently registered function for the CPU feature is
709 used. If no functions are registered for a CPU
710 feature, then the CPU feature is assumed to be
711 supported by all CPUs.
712 @param[in] InitializeFunc CPU feature initialize function. This is an optional
713 parameter that may be NULL. If NULL, then the most
714 recently registered function for the CPU feature is
715 used. If no functions are registered for a CPU
716 feature, then the CPU feature initialization is
718 @param[in] ... Variable argument list of UINT32 CPU feature value.
719 Values with no modifiers are the features provided
720 by the registered functions.
721 Values with CPU_FEATURE_BEFORE modifier are features
722 that must be initialized after the features provided
723 by the registered functions are used.
724 Values with CPU_FEATURE_AFTER modifier are features
725 that must be initialized before the features provided
726 by the registered functions are used.
727 The last argument in this variable argument list must
728 always be CPU_FEATURE_END.
730 @retval RETURN_SUCCESS The CPU feature was successfully registered.
731 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
733 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
734 supported due to a circular dependency between
735 BEFORE and AFTER features.
736 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration
737 not updated by Platform driver yet.
739 @note This service could be called by BSP only.
744 IN CHAR8
*FeatureName
, OPTIONAL
745 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc
, OPTIONAL
746 IN CPU_FEATURE_SUPPORT SupportFunc
, OPTIONAL
747 IN CPU_FEATURE_INITIALIZE InitializeFunc
, OPTIONAL
755 CPU_FEATURES_ENTRY
*CpuFeature
;
757 UINT8
*BeforeFeatureBitMask
;
758 UINT8
*AfterFeatureBitMask
;
759 UINT8
*CoreBeforeFeatureBitMask
;
760 UINT8
*CoreAfterFeatureBitMask
;
761 UINT8
*PackageBeforeFeatureBitMask
;
762 UINT8
*PackageAfterFeatureBitMask
;
767 BeforeFeatureBitMask
= NULL
;
768 AfterFeatureBitMask
= NULL
;
769 CoreBeforeFeatureBitMask
= NULL
;
770 CoreAfterFeatureBitMask
= NULL
;
771 PackageBeforeFeatureBitMask
= NULL
;
772 PackageAfterFeatureBitMask
= NULL
;
776 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
778 VA_START (Marker
, InitializeFunc
);
779 Feature
= VA_ARG (Marker
, UINT32
);
780 while (Feature
!= CPU_FEATURE_END
) {
781 ASSERT ((Feature
& (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
))
782 != (CPU_FEATURE_BEFORE
| CPU_FEATURE_AFTER
));
783 ASSERT ((Feature
& (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
))
784 != (CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
));
785 ASSERT ((Feature
& (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
))
786 != (CPU_FEATURE_CORE_BEFORE
| CPU_FEATURE_CORE_AFTER
));
787 ASSERT ((Feature
& (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
))
788 != (CPU_FEATURE_PACKAGE_BEFORE
| CPU_FEATURE_PACKAGE_AFTER
));
789 if (Feature
< CPU_FEATURE_BEFORE
) {
790 BeforeAll
= ((Feature
& CPU_FEATURE_BEFORE_ALL
) != 0) ? TRUE
: FALSE
;
791 AfterAll
= ((Feature
& CPU_FEATURE_AFTER_ALL
) != 0) ? TRUE
: FALSE
;
792 Feature
&= ~(CPU_FEATURE_BEFORE_ALL
| CPU_FEATURE_AFTER_ALL
);
793 ASSERT (FeatureMask
== NULL
);
794 SetCpuFeaturesBitMask (&FeatureMask
, Feature
, BitMaskSize
);
795 } else if ((Feature
& CPU_FEATURE_BEFORE
) != 0) {
796 SetCpuFeaturesBitMask (&BeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_BEFORE
, BitMaskSize
);
797 } else if ((Feature
& CPU_FEATURE_AFTER
) != 0) {
798 SetCpuFeaturesBitMask (&AfterFeatureBitMask
, Feature
& ~CPU_FEATURE_AFTER
, BitMaskSize
);
799 } else if ((Feature
& CPU_FEATURE_CORE_BEFORE
) != 0) {
800 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_BEFORE
, BitMaskSize
);
801 } else if ((Feature
& CPU_FEATURE_CORE_AFTER
) != 0) {
802 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_CORE_AFTER
, BitMaskSize
);
803 } else if ((Feature
& CPU_FEATURE_PACKAGE_BEFORE
) != 0) {
804 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_BEFORE
, BitMaskSize
);
805 } else if ((Feature
& CPU_FEATURE_PACKAGE_AFTER
) != 0) {
806 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask
, Feature
& ~CPU_FEATURE_PACKAGE_AFTER
, BitMaskSize
);
808 Feature
= VA_ARG (Marker
, UINT32
);
812 CpuFeature
= AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY
));
813 ASSERT (CpuFeature
!= NULL
);
814 CpuFeature
->Signature
= CPU_FEATURE_ENTRY_SIGNATURE
;
815 CpuFeature
->FeatureMask
= FeatureMask
;
816 CpuFeature
->BeforeFeatureBitMask
= BeforeFeatureBitMask
;
817 CpuFeature
->AfterFeatureBitMask
= AfterFeatureBitMask
;
818 CpuFeature
->CoreBeforeFeatureBitMask
= CoreBeforeFeatureBitMask
;
819 CpuFeature
->CoreAfterFeatureBitMask
= CoreAfterFeatureBitMask
;
820 CpuFeature
->PackageBeforeFeatureBitMask
= PackageBeforeFeatureBitMask
;
821 CpuFeature
->PackageAfterFeatureBitMask
= PackageAfterFeatureBitMask
;
822 CpuFeature
->BeforeAll
= BeforeAll
;
823 CpuFeature
->AfterAll
= AfterAll
;
824 CpuFeature
->GetConfigDataFunc
= GetConfigDataFunc
;
825 CpuFeature
->SupportFunc
= SupportFunc
;
826 CpuFeature
->InitializeFunc
= InitializeFunc
;
827 if (FeatureName
!= NULL
) {
828 CpuFeature
->FeatureName
= AllocatePool (CPU_FEATURE_NAME_SIZE
);
829 ASSERT (CpuFeature
->FeatureName
!= NULL
);
830 Status
= AsciiStrCpyS (CpuFeature
->FeatureName
, CPU_FEATURE_NAME_SIZE
, FeatureName
);
831 ASSERT_EFI_ERROR (Status
);
834 Status
= RegisterCpuFeatureWorker (CpuFeature
);
835 ASSERT_EFI_ERROR (Status
);
837 return RETURN_SUCCESS
;
841 Return ACPI_CPU_DATA data.
843 @return Pointer to ACPI_CPU_DATA data.
852 UINTN NumberOfEnabledProcessors
;
853 ACPI_CPU_DATA
*AcpiCpuData
;
855 CPU_REGISTER_TABLE
*RegisterTable
;
857 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
859 AcpiCpuData
= (ACPI_CPU_DATA
*) (UINTN
) PcdGet64 (PcdCpuS3DataAddress
);
860 if (AcpiCpuData
!= NULL
) {
864 AcpiCpuData
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA
)));
865 ASSERT (AcpiCpuData
!= NULL
);
868 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
870 Status
= PcdSet64S (PcdCpuS3DataAddress
, (UINT64
)(UINTN
)AcpiCpuData
);
871 ASSERT_EFI_ERROR (Status
);
873 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
874 AcpiCpuData
->NumberOfCpus
= (UINT32
)NumberOfCpus
;
877 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
879 TableSize
= 2 * NumberOfCpus
* sizeof (CPU_REGISTER_TABLE
);
880 RegisterTable
= AllocatePages (EFI_SIZE_TO_PAGES (TableSize
));
881 ASSERT (RegisterTable
!= NULL
);
883 for (Index
= 0; Index
< NumberOfCpus
; Index
++) {
884 Status
= GetProcessorInformation (Index
, &ProcessorInfoBuffer
);
885 ASSERT_EFI_ERROR (Status
);
887 RegisterTable
[Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
888 RegisterTable
[Index
].TableLength
= 0;
889 RegisterTable
[Index
].AllocatedSize
= 0;
890 RegisterTable
[Index
].RegisterTableEntry
= 0;
892 RegisterTable
[NumberOfCpus
+ Index
].InitialApicId
= (UINT32
)ProcessorInfoBuffer
.ProcessorId
;
893 RegisterTable
[NumberOfCpus
+ Index
].TableLength
= 0;
894 RegisterTable
[NumberOfCpus
+ Index
].AllocatedSize
= 0;
895 RegisterTable
[NumberOfCpus
+ Index
].RegisterTableEntry
= 0;
897 AcpiCpuData
->RegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RegisterTable
;
898 AcpiCpuData
->PreSmmInitRegisterTable
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(RegisterTable
+ NumberOfCpus
);
904 Enlarges CPU register table for each processor.
906 @param[in, out] RegisterTable Pointer processor's CPU register table
910 EnlargeRegisterTable (
911 IN OUT CPU_REGISTER_TABLE
*RegisterTable
914 EFI_PHYSICAL_ADDRESS Address
;
917 UsedPages
= RegisterTable
->AllocatedSize
/ EFI_PAGE_SIZE
;
918 Address
= (UINTN
)AllocatePages (UsedPages
+ 1);
919 ASSERT (Address
!= 0);
922 // If there are records existing in the register table, then copy its contents
923 // to new region and free the old one.
925 if (RegisterTable
->AllocatedSize
> 0) {
927 (VOID
*) (UINTN
) Address
,
928 (VOID
*) (UINTN
) RegisterTable
->RegisterTableEntry
,
929 RegisterTable
->AllocatedSize
932 FreePages ((VOID
*)(UINTN
)RegisterTable
->RegisterTableEntry
, UsedPages
);
936 // Adjust the allocated size and register table base address.
938 RegisterTable
->AllocatedSize
+= EFI_PAGE_SIZE
;
939 RegisterTable
->RegisterTableEntry
= Address
;
943 Add an entry in specified register table.
945 This function adds an entry in specified register table, with given register type,
946 register index, bit section and value.
948 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
949 If FALSE, entry will be added into register table
950 @param[in] ProcessorNumber The index of the CPU to add a register table entry
951 @param[in] RegisterType Type of the register to program
952 @param[in] Index Index of the register to program
953 @param[in] ValidBitStart Start of the bit section
954 @param[in] ValidBitLength Length of the bit section
955 @param[in] Value Value to write
958 CpuRegisterTableWriteWorker (
959 IN BOOLEAN PreSmmFlag
,
960 IN UINTN ProcessorNumber
,
961 IN REGISTER_TYPE RegisterType
,
963 IN UINT8 ValidBitStart
,
964 IN UINT8 ValidBitLength
,
968 CPU_FEATURES_DATA
*CpuFeaturesData
;
969 ACPI_CPU_DATA
*AcpiCpuData
;
970 CPU_REGISTER_TABLE
*RegisterTable
;
971 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
973 CpuFeaturesData
= GetCpuFeaturesData ();
974 if (CpuFeaturesData
->RegisterTable
== NULL
) {
975 AcpiCpuData
= GetAcpiCpuData ();
976 ASSERT ((AcpiCpuData
!= NULL
) && (AcpiCpuData
->RegisterTable
!= 0));
977 CpuFeaturesData
->RegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->RegisterTable
;
978 CpuFeaturesData
->PreSmmRegisterTable
= (CPU_REGISTER_TABLE
*) (UINTN
) AcpiCpuData
->PreSmmInitRegisterTable
;
982 RegisterTable
= &CpuFeaturesData
->PreSmmRegisterTable
[ProcessorNumber
];
984 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
987 if (RegisterTable
->TableLength
== RegisterTable
->AllocatedSize
/ sizeof (CPU_REGISTER_TABLE_ENTRY
)) {
988 EnlargeRegisterTable (RegisterTable
);
992 // Append entry in the register table.
994 RegisterTableEntry
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
995 RegisterTableEntry
[RegisterTable
->TableLength
].RegisterType
= RegisterType
;
996 RegisterTableEntry
[RegisterTable
->TableLength
].Index
= (UINT32
) Index
;
997 RegisterTableEntry
[RegisterTable
->TableLength
].HighIndex
= (UINT32
) RShiftU64 (Index
, 32);
998 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitStart
= ValidBitStart
;
999 RegisterTableEntry
[RegisterTable
->TableLength
].ValidBitLength
= ValidBitLength
;
1000 RegisterTableEntry
[RegisterTable
->TableLength
].Value
= Value
;
1002 RegisterTable
->TableLength
++;
1006 Adds an entry in specified register table.
1008 This function adds an entry in specified register table, with given register type,
1009 register index, bit section and value.
1011 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1012 @param[in] RegisterType Type of the register to program
1013 @param[in] Index Index of the register to program
1014 @param[in] ValueMask Mask of bits in register to write
1015 @param[in] Value Value to write
1017 @note This service could be called by BSP only.
1021 CpuRegisterTableWrite (
1022 IN UINTN ProcessorNumber
,
1023 IN REGISTER_TYPE RegisterType
,
1025 IN UINT64 ValueMask
,
1033 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1034 End
= (UINT8
)HighBitSet64 (ValueMask
);
1035 Length
= End
- Start
+ 1;
1036 CpuRegisterTableWriteWorker (FALSE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1040 Adds an entry in specified Pre-SMM 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] ProcessorNumber The index of the CPU to add a register table entry.
1046 @param[in] RegisterType Type of the register to program
1047 @param[in] Index Index of the register to program
1048 @param[in] ValueMask Mask of bits in register to write
1049 @param[in] Value Value to write
1051 @note This service could be called by BSP only.
1055 PreSmmCpuRegisterTableWrite (
1056 IN UINTN ProcessorNumber
,
1057 IN REGISTER_TYPE RegisterType
,
1059 IN UINT64 ValueMask
,
1067 Start
= (UINT8
)LowBitSet64 (ValueMask
);
1068 End
= (UINT8
)HighBitSet64 (ValueMask
);
1069 Length
= End
- Start
+ 1;
1070 CpuRegisterTableWriteWorker (TRUE
, ProcessorNumber
, RegisterType
, Index
, Start
, Length
, Value
);
1074 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1076 @param[in] CpuBitMask CPU feature bit mask buffer
1077 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
1078 @param[in] Feature The bit number of the CPU feature
1080 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1081 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1085 IsCpuFeatureSetInCpuPcd (
1086 IN UINT8
*CpuBitMask
,
1087 IN UINTN CpuBitMaskSize
,
1091 if ((Feature
>> 3) >= CpuBitMaskSize
) {
1094 return ((*(CpuBitMask
+ (Feature
>> 3)) & (1 << (Feature
& 0x07))) != 0);
1098 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
1099 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
1100 associated with that feature should be optimized away if compiler
1101 optimizations are enabled.
1103 @param[in] Feature The bit number of the CPU feature to check in the PCD
1104 PcdCpuFeaturesSupport
1106 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1107 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1109 @note This service could be called by BSP only.
1113 IsCpuFeatureSupported (
1117 return IsCpuFeatureSetInCpuPcd (
1118 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSupport
),
1119 PcdGetSize (PcdCpuFeaturesSupport
),
1125 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1127 @param[in] Feature The bit number of the CPU feature to check in the PCD
1128 PcdCpuFeaturesSetting
1130 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1131 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1133 @note This service could be called by BSP only.
1137 IsCpuFeatureInSetting (
1141 return IsCpuFeatureSetInCpuPcd (
1142 (UINT8
*)PcdGetPtr (PcdCpuFeaturesSetting
),
1143 PcdGetSize (PcdCpuFeaturesSetting
),
1149 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
1151 @param[in] Feature The bit number of the CPU feature to check in the PCD
1152 PcdCpuFeaturesCapability
1154 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
1155 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
1157 @note This service could be called by BSP only.
1161 IsCpuFeatureCapability (
1165 return IsCpuFeatureSetInCpuPcd (
1166 (UINT8
*)PcdGetPtr (PcdCpuFeaturesCapability
),
1167 PcdGetSize (PcdCpuFeaturesCapability
),
1174 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
1176 @param[in] Feature The bit number of the CPU feature to check in the PCD
1177 PcdCpuFeaturesUserConfiguration
1179 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
1180 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
1182 @note This service could be called by BSP only.
1186 IsCpuFeatureUserConfiguration (
1190 return IsCpuFeatureSetInCpuPcd (
1191 (UINT8
*)PcdGetPtr (PcdCpuFeaturesUserConfiguration
),
1192 PcdGetSize (PcdCpuFeaturesUserConfiguration
),
1199 Switches to assigned BSP after CPU features initialization.
1201 @param[in] ProcessorNumber The index of the CPU executing this function.
1203 @note This service could be called by BSP only.
1207 SwitchBspAfterFeaturesInitialize (
1208 IN UINTN ProcessorNumber
1211 CPU_FEATURES_DATA
*CpuFeaturesData
;
1213 CpuFeaturesData
= GetCpuFeaturesData ();
1214 CpuFeaturesData
->BspNumber
= ProcessorNumber
;