]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
UefiCpuPkg/RegisterCpuFeaturesLib: Fix GCC build failure.
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / RegisterCpuFeaturesLib.c
1 /** @file
2 CPU Register Table Library functions.
3
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
9
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.
12
13 **/
14
15 #include "RegisterCpuFeatures.h"
16
17 /**
18 Checks if two CPU feature bit masks are equal.
19
20 @param[in] FirstFeatureMask The first input CPU feature bit mask
21 @param[in] SecondFeatureMask The second input CPU feature bit mask
22
23 @retval TRUE Two CPU feature bit masks are equal.
24 @retval FALSE Two CPU feature bit masks are not equal.
25 **/
26 BOOLEAN
27 IsCpuFeatureMatch (
28 IN UINT8 *FirstFeatureMask,
29 IN UINT8 *SecondFeatureMask
30 )
31 {
32 UINTN BitMaskSize;
33
34 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
35 if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) {
36 return TRUE;
37 } else {
38 return FALSE;
39 }
40 }
41
42 /**
43 Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
44
45 @param[in] FeatureMask A pointer to the CPU feature bit mask.
46 **/
47 VOID
48 DumpCpuFeatureMask (
49 IN UINT8 *FeatureMask
50 )
51 {
52 UINTN Index;
53 UINT8 *Data8;
54 UINTN BitMaskSize;
55
56 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
57 Data8 = (UINT8 *) FeatureMask;
58 for (Index = 0; Index < BitMaskSize; Index++) {
59 DEBUG ((DEBUG_INFO, " %02x ", *Data8++));
60 }
61 DEBUG ((DEBUG_INFO, "\n"));
62 }
63
64 /**
65 Dump CPU feature name or CPU feature bit mask.
66
67 @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY
68 **/
69 VOID
70 DumpCpuFeature (
71 IN CPU_FEATURES_ENTRY *CpuFeature
72 )
73 {
74
75 if (CpuFeature->FeatureName != NULL) {
76 DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName));
77 } else {
78 DEBUG ((DEBUG_INFO, "FeatureMask = "));
79 DumpCpuFeatureMask (CpuFeature->FeatureMask);
80 }
81 }
82
83 /**
84 Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
85
86 @param[in] FeatureMask Pointer to CPU feature bit mask
87 @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer
88
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.
91 **/
92 BOOLEAN
93 IsBitMaskMatchCheck (
94 IN UINT8 *FeatureMask,
95 IN UINT8 *DependentBitMask
96 )
97 {
98 UINTN Index;
99 UINTN BitMaskSize;
100 UINT8 *Data1;
101 UINT8 *Data2;
102
103 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
104
105 Data1 = FeatureMask;
106 Data2 = DependentBitMask;
107 for (Index = 0; Index < BitMaskSize; Index++) {
108 if (((*(Data1++)) & (*(Data2++))) != 0) {
109 return TRUE;
110 }
111 }
112 return FALSE;
113 }
114
115 /**
116 Return feature dependence result.
117
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.
121
122 @retval return the dependence result.
123 **/
124 CPU_FEATURE_DEPENDENCE_TYPE
125 DetectFeatureScope (
126 IN CPU_FEATURES_ENTRY *CpuFeature,
127 IN BOOLEAN Before,
128 IN UINT8 *NextCpuFeatureMask
129 )
130 {
131 //
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.
139 //
140 if (NextCpuFeatureMask == NULL) {
141 return NoneDepType;
142 }
143
144 if (Before) {
145 if ((CpuFeature->PackageBeforeFeatureBitMask != NULL) &&
146 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageBeforeFeatureBitMask)) {
147 return PackageDepType;
148 }
149
150 if ((CpuFeature->CoreBeforeFeatureBitMask != NULL) &&
151 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreBeforeFeatureBitMask)) {
152 return CoreDepType;
153 }
154
155 if ((CpuFeature->BeforeFeatureBitMask != NULL) &&
156 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->BeforeFeatureBitMask)) {
157 return ThreadDepType;
158 }
159
160 return NoneDepType;
161 }
162
163 if ((CpuFeature->PackageAfterFeatureBitMask != NULL) &&
164 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageAfterFeatureBitMask)) {
165 return PackageDepType;
166 }
167
168 if ((CpuFeature->CoreAfterFeatureBitMask != NULL) &&
169 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreAfterFeatureBitMask)) {
170 return CoreDepType;
171 }
172
173 if ((CpuFeature->AfterFeatureBitMask != NULL) &&
174 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->AfterFeatureBitMask)) {
175 return ThreadDepType;
176 }
177
178 return NoneDepType;
179 }
180
181 /**
182 Base on dependence relationship to asjust feature dependence.
183
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.
188
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.
193
194 @retval TRUE means the current feature dependence has been adjusted.
195
196 @retval FALSE means the previous feature dependence has been adjusted.
197 or previous feature has no dependence with the find one.
198
199 **/
200 BOOLEAN
201 AdjustFeaturesDependence (
202 IN OUT CPU_FEATURES_ENTRY *PreviousFeature,
203 IN OUT CPU_FEATURES_ENTRY *CurrentFeature,
204 IN CPU_FEATURES_ENTRY *FindFeature,
205 IN BOOLEAN Before
206 )
207 {
208 CPU_FEATURE_DEPENDENCE_TYPE PreDependType;
209 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType;
210
211 PreDependType = DetectFeatureScope(PreviousFeature, Before, FindFeature->FeatureMask);
212 CurrentDependType = DetectFeatureScope(CurrentFeature, Before, FindFeature->FeatureMask);
213
214 //
215 // If previous feature has no dependence with the find featue.
216 // return FALSE.
217 //
218 if (PreDependType == NoneDepType) {
219 return FALSE;
220 }
221
222 //
223 // If both feature have dependence, keep the one which needs use more
224 // processors and clear the dependence for the other one.
225 //
226 if (PreDependType >= CurrentDependType) {
227 return TRUE;
228 } else {
229 return FALSE;
230 }
231 }
232
233 /**
234 Base on dependence relationship to asjust feature order.
235
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.
240
241 **/
242 VOID
243 AdjustEntry (
244 IN LIST_ENTRY *FeatureList,
245 IN OUT LIST_ENTRY *FindEntry,
246 IN OUT LIST_ENTRY *CurrentEntry,
247 IN BOOLEAN Before
248 )
249 {
250 LIST_ENTRY *PreviousEntry;
251 CPU_FEATURES_ENTRY *PreviousFeature;
252 CPU_FEATURES_ENTRY *CurrentFeature;
253 CPU_FEATURES_ENTRY *FindFeature;
254
255 //
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
266 // threads.
267 //
268 if (Before) {
269 PreviousEntry = GetPreviousNode (FeatureList, FindEntry);
270 } else {
271 PreviousEntry = GetNextNode (FeatureList, FindEntry);
272 }
273
274 CurrentFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
275 RemoveEntryList (CurrentEntry);
276
277 if (IsNull (FeatureList, PreviousEntry)) {
278 //
279 // If not exist the previous or next entry, just insert the current entry.
280 //
281 if (Before) {
282 InsertTailList (FindEntry, CurrentEntry);
283 } else {
284 InsertHeadList (FindEntry, CurrentEntry);
285 }
286 } else {
287 //
288 // If exist the previous or next entry, need to check it before insert curent entry.
289 //
290 PreviousFeature = CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry);
291 FindFeature = CPU_FEATURE_ENTRY_FROM_LINK (FindEntry);
292
293 if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, FindFeature, Before)) {
294 //
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.
298 //
299 if (Before) {
300 InsertTailList (PreviousEntry, CurrentEntry);
301 } else {
302 InsertHeadList (PreviousEntry, CurrentEntry);
303 }
304 } else {
305 if (Before) {
306 InsertTailList (FindEntry, CurrentEntry);
307 } else {
308 InsertHeadList (FindEntry, CurrentEntry);
309 }
310 }
311 }
312 }
313
314 /**
315 Checks and adjusts current CPU features per dependency relationship.
316
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.
320
321 @retval return Swapped info.
322 **/
323 BOOLEAN
324 InsertToBeforeEntry (
325 IN LIST_ENTRY *FeatureList,
326 IN LIST_ENTRY *CurrentEntry,
327 IN UINT8 *FeatureMask
328 )
329 {
330 LIST_ENTRY *CheckEntry;
331 CPU_FEATURES_ENTRY *CheckFeature;
332 BOOLEAN Swapped;
333
334 Swapped = FALSE;
335
336 //
337 // Check all features dispatched before this entry
338 //
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);
344 Swapped = TRUE;
345 break;
346 }
347 CheckEntry = CheckEntry->ForwardLink;
348 }
349
350 return Swapped;
351 }
352
353 /**
354 Checks and adjusts current CPU features per dependency relationship.
355
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.
359
360 @retval return Swapped info.
361 **/
362 BOOLEAN
363 InsertToAfterEntry (
364 IN LIST_ENTRY *FeatureList,
365 IN LIST_ENTRY *CurrentEntry,
366 IN UINT8 *FeatureMask
367 )
368 {
369 LIST_ENTRY *CheckEntry;
370 CPU_FEATURES_ENTRY *CheckFeature;
371 BOOLEAN Swapped;
372
373 Swapped = FALSE;
374
375 //
376 // Check all features dispatched after this entry
377 //
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);
383 Swapped = TRUE;
384 break;
385 }
386 CheckEntry = CheckEntry->ForwardLink;
387 }
388
389 return Swapped;
390 }
391
392 /**
393 Checks and adjusts CPU features order per dependency relationship.
394
395 @param[in] FeatureList Pointer to CPU feature list
396 **/
397 VOID
398 CheckCpuFeaturesDependency (
399 IN LIST_ENTRY *FeatureList
400 )
401 {
402 LIST_ENTRY *CurrentEntry;
403 CPU_FEATURES_ENTRY *CpuFeature;
404 LIST_ENTRY *CheckEntry;
405 CPU_FEATURES_ENTRY *CheckFeature;
406 BOOLEAN Swapped;
407 LIST_ENTRY *TempEntry;
408 LIST_ENTRY *NextEntry;
409
410 CurrentEntry = GetFirstNode (FeatureList);
411 while (!IsNull (FeatureList, CurrentEntry)) {
412 Swapped = FALSE;
413 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
414 NextEntry = CurrentEntry->ForwardLink;
415 if (CpuFeature->BeforeAll) {
416 //
417 // Check all features dispatched before this entry
418 //
419 CheckEntry = GetFirstNode (FeatureList);
420 while (CheckEntry != CurrentEntry) {
421 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
422 if (!CheckFeature->BeforeAll) {
423 //
424 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
425 // insert currentEntry before Checked feature
426 //
427 RemoveEntryList (CurrentEntry);
428 InsertTailList (CheckEntry, CurrentEntry);
429 Swapped = TRUE;
430 break;
431 }
432 CheckEntry = CheckEntry->ForwardLink;
433 }
434 if (Swapped) {
435 CurrentEntry = NextEntry;
436 continue;
437 }
438 }
439
440 if (CpuFeature->AfterAll) {
441 //
442 // Check all features dispatched after this entry
443 //
444 CheckEntry = GetNextNode (FeatureList, CurrentEntry);
445 while (!IsNull (FeatureList, CheckEntry)) {
446 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
447 if (!CheckFeature->AfterAll) {
448 //
449 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
450 // insert currentEntry after Checked feature
451 //
452 TempEntry = GetNextNode (FeatureList, CurrentEntry);
453 RemoveEntryList (CurrentEntry);
454 InsertHeadList (CheckEntry, CurrentEntry);
455 CurrentEntry = TempEntry;
456 Swapped = TRUE;
457 break;
458 }
459 CheckEntry = CheckEntry->ForwardLink;
460 }
461 if (Swapped) {
462 CurrentEntry = NextEntry;
463 continue;
464 }
465 }
466
467 if (CpuFeature->BeforeFeatureBitMask != NULL) {
468 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->BeforeFeatureBitMask);
469 if (Swapped) {
470 continue;
471 }
472 }
473
474 if (CpuFeature->AfterFeatureBitMask != NULL) {
475 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->AfterFeatureBitMask);
476 if (Swapped) {
477 continue;
478 }
479 }
480
481 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
482 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->CoreBeforeFeatureBitMask);
483 if (Swapped) {
484 continue;
485 }
486 }
487
488 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
489 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->CoreAfterFeatureBitMask);
490 if (Swapped) {
491 continue;
492 }
493 }
494
495 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
496 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->PackageBeforeFeatureBitMask);
497 if (Swapped) {
498 continue;
499 }
500 }
501
502 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
503 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->PackageAfterFeatureBitMask);
504 if (Swapped) {
505 continue;
506 }
507 }
508
509 CurrentEntry = CurrentEntry->ForwardLink;
510 }
511 }
512
513 /**
514 Worker function to register CPU Feature.
515
516 @param[in] CpuFeature Pointer to CPU feature entry
517
518 @retval RETURN_SUCCESS The CPU feature was successfully registered.
519 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
520 the CPU feature.
521 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
522 supported due to a circular dependency between
523 BEFORE and AFTER features.
524 **/
525 RETURN_STATUS
526 RegisterCpuFeatureWorker (
527 IN CPU_FEATURES_ENTRY *CpuFeature
528 )
529 {
530 EFI_STATUS Status;
531 CPU_FEATURES_DATA *CpuFeaturesData;
532 CPU_FEATURES_ENTRY *CpuFeatureEntry;
533 LIST_ENTRY *Entry;
534 UINTN BitMaskSize;
535 BOOLEAN FeatureExist;
536
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;
544 }
545 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);
546
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)) {
553 //
554 // If this feature already registered
555 //
556 FeatureExist = TRUE;
557 break;
558 }
559 Entry = Entry->ForwardLink;
560 }
561
562 if (!FeatureExist) {
563 DEBUG ((DEBUG_INFO, "[NEW] "));
564 DumpCpuFeature (CpuFeature);
565 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
566 CpuFeaturesData->FeaturesCount++;
567 } else {
568 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
569 DumpCpuFeature (CpuFeature);
570 ASSERT (CpuFeatureEntry != NULL);
571 //
572 // Overwrite original parameters of CPU feature
573 //
574 if (CpuFeature->GetConfigDataFunc != NULL) {
575 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
576 }
577 if (CpuFeature->SupportFunc != NULL) {
578 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
579 }
580 if (CpuFeature->InitializeFunc != NULL) {
581 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
582 }
583 if (CpuFeature->FeatureName != NULL) {
584 if (CpuFeatureEntry->FeatureName == NULL) {
585 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
586 ASSERT (CpuFeatureEntry->FeatureName != NULL);
587 }
588 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
589 ASSERT_EFI_ERROR (Status);
590 FreePool (CpuFeature->FeatureName);
591 }
592 if (CpuFeature->BeforeFeatureBitMask != NULL) {
593 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
594 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
595 }
596 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
597 }
598 if (CpuFeature->AfterFeatureBitMask != NULL) {
599 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
600 FreePool (CpuFeatureEntry->AfterFeatureBitMask);
601 }
602 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
603 }
604 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
605 if (CpuFeatureEntry->CoreBeforeFeatureBitMask != NULL) {
606 FreePool (CpuFeatureEntry->CoreBeforeFeatureBitMask);
607 }
608 CpuFeatureEntry->CoreBeforeFeatureBitMask = CpuFeature->CoreBeforeFeatureBitMask;
609 }
610 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
611 if (CpuFeatureEntry->CoreAfterFeatureBitMask != NULL) {
612 FreePool (CpuFeatureEntry->CoreAfterFeatureBitMask);
613 }
614 CpuFeatureEntry->CoreAfterFeatureBitMask = CpuFeature->CoreAfterFeatureBitMask;
615 }
616 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
617 if (CpuFeatureEntry->PackageBeforeFeatureBitMask != NULL) {
618 FreePool (CpuFeatureEntry->PackageBeforeFeatureBitMask);
619 }
620 CpuFeatureEntry->PackageBeforeFeatureBitMask = CpuFeature->PackageBeforeFeatureBitMask;
621 }
622 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
623 if (CpuFeatureEntry->PackageAfterFeatureBitMask != NULL) {
624 FreePool (CpuFeatureEntry->PackageAfterFeatureBitMask);
625 }
626 CpuFeatureEntry->PackageAfterFeatureBitMask = CpuFeature->PackageAfterFeatureBitMask;
627 }
628
629 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
630 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;
631
632 FreePool (CpuFeature->FeatureMask);
633 FreePool (CpuFeature);
634 }
635 //
636 // Verify CPU features dependency can change CPU feature order
637 //
638 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
639 return RETURN_SUCCESS;
640 }
641
642 /**
643 Sets CPU feature bit mask in CPU feature bit mask buffer.
644
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
648 **/
649 VOID
650 SetCpuFeaturesBitMask (
651 IN UINT8 **FeaturesBitMask,
652 IN UINT32 Feature,
653 IN UINTN BitMaskSize
654 )
655 {
656 UINT8 *CpuFeaturesBitMask;
657
658 ASSERT (FeaturesBitMask != NULL);
659 CpuFeaturesBitMask = *FeaturesBitMask;
660 if (CpuFeaturesBitMask == NULL) {
661 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
662 ASSERT (CpuFeaturesBitMask != NULL);
663 *FeaturesBitMask = CpuFeaturesBitMask;
664 }
665
666 CpuFeaturesBitMask += (Feature / 8);
667 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
668 }
669
670 /**
671 Registers a CPU Feature.
672
673 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
674 name.
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
692 skipped.
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.
704
705 @retval RETURN_SUCCESS The CPU feature was successfully registered.
706 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
707 the CPU feature.
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.
713
714 @note This service could be called by BSP only.
715 **/
716 RETURN_STATUS
717 EFIAPI
718 RegisterCpuFeature (
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
723 ...
724 )
725 {
726 EFI_STATUS Status;
727 VA_LIST Marker;
728 UINT32 Feature;
729 UINTN BitMaskSize;
730 CPU_FEATURES_ENTRY *CpuFeature;
731 UINT8 *FeatureMask;
732 UINT8 *BeforeFeatureBitMask;
733 UINT8 *AfterFeatureBitMask;
734 UINT8 *CoreBeforeFeatureBitMask;
735 UINT8 *CoreAfterFeatureBitMask;
736 UINT8 *PackageBeforeFeatureBitMask;
737 UINT8 *PackageAfterFeatureBitMask;
738 BOOLEAN BeforeAll;
739 BOOLEAN AfterAll;
740
741 FeatureMask = NULL;
742 BeforeFeatureBitMask = NULL;
743 AfterFeatureBitMask = NULL;
744 CoreBeforeFeatureBitMask = NULL;
745 CoreAfterFeatureBitMask = NULL;
746 PackageBeforeFeatureBitMask = NULL;
747 PackageAfterFeatureBitMask = NULL;
748 BeforeAll = FALSE;
749 AfterAll = FALSE;
750
751 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
752
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);
782 }
783 Feature = VA_ARG (Marker, UINT32);
784 }
785 VA_END (Marker);
786
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);
807 }
808
809 Status = RegisterCpuFeatureWorker (CpuFeature);
810 ASSERT_EFI_ERROR (Status);
811
812 return RETURN_SUCCESS;
813 }
814
815 /**
816 Return ACPI_CPU_DATA data.
817
818 @return Pointer to ACPI_CPU_DATA data.
819 **/
820 ACPI_CPU_DATA *
821 GetAcpiCpuData (
822 VOID
823 )
824 {
825 EFI_STATUS Status;
826 UINTN NumberOfCpus;
827 UINTN NumberOfEnabledProcessors;
828 ACPI_CPU_DATA *AcpiCpuData;
829 UINTN TableSize;
830 CPU_REGISTER_TABLE *RegisterTable;
831 UINTN Index;
832 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
833
834 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
835 if (AcpiCpuData != NULL) {
836 return AcpiCpuData;
837 }
838
839 AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));
840 ASSERT (AcpiCpuData != NULL);
841
842 //
843 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
844 //
845 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
846 ASSERT_EFI_ERROR (Status);
847
848 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
849 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
850
851 //
852 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
853 //
854 TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
855 RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));
856 ASSERT (RegisterTable != NULL);
857
858 for (Index = 0; Index < NumberOfCpus; Index++) {
859 Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);
860 ASSERT_EFI_ERROR (Status);
861
862 RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
863 RegisterTable[Index].TableLength = 0;
864 RegisterTable[Index].AllocatedSize = 0;
865 RegisterTable[Index].RegisterTableEntry = 0;
866
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;
871 }
872 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
873 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
874
875 return AcpiCpuData;
876 }
877
878 /**
879 Enlarges CPU register table for each processor.
880
881 @param[in, out] RegisterTable Pointer processor's CPU register table
882 **/
883 STATIC
884 VOID
885 EnlargeRegisterTable (
886 IN OUT CPU_REGISTER_TABLE *RegisterTable
887 )
888 {
889 EFI_PHYSICAL_ADDRESS Address;
890 UINTN UsedPages;
891
892 UsedPages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
893 Address = (UINTN)AllocatePages (UsedPages + 1);
894 ASSERT (Address != 0);
895
896 //
897 // If there are records existing in the register table, then copy its contents
898 // to new region and free the old one.
899 //
900 if (RegisterTable->AllocatedSize > 0) {
901 CopyMem (
902 (VOID *) (UINTN) Address,
903 (VOID *) (UINTN) RegisterTable->RegisterTableEntry,
904 RegisterTable->AllocatedSize
905 );
906
907 FreePages ((VOID *)(UINTN)RegisterTable->RegisterTableEntry, UsedPages);
908 }
909
910 //
911 // Adjust the allocated size and register table base address.
912 //
913 RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
914 RegisterTable->RegisterTableEntry = Address;
915 }
916
917 /**
918 Add an entry in specified register table.
919
920 This function adds an entry in specified register table, with given register type,
921 register index, bit section and value.
922
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
931 **/
932 VOID
933 CpuRegisterTableWriteWorker (
934 IN BOOLEAN PreSmmFlag,
935 IN UINTN ProcessorNumber,
936 IN REGISTER_TYPE RegisterType,
937 IN UINT64 Index,
938 IN UINT8 ValidBitStart,
939 IN UINT8 ValidBitLength,
940 IN UINT64 Value
941 )
942 {
943 CPU_FEATURES_DATA *CpuFeaturesData;
944 ACPI_CPU_DATA *AcpiCpuData;
945 CPU_REGISTER_TABLE *RegisterTable;
946 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
947
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;
954 }
955
956 if (PreSmmFlag) {
957 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
958 } else {
959 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
960 }
961
962 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
963 EnlargeRegisterTable (RegisterTable);
964 }
965
966 //
967 // Append entry in the register table.
968 //
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;
976
977 RegisterTable->TableLength++;
978 }
979
980 /**
981 Adds an entry in specified register table.
982
983 This function adds an entry in specified register table, with given register type,
984 register index, bit section and value.
985
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
991
992 @note This service could be called by BSP only.
993 **/
994 VOID
995 EFIAPI
996 CpuRegisterTableWrite (
997 IN UINTN ProcessorNumber,
998 IN REGISTER_TYPE RegisterType,
999 IN UINT64 Index,
1000 IN UINT64 ValueMask,
1001 IN UINT64 Value
1002 )
1003 {
1004 UINT8 Start;
1005 UINT8 End;
1006 UINT8 Length;
1007
1008 Start = (UINT8)LowBitSet64 (ValueMask);
1009 End = (UINT8)HighBitSet64 (ValueMask);
1010 Length = End - Start + 1;
1011 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
1012 }
1013
1014 /**
1015 Adds an entry in specified Pre-SMM register table.
1016
1017 This function adds an entry in specified register table, with given register type,
1018 register index, bit section and value.
1019
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
1025
1026 @note This service could be called by BSP only.
1027 **/
1028 VOID
1029 EFIAPI
1030 PreSmmCpuRegisterTableWrite (
1031 IN UINTN ProcessorNumber,
1032 IN REGISTER_TYPE RegisterType,
1033 IN UINT64 Index,
1034 IN UINT64 ValueMask,
1035 IN UINT64 Value
1036 )
1037 {
1038 UINT8 Start;
1039 UINT8 End;
1040 UINT8 Length;
1041
1042 Start = (UINT8)LowBitSet64 (ValueMask);
1043 End = (UINT8)HighBitSet64 (ValueMask);
1044 Length = End - Start + 1;
1045 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
1046 }
1047
1048 /**
1049 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1050
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
1054
1055 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1056 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1057
1058 **/
1059 BOOLEAN
1060 IsCpuFeatureSetInCpuPcd (
1061 IN UINT8 *CpuBitMask,
1062 IN UINTN CpuBitMaskSize,
1063 IN UINT32 Feature
1064 )
1065 {
1066 if ((Feature >> 3) >= CpuBitMaskSize) {
1067 return FALSE;
1068 }
1069 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
1070 }
1071
1072 /**
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.
1077
1078 @param[in] Feature The bit number of the CPU feature to check in the PCD
1079 PcdCpuFeaturesSupport
1080
1081 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1082 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1083
1084 @note This service could be called by BSP only.
1085 **/
1086 BOOLEAN
1087 EFIAPI
1088 IsCpuFeatureSupported (
1089 IN UINT32 Feature
1090 )
1091 {
1092 return IsCpuFeatureSetInCpuPcd (
1093 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
1094 PcdGetSize (PcdCpuFeaturesSupport),
1095 Feature
1096 );
1097 }
1098
1099 /**
1100 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1101
1102 @param[in] Feature The bit number of the CPU feature to check in the PCD
1103 PcdCpuFeaturesSetting
1104
1105 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1106 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1107
1108 @note This service could be called by BSP only.
1109 **/
1110 BOOLEAN
1111 EFIAPI
1112 IsCpuFeatureInSetting (
1113 IN UINT32 Feature
1114 )
1115 {
1116 return IsCpuFeatureSetInCpuPcd (
1117 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
1118 PcdGetSize (PcdCpuFeaturesSetting),
1119 Feature
1120 );
1121 }
1122
1123 /**
1124 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
1125
1126 @param[in] Feature The bit number of the CPU feature to check in the PCD
1127 PcdCpuFeaturesCapability
1128
1129 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
1130 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
1131
1132 @note This service could be called by BSP only.
1133 **/
1134 BOOLEAN
1135 EFIAPI
1136 IsCpuFeatureCapability (
1137 IN UINT32 Feature
1138 )
1139 {
1140 return IsCpuFeatureSetInCpuPcd (
1141 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
1142 PcdGetSize (PcdCpuFeaturesCapability),
1143 Feature
1144 );
1145
1146 }
1147
1148 /**
1149 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
1150
1151 @param[in] Feature The bit number of the CPU feature to check in the PCD
1152 PcdCpuFeaturesUserConfiguration
1153
1154 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
1155 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
1156
1157 @note This service could be called by BSP only.
1158 **/
1159 BOOLEAN
1160 EFIAPI
1161 IsCpuFeatureUserConfiguration (
1162 IN UINT32 Feature
1163 )
1164 {
1165 return IsCpuFeatureSetInCpuPcd (
1166 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
1167 PcdGetSize (PcdCpuFeaturesUserConfiguration),
1168 Feature
1169 );
1170
1171 }
1172
1173 /**
1174 Switches to assigned BSP after CPU features initialization.
1175
1176 @param[in] ProcessorNumber The index of the CPU executing this function.
1177
1178 @note This service could be called by BSP only.
1179 **/
1180 VOID
1181 EFIAPI
1182 SwitchBspAfterFeaturesInitialize (
1183 IN UINTN ProcessorNumber
1184 )
1185 {
1186 CPU_FEATURES_DATA *CpuFeaturesData;
1187
1188 CpuFeaturesData = GetCpuFeaturesData ();
1189 CpuFeaturesData->BspNumber = ProcessorNumber;
1190 }
1191