]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
5b49bc450494cca3815894525b74192664bb8ff1
[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
121 @retval return the dependence result.
122 **/
123 CPU_FEATURE_DEPENDENCE_TYPE
124 DetectFeatureScope (
125 IN CPU_FEATURES_ENTRY *CpuFeature,
126 IN BOOLEAN Before
127 )
128 {
129 if (Before) {
130 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
131 return PackageDepType;
132 }
133
134 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
135 return CoreDepType;
136 }
137
138 if (CpuFeature->BeforeFeatureBitMask != NULL) {
139 return ThreadDepType;
140 }
141
142 return NoneDepType;
143 }
144
145 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
146 return PackageDepType;
147 }
148
149 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
150 return CoreDepType;
151 }
152
153 if (CpuFeature->AfterFeatureBitMask != NULL) {
154 return ThreadDepType;
155 }
156
157 return NoneDepType;
158 }
159
160 /**
161 Clear dependence for the specified type.
162
163 @param[in] CurrentFeature Cpu feature need to clear.
164 @param[in] Before Before or after dependence relationship.
165
166 **/
167 VOID
168 ClearFeatureScope (
169 IN CPU_FEATURES_ENTRY *CpuFeature,
170 IN BOOLEAN Before
171 )
172 {
173 if (Before) {
174 if (CpuFeature->BeforeFeatureBitMask != NULL) {
175 FreePool (CpuFeature->BeforeFeatureBitMask);
176 CpuFeature->BeforeFeatureBitMask = NULL;
177 }
178 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
179 FreePool (CpuFeature->CoreBeforeFeatureBitMask);
180 CpuFeature->CoreBeforeFeatureBitMask = NULL;
181 }
182 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
183 FreePool (CpuFeature->PackageBeforeFeatureBitMask);
184 CpuFeature->PackageBeforeFeatureBitMask = NULL;
185 }
186 } else {
187 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
188 FreePool (CpuFeature->PackageAfterFeatureBitMask);
189 CpuFeature->PackageAfterFeatureBitMask = NULL;
190 }
191 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
192 FreePool (CpuFeature->CoreAfterFeatureBitMask);
193 CpuFeature->CoreAfterFeatureBitMask = NULL;
194 }
195 if (CpuFeature->AfterFeatureBitMask != NULL) {
196 FreePool (CpuFeature->AfterFeatureBitMask);
197 CpuFeature->AfterFeatureBitMask = NULL;
198 }
199 }
200 }
201
202 /**
203 Base on dependence relationship to asjust feature dependence.
204
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.
209
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.
213
214 @retval TRUE means the current feature dependence has been adjusted.
215
216 @retval FALSE means the previous feature dependence has been adjusted.
217 or previous feature has no dependence with the find one.
218
219 **/
220 BOOLEAN
221 AdjustFeaturesDependence (
222 IN OUT CPU_FEATURES_ENTRY *PreviousFeature,
223 IN OUT CPU_FEATURES_ENTRY *CurrentFeature,
224 IN BOOLEAN Before
225 )
226 {
227 CPU_FEATURE_DEPENDENCE_TYPE PreDependType;
228 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType;
229
230 PreDependType = DetectFeatureScope(PreviousFeature, Before);
231 CurrentDependType = DetectFeatureScope(CurrentFeature, Before);
232
233 //
234 // If previous feature has no dependence with the find featue.
235 // return FALSE.
236 //
237 if (PreDependType == NoneDepType) {
238 return FALSE;
239 }
240
241 //
242 // If both feature have dependence, keep the one which needs use more
243 // processors and clear the dependence for the other one.
244 //
245 if (PreDependType >= CurrentDependType) {
246 ClearFeatureScope (CurrentFeature, Before);
247 return TRUE;
248 } else {
249 ClearFeatureScope (PreviousFeature, Before);
250 return FALSE;
251 }
252 }
253
254 /**
255 Base on dependence relationship to asjust feature order.
256
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.
261
262 **/
263 VOID
264 AdjustEntry (
265 IN LIST_ENTRY *FeatureList,
266 IN OUT LIST_ENTRY *FindEntry,
267 IN OUT LIST_ENTRY *CurrentEntry,
268 IN BOOLEAN Before
269 )
270 {
271 LIST_ENTRY *PreviousEntry;
272 CPU_FEATURES_ENTRY *PreviousFeature;
273 CPU_FEATURES_ENTRY *CurrentFeature;
274
275 //
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
286 // threads.
287 //
288 if (Before) {
289 PreviousEntry = GetPreviousNode (FeatureList, FindEntry);
290 } else {
291 PreviousEntry = GetNextNode (FeatureList, FindEntry);
292 }
293
294 CurrentFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
295 RemoveEntryList (CurrentEntry);
296
297 if (IsNull (FeatureList, PreviousEntry)) {
298 //
299 // If not exist the previous or next entry, just insert the current entry.
300 //
301 if (Before) {
302 InsertTailList (FindEntry, CurrentEntry);
303 } else {
304 InsertHeadList (FindEntry, CurrentEntry);
305 }
306 } else {
307 //
308 // If exist the previous or next entry, need to check it before insert curent entry.
309 //
310 PreviousFeature = CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry);
311
312 if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, Before)) {
313 //
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.
317 //
318 if (Before) {
319 InsertTailList (PreviousEntry, CurrentEntry);
320 } else {
321 InsertHeadList (PreviousEntry, CurrentEntry);
322 }
323 } else {
324 if (Before) {
325 InsertTailList (FindEntry, CurrentEntry);
326 } else {
327 InsertHeadList (FindEntry, CurrentEntry);
328 }
329 }
330 }
331 }
332
333 /**
334 Checks and adjusts current CPU features per dependency relationship.
335
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.
339
340 @retval return Swapped info.
341 **/
342 BOOLEAN
343 InsertToBeforeEntry (
344 IN LIST_ENTRY *FeatureList,
345 IN LIST_ENTRY *CurrentEntry,
346 IN UINT8 *FeatureMask
347 )
348 {
349 LIST_ENTRY *CheckEntry;
350 CPU_FEATURES_ENTRY *CheckFeature;
351 BOOLEAN Swapped;
352
353 Swapped = FALSE;
354
355 //
356 // Check all features dispatched before this entry
357 //
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);
363 Swapped = TRUE;
364 break;
365 }
366 CheckEntry = CheckEntry->ForwardLink;
367 }
368
369 return Swapped;
370 }
371
372 /**
373 Checks and adjusts current CPU features per dependency relationship.
374
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.
378
379 @retval return Swapped info.
380 **/
381 BOOLEAN
382 InsertToAfterEntry (
383 IN LIST_ENTRY *FeatureList,
384 IN LIST_ENTRY *CurrentEntry,
385 IN UINT8 *FeatureMask
386 )
387 {
388 LIST_ENTRY *CheckEntry;
389 CPU_FEATURES_ENTRY *CheckFeature;
390 BOOLEAN Swapped;
391
392 Swapped = FALSE;
393
394 //
395 // Check all features dispatched after this entry
396 //
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);
402 Swapped = TRUE;
403 break;
404 }
405 CheckEntry = CheckEntry->ForwardLink;
406 }
407
408 return Swapped;
409 }
410
411 /**
412 Checks and adjusts CPU features order per dependency relationship.
413
414 @param[in] FeatureList Pointer to CPU feature list
415 **/
416 VOID
417 CheckCpuFeaturesDependency (
418 IN LIST_ENTRY *FeatureList
419 )
420 {
421 LIST_ENTRY *CurrentEntry;
422 CPU_FEATURES_ENTRY *CpuFeature;
423 LIST_ENTRY *CheckEntry;
424 CPU_FEATURES_ENTRY *CheckFeature;
425 BOOLEAN Swapped;
426 LIST_ENTRY *TempEntry;
427 LIST_ENTRY *NextEntry;
428
429 CurrentEntry = GetFirstNode (FeatureList);
430 while (!IsNull (FeatureList, CurrentEntry)) {
431 Swapped = FALSE;
432 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
433 NextEntry = CurrentEntry->ForwardLink;
434 if (CpuFeature->BeforeAll) {
435 //
436 // Check all features dispatched before this entry
437 //
438 CheckEntry = GetFirstNode (FeatureList);
439 while (CheckEntry != CurrentEntry) {
440 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
441 if (!CheckFeature->BeforeAll) {
442 //
443 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
444 // insert currentEntry before Checked feature
445 //
446 RemoveEntryList (CurrentEntry);
447 InsertTailList (CheckEntry, CurrentEntry);
448 Swapped = TRUE;
449 break;
450 }
451 CheckEntry = CheckEntry->ForwardLink;
452 }
453 if (Swapped) {
454 CurrentEntry = NextEntry;
455 continue;
456 }
457 }
458
459 if (CpuFeature->AfterAll) {
460 //
461 // Check all features dispatched after this entry
462 //
463 CheckEntry = GetNextNode (FeatureList, CurrentEntry);
464 while (!IsNull (FeatureList, CheckEntry)) {
465 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
466 if (!CheckFeature->AfterAll) {
467 //
468 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
469 // insert currentEntry after Checked feature
470 //
471 TempEntry = GetNextNode (FeatureList, CurrentEntry);
472 RemoveEntryList (CurrentEntry);
473 InsertHeadList (CheckEntry, CurrentEntry);
474 CurrentEntry = TempEntry;
475 Swapped = TRUE;
476 break;
477 }
478 CheckEntry = CheckEntry->ForwardLink;
479 }
480 if (Swapped) {
481 CurrentEntry = NextEntry;
482 continue;
483 }
484 }
485
486 if (CpuFeature->BeforeFeatureBitMask != NULL) {
487 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->BeforeFeatureBitMask);
488 if (Swapped) {
489 CurrentEntry = NextEntry;
490 continue;
491 }
492 }
493
494 if (CpuFeature->AfterFeatureBitMask != NULL) {
495 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->AfterFeatureBitMask);
496 if (Swapped) {
497 CurrentEntry = NextEntry;
498 continue;
499 }
500 }
501
502 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
503 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->CoreBeforeFeatureBitMask);
504 if (Swapped) {
505 CurrentEntry = NextEntry;
506 continue;
507 }
508 }
509
510 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
511 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->CoreAfterFeatureBitMask);
512 if (Swapped) {
513 CurrentEntry = NextEntry;
514 continue;
515 }
516 }
517
518 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
519 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->PackageBeforeFeatureBitMask);
520 if (Swapped) {
521 CurrentEntry = NextEntry;
522 continue;
523 }
524 }
525
526 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
527 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->PackageAfterFeatureBitMask);
528 if (Swapped) {
529 CurrentEntry = NextEntry;
530 continue;
531 }
532 }
533
534 CurrentEntry = CurrentEntry->ForwardLink;
535 }
536 }
537
538 /**
539 Worker function to register CPU Feature.
540
541 @param[in] CpuFeature Pointer to CPU feature entry
542
543 @retval RETURN_SUCCESS The CPU feature was successfully registered.
544 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
545 the CPU feature.
546 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
547 supported due to a circular dependency between
548 BEFORE and AFTER features.
549 **/
550 RETURN_STATUS
551 RegisterCpuFeatureWorker (
552 IN CPU_FEATURES_ENTRY *CpuFeature
553 )
554 {
555 EFI_STATUS Status;
556 CPU_FEATURES_DATA *CpuFeaturesData;
557 CPU_FEATURES_ENTRY *CpuFeatureEntry;
558 LIST_ENTRY *Entry;
559 UINTN BitMaskSize;
560 BOOLEAN FeatureExist;
561
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;
569 }
570 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);
571
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)) {
578 //
579 // If this feature already registered
580 //
581 FeatureExist = TRUE;
582 break;
583 }
584 Entry = Entry->ForwardLink;
585 }
586
587 if (!FeatureExist) {
588 DEBUG ((DEBUG_INFO, "[NEW] "));
589 DumpCpuFeature (CpuFeature);
590 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
591 CpuFeaturesData->FeaturesCount++;
592 } else {
593 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
594 DumpCpuFeature (CpuFeature);
595 ASSERT (CpuFeatureEntry != NULL);
596 //
597 // Overwrite original parameters of CPU feature
598 //
599 if (CpuFeature->GetConfigDataFunc != NULL) {
600 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
601 }
602 if (CpuFeature->SupportFunc != NULL) {
603 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
604 }
605 if (CpuFeature->InitializeFunc != NULL) {
606 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
607 }
608 if (CpuFeature->FeatureName != NULL) {
609 if (CpuFeatureEntry->FeatureName == NULL) {
610 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
611 ASSERT (CpuFeatureEntry->FeatureName != NULL);
612 }
613 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
614 ASSERT_EFI_ERROR (Status);
615 FreePool (CpuFeature->FeatureName);
616 }
617 if (CpuFeature->BeforeFeatureBitMask != NULL) {
618 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
619 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
620 }
621 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
622 }
623 if (CpuFeature->AfterFeatureBitMask != NULL) {
624 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
625 FreePool (CpuFeatureEntry->AfterFeatureBitMask);
626 }
627 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
628 }
629 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
630 if (CpuFeatureEntry->CoreBeforeFeatureBitMask != NULL) {
631 FreePool (CpuFeatureEntry->CoreBeforeFeatureBitMask);
632 }
633 CpuFeatureEntry->CoreBeforeFeatureBitMask = CpuFeature->CoreBeforeFeatureBitMask;
634 }
635 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
636 if (CpuFeatureEntry->CoreAfterFeatureBitMask != NULL) {
637 FreePool (CpuFeatureEntry->CoreAfterFeatureBitMask);
638 }
639 CpuFeatureEntry->CoreAfterFeatureBitMask = CpuFeature->CoreAfterFeatureBitMask;
640 }
641 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
642 if (CpuFeatureEntry->PackageBeforeFeatureBitMask != NULL) {
643 FreePool (CpuFeatureEntry->PackageBeforeFeatureBitMask);
644 }
645 CpuFeatureEntry->PackageBeforeFeatureBitMask = CpuFeature->PackageBeforeFeatureBitMask;
646 }
647 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
648 if (CpuFeatureEntry->PackageAfterFeatureBitMask != NULL) {
649 FreePool (CpuFeatureEntry->PackageAfterFeatureBitMask);
650 }
651 CpuFeatureEntry->PackageAfterFeatureBitMask = CpuFeature->PackageAfterFeatureBitMask;
652 }
653
654 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
655 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;
656
657 FreePool (CpuFeature->FeatureMask);
658 FreePool (CpuFeature);
659 }
660 //
661 // Verify CPU features dependency can change CPU feature order
662 //
663 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
664 return RETURN_SUCCESS;
665 }
666
667 /**
668 Sets CPU feature bit mask in CPU feature bit mask buffer.
669
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
673 **/
674 VOID
675 SetCpuFeaturesBitMask (
676 IN UINT8 **FeaturesBitMask,
677 IN UINT32 Feature,
678 IN UINTN BitMaskSize
679 )
680 {
681 UINT8 *CpuFeaturesBitMask;
682
683 ASSERT (FeaturesBitMask != NULL);
684 CpuFeaturesBitMask = *FeaturesBitMask;
685 if (CpuFeaturesBitMask == NULL) {
686 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
687 ASSERT (CpuFeaturesBitMask != NULL);
688 *FeaturesBitMask = CpuFeaturesBitMask;
689 }
690
691 CpuFeaturesBitMask += (Feature / 8);
692 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
693 }
694
695 /**
696 Registers a CPU Feature.
697
698 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
699 name.
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
717 skipped.
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.
729
730 @retval RETURN_SUCCESS The CPU feature was successfully registered.
731 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
732 the CPU feature.
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.
738
739 @note This service could be called by BSP only.
740 **/
741 RETURN_STATUS
742 EFIAPI
743 RegisterCpuFeature (
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
748 ...
749 )
750 {
751 EFI_STATUS Status;
752 VA_LIST Marker;
753 UINT32 Feature;
754 UINTN BitMaskSize;
755 CPU_FEATURES_ENTRY *CpuFeature;
756 UINT8 *FeatureMask;
757 UINT8 *BeforeFeatureBitMask;
758 UINT8 *AfterFeatureBitMask;
759 UINT8 *CoreBeforeFeatureBitMask;
760 UINT8 *CoreAfterFeatureBitMask;
761 UINT8 *PackageBeforeFeatureBitMask;
762 UINT8 *PackageAfterFeatureBitMask;
763 BOOLEAN BeforeAll;
764 BOOLEAN AfterAll;
765
766 FeatureMask = NULL;
767 BeforeFeatureBitMask = NULL;
768 AfterFeatureBitMask = NULL;
769 CoreBeforeFeatureBitMask = NULL;
770 CoreAfterFeatureBitMask = NULL;
771 PackageBeforeFeatureBitMask = NULL;
772 PackageAfterFeatureBitMask = NULL;
773 BeforeAll = FALSE;
774 AfterAll = FALSE;
775
776 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
777
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);
807 }
808 Feature = VA_ARG (Marker, UINT32);
809 }
810 VA_END (Marker);
811
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);
832 }
833
834 Status = RegisterCpuFeatureWorker (CpuFeature);
835 ASSERT_EFI_ERROR (Status);
836
837 return RETURN_SUCCESS;
838 }
839
840 /**
841 Return ACPI_CPU_DATA data.
842
843 @return Pointer to ACPI_CPU_DATA data.
844 **/
845 ACPI_CPU_DATA *
846 GetAcpiCpuData (
847 VOID
848 )
849 {
850 EFI_STATUS Status;
851 UINTN NumberOfCpus;
852 UINTN NumberOfEnabledProcessors;
853 ACPI_CPU_DATA *AcpiCpuData;
854 UINTN TableSize;
855 CPU_REGISTER_TABLE *RegisterTable;
856 UINTN Index;
857 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
858
859 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
860 if (AcpiCpuData != NULL) {
861 return AcpiCpuData;
862 }
863
864 AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));
865 ASSERT (AcpiCpuData != NULL);
866
867 //
868 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
869 //
870 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
871 ASSERT_EFI_ERROR (Status);
872
873 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
874 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
875
876 //
877 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
878 //
879 TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
880 RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));
881 ASSERT (RegisterTable != NULL);
882
883 for (Index = 0; Index < NumberOfCpus; Index++) {
884 Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);
885 ASSERT_EFI_ERROR (Status);
886
887 RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
888 RegisterTable[Index].TableLength = 0;
889 RegisterTable[Index].AllocatedSize = 0;
890 RegisterTable[Index].RegisterTableEntry = 0;
891
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;
896 }
897 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
898 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
899
900 return AcpiCpuData;
901 }
902
903 /**
904 Enlarges CPU register table for each processor.
905
906 @param[in, out] RegisterTable Pointer processor's CPU register table
907 **/
908 STATIC
909 VOID
910 EnlargeRegisterTable (
911 IN OUT CPU_REGISTER_TABLE *RegisterTable
912 )
913 {
914 EFI_PHYSICAL_ADDRESS Address;
915 UINTN UsedPages;
916
917 UsedPages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
918 Address = (UINTN)AllocatePages (UsedPages + 1);
919 ASSERT (Address != 0);
920
921 //
922 // If there are records existing in the register table, then copy its contents
923 // to new region and free the old one.
924 //
925 if (RegisterTable->AllocatedSize > 0) {
926 CopyMem (
927 (VOID *) (UINTN) Address,
928 (VOID *) (UINTN) RegisterTable->RegisterTableEntry,
929 RegisterTable->AllocatedSize
930 );
931
932 FreePages ((VOID *)(UINTN)RegisterTable->RegisterTableEntry, UsedPages);
933 }
934
935 //
936 // Adjust the allocated size and register table base address.
937 //
938 RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
939 RegisterTable->RegisterTableEntry = Address;
940 }
941
942 /**
943 Add an entry in specified register table.
944
945 This function adds an entry in specified register table, with given register type,
946 register index, bit section and value.
947
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
956 **/
957 VOID
958 CpuRegisterTableWriteWorker (
959 IN BOOLEAN PreSmmFlag,
960 IN UINTN ProcessorNumber,
961 IN REGISTER_TYPE RegisterType,
962 IN UINT64 Index,
963 IN UINT8 ValidBitStart,
964 IN UINT8 ValidBitLength,
965 IN UINT64 Value
966 )
967 {
968 CPU_FEATURES_DATA *CpuFeaturesData;
969 ACPI_CPU_DATA *AcpiCpuData;
970 CPU_REGISTER_TABLE *RegisterTable;
971 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
972
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;
979 }
980
981 if (PreSmmFlag) {
982 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
983 } else {
984 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
985 }
986
987 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
988 EnlargeRegisterTable (RegisterTable);
989 }
990
991 //
992 // Append entry in the register table.
993 //
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;
1001
1002 RegisterTable->TableLength++;
1003 }
1004
1005 /**
1006 Adds an entry in specified register table.
1007
1008 This function adds an entry in specified register table, with given register type,
1009 register index, bit section and value.
1010
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
1016
1017 @note This service could be called by BSP only.
1018 **/
1019 VOID
1020 EFIAPI
1021 CpuRegisterTableWrite (
1022 IN UINTN ProcessorNumber,
1023 IN REGISTER_TYPE RegisterType,
1024 IN UINT64 Index,
1025 IN UINT64 ValueMask,
1026 IN UINT64 Value
1027 )
1028 {
1029 UINT8 Start;
1030 UINT8 End;
1031 UINT8 Length;
1032
1033 Start = (UINT8)LowBitSet64 (ValueMask);
1034 End = (UINT8)HighBitSet64 (ValueMask);
1035 Length = End - Start + 1;
1036 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
1037 }
1038
1039 /**
1040 Adds an entry in specified Pre-SMM register table.
1041
1042 This function adds an entry in specified register table, with given register type,
1043 register index, bit section and value.
1044
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
1050
1051 @note This service could be called by BSP only.
1052 **/
1053 VOID
1054 EFIAPI
1055 PreSmmCpuRegisterTableWrite (
1056 IN UINTN ProcessorNumber,
1057 IN REGISTER_TYPE RegisterType,
1058 IN UINT64 Index,
1059 IN UINT64 ValueMask,
1060 IN UINT64 Value
1061 )
1062 {
1063 UINT8 Start;
1064 UINT8 End;
1065 UINT8 Length;
1066
1067 Start = (UINT8)LowBitSet64 (ValueMask);
1068 End = (UINT8)HighBitSet64 (ValueMask);
1069 Length = End - Start + 1;
1070 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
1071 }
1072
1073 /**
1074 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1075
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
1079
1080 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1081 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1082
1083 **/
1084 BOOLEAN
1085 IsCpuFeatureSetInCpuPcd (
1086 IN UINT8 *CpuBitMask,
1087 IN UINTN CpuBitMaskSize,
1088 IN UINT32 Feature
1089 )
1090 {
1091 if ((Feature >> 3) >= CpuBitMaskSize) {
1092 return FALSE;
1093 }
1094 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
1095 }
1096
1097 /**
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.
1102
1103 @param[in] Feature The bit number of the CPU feature to check in the PCD
1104 PcdCpuFeaturesSupport
1105
1106 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1107 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1108
1109 @note This service could be called by BSP only.
1110 **/
1111 BOOLEAN
1112 EFIAPI
1113 IsCpuFeatureSupported (
1114 IN UINT32 Feature
1115 )
1116 {
1117 return IsCpuFeatureSetInCpuPcd (
1118 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
1119 PcdGetSize (PcdCpuFeaturesSupport),
1120 Feature
1121 );
1122 }
1123
1124 /**
1125 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1126
1127 @param[in] Feature The bit number of the CPU feature to check in the PCD
1128 PcdCpuFeaturesSetting
1129
1130 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1131 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1132
1133 @note This service could be called by BSP only.
1134 **/
1135 BOOLEAN
1136 EFIAPI
1137 IsCpuFeatureInSetting (
1138 IN UINT32 Feature
1139 )
1140 {
1141 return IsCpuFeatureSetInCpuPcd (
1142 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
1143 PcdGetSize (PcdCpuFeaturesSetting),
1144 Feature
1145 );
1146 }
1147
1148 /**
1149 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
1150
1151 @param[in] Feature The bit number of the CPU feature to check in the PCD
1152 PcdCpuFeaturesCapability
1153
1154 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
1155 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
1156
1157 @note This service could be called by BSP only.
1158 **/
1159 BOOLEAN
1160 EFIAPI
1161 IsCpuFeatureCapability (
1162 IN UINT32 Feature
1163 )
1164 {
1165 return IsCpuFeatureSetInCpuPcd (
1166 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
1167 PcdGetSize (PcdCpuFeaturesCapability),
1168 Feature
1169 );
1170
1171 }
1172
1173 /**
1174 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
1175
1176 @param[in] Feature The bit number of the CPU feature to check in the PCD
1177 PcdCpuFeaturesUserConfiguration
1178
1179 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
1180 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
1181
1182 @note This service could be called by BSP only.
1183 **/
1184 BOOLEAN
1185 EFIAPI
1186 IsCpuFeatureUserConfiguration (
1187 IN UINT32 Feature
1188 )
1189 {
1190 return IsCpuFeatureSetInCpuPcd (
1191 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
1192 PcdGetSize (PcdCpuFeaturesUserConfiguration),
1193 Feature
1194 );
1195
1196 }
1197
1198 /**
1199 Switches to assigned BSP after CPU features initialization.
1200
1201 @param[in] ProcessorNumber The index of the CPU executing this function.
1202
1203 @note This service could be called by BSP only.
1204 **/
1205 VOID
1206 EFIAPI
1207 SwitchBspAfterFeaturesInitialize (
1208 IN UINTN ProcessorNumber
1209 )
1210 {
1211 CPU_FEATURES_DATA *CpuFeaturesData;
1212
1213 CpuFeaturesData = GetCpuFeaturesData ();
1214 CpuFeaturesData->BspNumber = ProcessorNumber;
1215 }
1216