]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
fa0f0b41e26bdff055db5bd0affd6b56bd3cee3d
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / RegisterCpuFeaturesLib.c
1 /** @file
2 CPU Register Table Library functions.
3
4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "RegisterCpuFeatures.h"
10
11 /**
12 Checks if two CPU feature bit masks are equal.
13
14 @param[in] FirstFeatureMask The first input CPU feature bit mask
15 @param[in] SecondFeatureMask The second input CPU feature bit mask
16
17 @retval TRUE Two CPU feature bit masks are equal.
18 @retval FALSE Two CPU feature bit masks are not equal.
19 **/
20 BOOLEAN
21 IsCpuFeatureMatch (
22 IN UINT8 *FirstFeatureMask,
23 IN UINT8 *SecondFeatureMask
24 )
25 {
26 UINTN BitMaskSize;
27
28 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
29 if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) {
30 return TRUE;
31 } else {
32 return FALSE;
33 }
34 }
35
36 /**
37 Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
38
39 @param[in] FeatureMask A pointer to the CPU feature bit mask.
40 **/
41 VOID
42 DumpCpuFeatureMask (
43 IN UINT8 *FeatureMask
44 )
45 {
46 UINTN Index;
47 UINT8 *Data8;
48 UINTN BitMaskSize;
49
50 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
51 Data8 = (UINT8 *) FeatureMask;
52 for (Index = 0; Index < BitMaskSize; Index++) {
53 DEBUG ((DEBUG_INFO, " %02x ", *Data8++));
54 }
55 DEBUG ((DEBUG_INFO, "\n"));
56 }
57
58 /**
59 Dump CPU feature name or CPU feature bit mask.
60
61 @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY
62 **/
63 VOID
64 DumpCpuFeature (
65 IN CPU_FEATURES_ENTRY *CpuFeature
66 )
67 {
68
69 if (CpuFeature->FeatureName != NULL) {
70 DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName));
71 } else {
72 DEBUG ((DEBUG_INFO, "FeatureMask = "));
73 DumpCpuFeatureMask (CpuFeature->FeatureMask);
74 }
75 }
76
77 /**
78 Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
79
80 @param[in] FeatureMask Pointer to CPU feature bit mask
81 @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer
82
83 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
84 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
85 **/
86 BOOLEAN
87 IsBitMaskMatchCheck (
88 IN UINT8 *FeatureMask,
89 IN UINT8 *DependentBitMask
90 )
91 {
92 UINTN Index;
93 UINTN BitMaskSize;
94 UINT8 *Data1;
95 UINT8 *Data2;
96
97 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
98
99 Data1 = FeatureMask;
100 Data2 = DependentBitMask;
101 for (Index = 0; Index < BitMaskSize; Index++) {
102 if (((*(Data1++)) & (*(Data2++))) != 0) {
103 return TRUE;
104 }
105 }
106 return FALSE;
107 }
108
109 /**
110 Try to find the specify cpu featuren in former/after feature list.
111
112 @param[in] FeatureList Pointer to dependent CPU feature list
113 @param[in] CurrentEntry Pointer to current CPU feature entry.
114 @param[in] SearchFormer Find in former feature or after features.
115 @param[in] FeatureMask Pointer to CPU feature bit mask
116
117 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
118 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
119 **/
120 BOOLEAN
121 FindSpecifyFeature (
122 IN LIST_ENTRY *FeatureList,
123 IN LIST_ENTRY *CurrentEntry,
124 IN BOOLEAN SearchFormer,
125 IN UINT8 *FeatureMask
126 )
127 {
128 CPU_FEATURES_ENTRY *CpuFeature;
129 LIST_ENTRY *NextEntry;
130
131 //
132 // Check whether exist the not neighborhood entry first.
133 // If not exist, return FALSE means not found status.
134 //
135 if (SearchFormer) {
136 NextEntry = CurrentEntry->BackLink;
137 if (IsNull (FeatureList, NextEntry)) {
138 return FALSE;
139 }
140
141 NextEntry = NextEntry->BackLink;
142 if (IsNull (FeatureList, NextEntry)) {
143 return FALSE;
144 }
145
146 NextEntry = CurrentEntry->BackLink->BackLink;
147 } else {
148 NextEntry = CurrentEntry->ForwardLink;
149 if (IsNull (FeatureList, NextEntry)) {
150 return FALSE;
151 }
152
153 NextEntry = NextEntry->ForwardLink;
154 if (IsNull (FeatureList, NextEntry)) {
155 return FALSE;
156 }
157
158 NextEntry = CurrentEntry->ForwardLink->ForwardLink;
159 }
160
161 while (!IsNull (FeatureList, NextEntry)) {
162 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (NextEntry);
163
164 if (IsBitMaskMatchCheck (FeatureMask, CpuFeature->FeatureMask)) {
165 return TRUE;
166 }
167
168 if (SearchFormer) {
169 NextEntry = NextEntry->BackLink;
170 } else {
171 NextEntry = NextEntry->ForwardLink;
172 }
173 }
174
175 return FALSE;
176 }
177
178 /**
179 Return feature dependence result.
180
181 @param[in] CpuFeature Pointer to CPU feature.
182 @param[in] Before Check before dependence or after.
183 @param[in] NextCpuFeatureMask Pointer to next CPU feature Mask.
184
185 @retval return the dependence result.
186 **/
187 CPU_FEATURE_DEPENDENCE_TYPE
188 DetectFeatureScope (
189 IN CPU_FEATURES_ENTRY *CpuFeature,
190 IN BOOLEAN Before,
191 IN UINT8 *NextCpuFeatureMask
192 )
193 {
194 //
195 // if need to check before type dependence but the feature after current feature is not
196 // exist, means this before type dependence not valid, just return NoneDepType.
197 // Just like Feature A has a dependence of feature B, but Feature B not installed, so
198 // Feature A maybe insert to the last entry of the list. In this case, for below code,
199 // Featrure A has depend of feature B, but it is the last entry of the list, so the
200 // NextCpuFeatureMask is NULL, so the dependence for feature A here is useless and code
201 // just return NoneDepType.
202 //
203 if (NextCpuFeatureMask == NULL) {
204 return NoneDepType;
205 }
206
207 if (Before) {
208 if ((CpuFeature->PackageBeforeFeatureBitMask != NULL) &&
209 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageBeforeFeatureBitMask)) {
210 return PackageDepType;
211 }
212
213 if ((CpuFeature->CoreBeforeFeatureBitMask != NULL) &&
214 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreBeforeFeatureBitMask)) {
215 return CoreDepType;
216 }
217
218 if ((CpuFeature->BeforeFeatureBitMask != NULL) &&
219 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->BeforeFeatureBitMask)) {
220 return ThreadDepType;
221 }
222
223 return NoneDepType;
224 }
225
226 if ((CpuFeature->PackageAfterFeatureBitMask != NULL) &&
227 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageAfterFeatureBitMask)) {
228 return PackageDepType;
229 }
230
231 if ((CpuFeature->CoreAfterFeatureBitMask != NULL) &&
232 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreAfterFeatureBitMask)) {
233 return CoreDepType;
234 }
235
236 if ((CpuFeature->AfterFeatureBitMask != NULL) &&
237 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->AfterFeatureBitMask)) {
238 return ThreadDepType;
239 }
240
241 return NoneDepType;
242 }
243
244 /**
245 Return feature dependence result.
246
247 @param[in] CpuFeature Pointer to CPU feature.
248 @param[in] Before Check before dependence or after.
249 @param[in] FeatureList Pointer to CPU feature list.
250
251 @retval return the dependence result.
252 **/
253 CPU_FEATURE_DEPENDENCE_TYPE
254 DetectNoneNeighborhoodFeatureScope (
255 IN CPU_FEATURES_ENTRY *CpuFeature,
256 IN BOOLEAN Before,
257 IN LIST_ENTRY *FeatureList
258 )
259 {
260 if (Before) {
261 if ((CpuFeature->PackageBeforeFeatureBitMask != NULL) &&
262 FindSpecifyFeature(FeatureList, &CpuFeature->Link, FALSE, CpuFeature->PackageBeforeFeatureBitMask)) {
263 return PackageDepType;
264 }
265
266 if ((CpuFeature->CoreBeforeFeatureBitMask != NULL) &&
267 FindSpecifyFeature(FeatureList, &CpuFeature->Link, FALSE, CpuFeature->CoreBeforeFeatureBitMask)) {
268 return CoreDepType;
269 }
270
271 if ((CpuFeature->BeforeFeatureBitMask != NULL) &&
272 FindSpecifyFeature(FeatureList, &CpuFeature->Link, FALSE, CpuFeature->BeforeFeatureBitMask)) {
273 return ThreadDepType;
274 }
275
276 return NoneDepType;
277 }
278
279 if ((CpuFeature->PackageAfterFeatureBitMask != NULL) &&
280 FindSpecifyFeature(FeatureList, &CpuFeature->Link, TRUE, CpuFeature->PackageAfterFeatureBitMask)) {
281 return PackageDepType;
282 }
283
284 if ((CpuFeature->CoreAfterFeatureBitMask != NULL) &&
285 FindSpecifyFeature(FeatureList, &CpuFeature->Link, TRUE, CpuFeature->CoreAfterFeatureBitMask)) {
286 return CoreDepType;
287 }
288
289 if ((CpuFeature->AfterFeatureBitMask != NULL) &&
290 FindSpecifyFeature(FeatureList, &CpuFeature->Link, TRUE, CpuFeature->AfterFeatureBitMask)) {
291 return ThreadDepType;
292 }
293
294 return NoneDepType;
295 }
296
297 /**
298 Base on dependence relationship to asjust feature dependence.
299
300 ONLY when the feature before(or after) the find feature also has
301 dependence with the find feature. In this case, driver need to base
302 on dependce relationship to decide how to insert current feature and
303 adjust the feature dependence.
304
305 @param[in, out] PreviousFeature CPU feature current before the find one.
306 @param[in, out] CurrentFeature Cpu feature need to adjust.
307 @param[in] FindFeature Cpu feature which current feature depends.
308 @param[in] Before Before or after dependence relationship.
309
310 @retval TRUE means the current feature dependence has been adjusted.
311
312 @retval FALSE means the previous feature dependence has been adjusted.
313 or previous feature has no dependence with the find one.
314
315 **/
316 BOOLEAN
317 AdjustFeaturesDependence (
318 IN OUT CPU_FEATURES_ENTRY *PreviousFeature,
319 IN OUT CPU_FEATURES_ENTRY *CurrentFeature,
320 IN CPU_FEATURES_ENTRY *FindFeature,
321 IN BOOLEAN Before
322 )
323 {
324 CPU_FEATURE_DEPENDENCE_TYPE PreDependType;
325 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType;
326
327 PreDependType = DetectFeatureScope(PreviousFeature, Before, FindFeature->FeatureMask);
328 CurrentDependType = DetectFeatureScope(CurrentFeature, Before, FindFeature->FeatureMask);
329
330 //
331 // If previous feature has no dependence with the find featue.
332 // return FALSE.
333 //
334 if (PreDependType == NoneDepType) {
335 return FALSE;
336 }
337
338 //
339 // If both feature have dependence, keep the one which needs use more
340 // processors and clear the dependence for the other one.
341 //
342 if (PreDependType >= CurrentDependType) {
343 return TRUE;
344 } else {
345 return FALSE;
346 }
347 }
348
349 /**
350 Base on dependence relationship to asjust feature order.
351
352 @param[in] FeatureList Pointer to CPU feature list
353 @param[in, out] FindEntry The entry this feature depend on.
354 @param[in, out] CurrentEntry The entry for this feature.
355 @param[in] Before Before or after dependence relationship.
356
357 **/
358 VOID
359 AdjustEntry (
360 IN LIST_ENTRY *FeatureList,
361 IN OUT LIST_ENTRY *FindEntry,
362 IN OUT LIST_ENTRY *CurrentEntry,
363 IN BOOLEAN Before
364 )
365 {
366 LIST_ENTRY *PreviousEntry;
367 CPU_FEATURES_ENTRY *PreviousFeature;
368 CPU_FEATURES_ENTRY *CurrentFeature;
369 CPU_FEATURES_ENTRY *FindFeature;
370
371 //
372 // For CPU feature which has core or package type dependence, later code need to insert
373 // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.
374 // So if driver finds both feature A and B need to execute before feature C, driver will
375 // base on dependence type of feature A and B to update the logic here.
376 // For example, feature A has package type dependence and feature B has core type dependence,
377 // because package type dependence need to wait for more processors which has strong dependence
378 // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver
379 // will remove the feature dependence in feature B.
380 // Driver just needs to make sure before feature C been executed, feature A has finished its task
381 // in all all thread. Feature A finished in all threads also means feature B have finshed in all
382 // threads.
383 //
384 if (Before) {
385 PreviousEntry = GetPreviousNode (FeatureList, FindEntry);
386 } else {
387
388 PreviousEntry = GetNextNode (FeatureList, FindEntry);
389 }
390
391 CurrentFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
392 RemoveEntryList (CurrentEntry);
393
394 if (IsNull (FeatureList, PreviousEntry)) {
395 //
396 // If not exist the previous or next entry, just insert the current entry.
397 //
398 if (Before) {
399 InsertTailList (FindEntry, CurrentEntry);
400 } else {
401 InsertHeadList (FindEntry, CurrentEntry);
402 }
403 } else {
404 //
405 // If exist the previous or next entry, need to check it before insert curent entry.
406 //
407 PreviousFeature = CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry);
408 FindFeature = CPU_FEATURE_ENTRY_FROM_LINK (FindEntry);
409
410 if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, FindFeature, Before)) {
411 //
412 // Return TRUE means current feature dependence has been cleared and the previous
413 // feature dependence has been kept and used. So insert current feature before (or after)
414 // the previous feature.
415 //
416 if (Before) {
417 InsertTailList (PreviousEntry, CurrentEntry);
418 } else {
419 InsertHeadList (PreviousEntry, CurrentEntry);
420 }
421 } else {
422 if (Before) {
423 InsertTailList (FindEntry, CurrentEntry);
424 } else {
425 InsertHeadList (FindEntry, CurrentEntry);
426 }
427 }
428 }
429 }
430
431
432 /**
433 Checks and adjusts current CPU features per dependency relationship.
434
435 @param[in] FeatureList Pointer to CPU feature list
436 @param[in] CurrentEntry Pointer to current checked CPU feature
437 @param[in] FeatureMask The feature bit mask.
438
439 @retval return Swapped info.
440 **/
441 BOOLEAN
442 InsertToBeforeEntry (
443 IN LIST_ENTRY *FeatureList,
444 IN LIST_ENTRY *CurrentEntry,
445 IN UINT8 *FeatureMask
446 )
447 {
448 LIST_ENTRY *CheckEntry;
449 CPU_FEATURES_ENTRY *CheckFeature;
450 BOOLEAN Swapped;
451
452 Swapped = FALSE;
453
454 //
455 // Check all features dispatched before this entry
456 //
457 CheckEntry = GetFirstNode (FeatureList);
458 while (CheckEntry != CurrentEntry) {
459 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
460 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {
461 AdjustEntry (FeatureList, CheckEntry, CurrentEntry, TRUE);
462 Swapped = TRUE;
463 break;
464 }
465 CheckEntry = CheckEntry->ForwardLink;
466 }
467
468 return Swapped;
469 }
470
471 /**
472 Checks and adjusts current CPU features per dependency relationship.
473
474 @param[in] FeatureList Pointer to CPU feature list
475 @param[in] CurrentEntry Pointer to current checked CPU feature
476 @param[in] FeatureMask The feature bit mask.
477
478 @retval return Swapped info.
479 **/
480 BOOLEAN
481 InsertToAfterEntry (
482 IN LIST_ENTRY *FeatureList,
483 IN LIST_ENTRY *CurrentEntry,
484 IN UINT8 *FeatureMask
485 )
486 {
487 LIST_ENTRY *CheckEntry;
488 CPU_FEATURES_ENTRY *CheckFeature;
489 BOOLEAN Swapped;
490
491 Swapped = FALSE;
492
493 //
494 // Check all features dispatched after this entry
495 //
496 CheckEntry = GetNextNode (FeatureList, CurrentEntry);
497 while (!IsNull (FeatureList, CheckEntry)) {
498 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
499 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {
500 AdjustEntry (FeatureList, CheckEntry, CurrentEntry, FALSE);
501 Swapped = TRUE;
502 break;
503 }
504 CheckEntry = CheckEntry->ForwardLink;
505 }
506
507 return Swapped;
508 }
509
510 /**
511 Checks and adjusts CPU features order per dependency relationship.
512
513 @param[in] FeatureList Pointer to CPU feature list
514 **/
515 VOID
516 CheckCpuFeaturesDependency (
517 IN LIST_ENTRY *FeatureList
518 )
519 {
520 LIST_ENTRY *CurrentEntry;
521 CPU_FEATURES_ENTRY *CpuFeature;
522 LIST_ENTRY *CheckEntry;
523 CPU_FEATURES_ENTRY *CheckFeature;
524 BOOLEAN Swapped;
525 LIST_ENTRY *TempEntry;
526 LIST_ENTRY *NextEntry;
527
528 CurrentEntry = GetFirstNode (FeatureList);
529 while (!IsNull (FeatureList, CurrentEntry)) {
530 Swapped = FALSE;
531 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
532 NextEntry = CurrentEntry->ForwardLink;
533 if (CpuFeature->BeforeAll) {
534 //
535 // Check all features dispatched before this entry
536 //
537 CheckEntry = GetFirstNode (FeatureList);
538 while (CheckEntry != CurrentEntry) {
539 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
540 if (!CheckFeature->BeforeAll) {
541 //
542 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
543 // insert currentEntry before Checked feature
544 //
545 RemoveEntryList (CurrentEntry);
546 InsertTailList (CheckEntry, CurrentEntry);
547 Swapped = TRUE;
548 break;
549 }
550 CheckEntry = CheckEntry->ForwardLink;
551 }
552 if (Swapped) {
553 CurrentEntry = NextEntry;
554 continue;
555 }
556 }
557
558 if (CpuFeature->AfterAll) {
559 //
560 // Check all features dispatched after this entry
561 //
562 CheckEntry = GetNextNode (FeatureList, CurrentEntry);
563 while (!IsNull (FeatureList, CheckEntry)) {
564 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
565 if (!CheckFeature->AfterAll) {
566 //
567 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
568 // insert currentEntry after Checked feature
569 //
570 TempEntry = GetNextNode (FeatureList, CurrentEntry);
571 RemoveEntryList (CurrentEntry);
572 InsertHeadList (CheckEntry, CurrentEntry);
573 CurrentEntry = TempEntry;
574 Swapped = TRUE;
575 break;
576 }
577 CheckEntry = CheckEntry->ForwardLink;
578 }
579 if (Swapped) {
580 CurrentEntry = NextEntry;
581 continue;
582 }
583 }
584
585 if (CpuFeature->BeforeFeatureBitMask != NULL) {
586 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->BeforeFeatureBitMask);
587 if (Swapped) {
588 continue;
589 }
590 }
591
592 if (CpuFeature->AfterFeatureBitMask != NULL) {
593 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->AfterFeatureBitMask);
594 if (Swapped) {
595 continue;
596 }
597 }
598
599 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
600 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->CoreBeforeFeatureBitMask);
601 if (Swapped) {
602 continue;
603 }
604 }
605
606 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
607 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->CoreAfterFeatureBitMask);
608 if (Swapped) {
609 continue;
610 }
611 }
612
613 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
614 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->PackageBeforeFeatureBitMask);
615 if (Swapped) {
616 continue;
617 }
618 }
619
620 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
621 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->PackageAfterFeatureBitMask);
622 if (Swapped) {
623 continue;
624 }
625 }
626
627 CurrentEntry = CurrentEntry->ForwardLink;
628 }
629 }
630
631 /**
632 Worker function to register CPU Feature.
633
634 @param[in] CpuFeature Pointer to CPU feature entry
635
636 @retval RETURN_SUCCESS The CPU feature was successfully registered.
637 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
638 the CPU feature.
639 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
640 supported due to a circular dependency between
641 BEFORE and AFTER features.
642 **/
643 RETURN_STATUS
644 RegisterCpuFeatureWorker (
645 IN CPU_FEATURES_ENTRY *CpuFeature
646 )
647 {
648 EFI_STATUS Status;
649 CPU_FEATURES_DATA *CpuFeaturesData;
650 CPU_FEATURES_ENTRY *CpuFeatureEntry;
651 LIST_ENTRY *Entry;
652 UINTN BitMaskSize;
653 BOOLEAN FeatureExist;
654
655 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
656 CpuFeaturesData = GetCpuFeaturesData ();
657 if (CpuFeaturesData->FeaturesCount == 0) {
658 InitializeListHead (&CpuFeaturesData->FeatureList);
659 InitializeSpinLock (&CpuFeaturesData->CpuFlags.MemoryMappedLock);
660 InitializeSpinLock (&CpuFeaturesData->CpuFlags.ConsoleLogLock);
661 CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;
662 }
663 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);
664
665 FeatureExist = FALSE;
666 CpuFeatureEntry = NULL;
667 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
668 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
669 CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
670 if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {
671 //
672 // If this feature already registered
673 //
674 FeatureExist = TRUE;
675 break;
676 }
677 Entry = Entry->ForwardLink;
678 }
679
680 if (!FeatureExist) {
681 DEBUG ((DEBUG_INFO, "[NEW] "));
682 DumpCpuFeature (CpuFeature);
683 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
684 CpuFeaturesData->FeaturesCount++;
685 } else {
686 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
687 DumpCpuFeature (CpuFeature);
688 ASSERT (CpuFeatureEntry != NULL);
689 //
690 // Overwrite original parameters of CPU feature
691 //
692 if (CpuFeature->GetConfigDataFunc != NULL) {
693 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
694 }
695 if (CpuFeature->SupportFunc != NULL) {
696 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
697 }
698 if (CpuFeature->InitializeFunc != NULL) {
699 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
700 }
701 if (CpuFeature->FeatureName != NULL) {
702 if (CpuFeatureEntry->FeatureName == NULL) {
703 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
704 ASSERT (CpuFeatureEntry->FeatureName != NULL);
705 }
706 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
707 ASSERT_EFI_ERROR (Status);
708 FreePool (CpuFeature->FeatureName);
709 }
710 if (CpuFeature->BeforeFeatureBitMask != NULL) {
711 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
712 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
713 }
714 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
715 }
716 if (CpuFeature->AfterFeatureBitMask != NULL) {
717 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
718 FreePool (CpuFeatureEntry->AfterFeatureBitMask);
719 }
720 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
721 }
722 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {
723 if (CpuFeatureEntry->CoreBeforeFeatureBitMask != NULL) {
724 FreePool (CpuFeatureEntry->CoreBeforeFeatureBitMask);
725 }
726 CpuFeatureEntry->CoreBeforeFeatureBitMask = CpuFeature->CoreBeforeFeatureBitMask;
727 }
728 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {
729 if (CpuFeatureEntry->CoreAfterFeatureBitMask != NULL) {
730 FreePool (CpuFeatureEntry->CoreAfterFeatureBitMask);
731 }
732 CpuFeatureEntry->CoreAfterFeatureBitMask = CpuFeature->CoreAfterFeatureBitMask;
733 }
734 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {
735 if (CpuFeatureEntry->PackageBeforeFeatureBitMask != NULL) {
736 FreePool (CpuFeatureEntry->PackageBeforeFeatureBitMask);
737 }
738 CpuFeatureEntry->PackageBeforeFeatureBitMask = CpuFeature->PackageBeforeFeatureBitMask;
739 }
740 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {
741 if (CpuFeatureEntry->PackageAfterFeatureBitMask != NULL) {
742 FreePool (CpuFeatureEntry->PackageAfterFeatureBitMask);
743 }
744 CpuFeatureEntry->PackageAfterFeatureBitMask = CpuFeature->PackageAfterFeatureBitMask;
745 }
746
747 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
748 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;
749
750 FreePool (CpuFeature->FeatureMask);
751 FreePool (CpuFeature);
752 }
753 //
754 // Verify CPU features dependency can change CPU feature order
755 //
756 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
757 return RETURN_SUCCESS;
758 }
759
760 /**
761 Sets CPU feature bit mask in CPU feature bit mask buffer.
762
763 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
764 @param[in] Feature The bit number of the CPU feature
765 @param[in] BitMaskSize CPU feature bit mask buffer size
766 **/
767 VOID
768 SetCpuFeaturesBitMask (
769 IN UINT8 **FeaturesBitMask,
770 IN UINT32 Feature,
771 IN UINTN BitMaskSize
772 )
773 {
774 UINT8 *CpuFeaturesBitMask;
775
776 ASSERT (FeaturesBitMask != NULL);
777 CpuFeaturesBitMask = *FeaturesBitMask;
778 if (CpuFeaturesBitMask == NULL) {
779 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
780 ASSERT (CpuFeaturesBitMask != NULL);
781 *FeaturesBitMask = CpuFeaturesBitMask;
782 }
783
784 CpuFeaturesBitMask += (Feature / 8);
785 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
786 }
787
788 /**
789 Registers a CPU Feature.
790
791 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
792 name.
793 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
794 is an optional parameter that may be NULL. If NULL,
795 then the most recently registered function for the
796 CPU feature is used. If no functions are registered
797 for a CPU feature, then the CPU configuration data
798 for the registered feature is NULL.
799 @param[in] SupportFunc CPU feature support function. This is an optional
800 parameter that may be NULL. If NULL, then the most
801 recently registered function for the CPU feature is
802 used. If no functions are registered for a CPU
803 feature, then the CPU feature is assumed to be
804 supported by all CPUs.
805 @param[in] InitializeFunc CPU feature initialize function. This is an optional
806 parameter that may be NULL. If NULL, then the most
807 recently registered function for the CPU feature is
808 used. If no functions are registered for a CPU
809 feature, then the CPU feature initialization is
810 skipped.
811 @param[in] ... Variable argument list of UINT32 CPU feature value.
812 Values with no modifiers are the features provided
813 by the registered functions.
814 Values with CPU_FEATURE_BEFORE modifier are features
815 that must be initialized after the features provided
816 by the registered functions are used.
817 Values with CPU_FEATURE_AFTER modifier are features
818 that must be initialized before the features provided
819 by the registered functions are used.
820 The last argument in this variable argument list must
821 always be CPU_FEATURE_END.
822
823 @retval RETURN_SUCCESS The CPU feature was successfully registered.
824 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
825 the CPU feature.
826 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
827 supported due to a circular dependency between
828 BEFORE and AFTER features.
829 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration
830 not updated by Platform driver yet.
831
832 @note This service could be called by BSP only.
833 **/
834 RETURN_STATUS
835 EFIAPI
836 RegisterCpuFeature (
837 IN CHAR8 *FeatureName, OPTIONAL
838 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL
839 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL
840 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL
841 ...
842 )
843 {
844 EFI_STATUS Status;
845 VA_LIST Marker;
846 UINT32 Feature;
847 UINTN BitMaskSize;
848 CPU_FEATURES_ENTRY *CpuFeature;
849 UINT8 *FeatureMask;
850 UINT8 *BeforeFeatureBitMask;
851 UINT8 *AfterFeatureBitMask;
852 UINT8 *CoreBeforeFeatureBitMask;
853 UINT8 *CoreAfterFeatureBitMask;
854 UINT8 *PackageBeforeFeatureBitMask;
855 UINT8 *PackageAfterFeatureBitMask;
856 BOOLEAN BeforeAll;
857 BOOLEAN AfterAll;
858
859 FeatureMask = NULL;
860 BeforeFeatureBitMask = NULL;
861 AfterFeatureBitMask = NULL;
862 CoreBeforeFeatureBitMask = NULL;
863 CoreAfterFeatureBitMask = NULL;
864 PackageBeforeFeatureBitMask = NULL;
865 PackageAfterFeatureBitMask = NULL;
866 BeforeAll = FALSE;
867 AfterAll = FALSE;
868
869 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
870
871 VA_START (Marker, InitializeFunc);
872 Feature = VA_ARG (Marker, UINT32);
873 while (Feature != CPU_FEATURE_END) {
874 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))
875 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));
876 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))
877 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));
878 ASSERT ((Feature & (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER))
879 != (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER));
880 ASSERT ((Feature & (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER))
881 != (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER));
882 if (Feature < CPU_FEATURE_BEFORE) {
883 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;
884 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;
885 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
886 ASSERT (FeatureMask == NULL);
887 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);
888 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {
889 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);
890 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {
891 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);
892 } else if ((Feature & CPU_FEATURE_CORE_BEFORE) != 0) {
893 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask, Feature & ~CPU_FEATURE_CORE_BEFORE, BitMaskSize);
894 } else if ((Feature & CPU_FEATURE_CORE_AFTER) != 0) {
895 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask, Feature & ~CPU_FEATURE_CORE_AFTER, BitMaskSize);
896 } else if ((Feature & CPU_FEATURE_PACKAGE_BEFORE) != 0) {
897 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_BEFORE, BitMaskSize);
898 } else if ((Feature & CPU_FEATURE_PACKAGE_AFTER) != 0) {
899 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_AFTER, BitMaskSize);
900 }
901 Feature = VA_ARG (Marker, UINT32);
902 }
903 VA_END (Marker);
904
905 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));
906 ASSERT (CpuFeature != NULL);
907 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;
908 CpuFeature->FeatureMask = FeatureMask;
909 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;
910 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;
911 CpuFeature->CoreBeforeFeatureBitMask = CoreBeforeFeatureBitMask;
912 CpuFeature->CoreAfterFeatureBitMask = CoreAfterFeatureBitMask;
913 CpuFeature->PackageBeforeFeatureBitMask = PackageBeforeFeatureBitMask;
914 CpuFeature->PackageAfterFeatureBitMask = PackageAfterFeatureBitMask;
915 CpuFeature->BeforeAll = BeforeAll;
916 CpuFeature->AfterAll = AfterAll;
917 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;
918 CpuFeature->SupportFunc = SupportFunc;
919 CpuFeature->InitializeFunc = InitializeFunc;
920 if (FeatureName != NULL) {
921 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
922 ASSERT (CpuFeature->FeatureName != NULL);
923 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);
924 ASSERT_EFI_ERROR (Status);
925 }
926
927 Status = RegisterCpuFeatureWorker (CpuFeature);
928 ASSERT_EFI_ERROR (Status);
929
930 return RETURN_SUCCESS;
931 }
932
933 /**
934 Return ACPI_CPU_DATA data.
935
936 @return Pointer to ACPI_CPU_DATA data.
937 **/
938 ACPI_CPU_DATA *
939 GetAcpiCpuData (
940 VOID
941 )
942 {
943 EFI_STATUS Status;
944 UINTN NumberOfCpus;
945 UINTN NumberOfEnabledProcessors;
946 ACPI_CPU_DATA *AcpiCpuData;
947 UINTN TableSize;
948 CPU_REGISTER_TABLE *RegisterTable;
949 UINTN Index;
950 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
951
952 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
953 if (AcpiCpuData != NULL) {
954 return AcpiCpuData;
955 }
956
957 AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));
958 ASSERT (AcpiCpuData != NULL);
959
960 //
961 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
962 //
963 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
964 ASSERT_EFI_ERROR (Status);
965
966 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
967 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
968
969 //
970 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
971 //
972 TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
973 RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));
974 ASSERT (RegisterTable != NULL);
975
976 for (Index = 0; Index < NumberOfCpus; Index++) {
977 Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);
978 ASSERT_EFI_ERROR (Status);
979
980 RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
981 RegisterTable[Index].TableLength = 0;
982 RegisterTable[Index].AllocatedSize = 0;
983 RegisterTable[Index].RegisterTableEntry = 0;
984
985 RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
986 RegisterTable[NumberOfCpus + Index].TableLength = 0;
987 RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;
988 RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
989 }
990 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
991 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
992
993 return AcpiCpuData;
994 }
995
996 /**
997 Enlarges CPU register table for each processor.
998
999 @param[in, out] RegisterTable Pointer processor's CPU register table
1000 **/
1001 STATIC
1002 VOID
1003 EnlargeRegisterTable (
1004 IN OUT CPU_REGISTER_TABLE *RegisterTable
1005 )
1006 {
1007 EFI_PHYSICAL_ADDRESS Address;
1008 UINTN UsedPages;
1009
1010 UsedPages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
1011 Address = (UINTN)AllocatePages (UsedPages + 1);
1012 ASSERT (Address != 0);
1013
1014 //
1015 // If there are records existing in the register table, then copy its contents
1016 // to new region and free the old one.
1017 //
1018 if (RegisterTable->AllocatedSize > 0) {
1019 CopyMem (
1020 (VOID *) (UINTN) Address,
1021 (VOID *) (UINTN) RegisterTable->RegisterTableEntry,
1022 RegisterTable->AllocatedSize
1023 );
1024
1025 FreePages ((VOID *)(UINTN)RegisterTable->RegisterTableEntry, UsedPages);
1026 }
1027
1028 //
1029 // Adjust the allocated size and register table base address.
1030 //
1031 RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
1032 RegisterTable->RegisterTableEntry = Address;
1033 }
1034
1035 /**
1036 Add an entry in specified register table.
1037
1038 This function adds an entry in specified register table, with given register type,
1039 register index, bit section and value.
1040
1041 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
1042 If FALSE, entry will be added into register table
1043 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1044 @param[in] RegisterType Type of the register to program
1045 @param[in] Index Index of the register to program
1046 @param[in] ValidBitStart Start of the bit section
1047 @param[in] ValidBitLength Length of the bit section
1048 @param[in] Value Value to write
1049 **/
1050 VOID
1051 CpuRegisterTableWriteWorker (
1052 IN BOOLEAN PreSmmFlag,
1053 IN UINTN ProcessorNumber,
1054 IN REGISTER_TYPE RegisterType,
1055 IN UINT64 Index,
1056 IN UINT8 ValidBitStart,
1057 IN UINT8 ValidBitLength,
1058 IN UINT64 Value
1059 )
1060 {
1061 CPU_FEATURES_DATA *CpuFeaturesData;
1062 ACPI_CPU_DATA *AcpiCpuData;
1063 CPU_REGISTER_TABLE *RegisterTable;
1064 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
1065
1066 CpuFeaturesData = GetCpuFeaturesData ();
1067 if (CpuFeaturesData->RegisterTable == NULL) {
1068 AcpiCpuData = GetAcpiCpuData ();
1069 ASSERT ((AcpiCpuData != NULL) && (AcpiCpuData->RegisterTable != 0));
1070 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;
1071 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;
1072 }
1073
1074 if (PreSmmFlag) {
1075 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
1076 } else {
1077 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
1078 }
1079
1080 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
1081 EnlargeRegisterTable (RegisterTable);
1082 }
1083
1084 //
1085 // Append entry in the register table.
1086 //
1087 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
1088 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
1089 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;
1090 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);
1091 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
1092 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
1093 RegisterTableEntry[RegisterTable->TableLength].Value = Value;
1094
1095 RegisterTable->TableLength++;
1096 }
1097
1098 /**
1099 Adds an entry in specified register table.
1100
1101 This function adds an entry in specified register table, with given register type,
1102 register index, bit section and value.
1103
1104 @param[in] ProcessorNumber The index of the CPU to add a register table entry
1105 @param[in] RegisterType Type of the register to program
1106 @param[in] Index Index of the register to program
1107 @param[in] ValueMask Mask of bits in register to write
1108 @param[in] Value Value to write
1109
1110 @note This service could be called by BSP only.
1111 **/
1112 VOID
1113 EFIAPI
1114 CpuRegisterTableWrite (
1115 IN UINTN ProcessorNumber,
1116 IN REGISTER_TYPE RegisterType,
1117 IN UINT64 Index,
1118 IN UINT64 ValueMask,
1119 IN UINT64 Value
1120 )
1121 {
1122 UINT8 Start;
1123 UINT8 End;
1124 UINT8 Length;
1125
1126 Start = (UINT8)LowBitSet64 (ValueMask);
1127 End = (UINT8)HighBitSet64 (ValueMask);
1128 Length = End - Start + 1;
1129 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
1130 }
1131
1132 /**
1133 Adds an entry in specified Pre-SMM register table.
1134
1135 This function adds an entry in specified register table, with given register type,
1136 register index, bit section and value.
1137
1138 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
1139 @param[in] RegisterType Type of the register to program
1140 @param[in] Index Index of the register to program
1141 @param[in] ValueMask Mask of bits in register to write
1142 @param[in] Value Value to write
1143
1144 @note This service could be called by BSP only.
1145 **/
1146 VOID
1147 EFIAPI
1148 PreSmmCpuRegisterTableWrite (
1149 IN UINTN ProcessorNumber,
1150 IN REGISTER_TYPE RegisterType,
1151 IN UINT64 Index,
1152 IN UINT64 ValueMask,
1153 IN UINT64 Value
1154 )
1155 {
1156 UINT8 Start;
1157 UINT8 End;
1158 UINT8 Length;
1159
1160 Start = (UINT8)LowBitSet64 (ValueMask);
1161 End = (UINT8)HighBitSet64 (ValueMask);
1162 Length = End - Start + 1;
1163 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
1164 }
1165
1166 /**
1167 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
1168
1169 @param[in] CpuBitMask CPU feature bit mask buffer
1170 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
1171 @param[in] Feature The bit number of the CPU feature
1172
1173 @retval TRUE The CPU feature is set in CpuBitMask.
1174 @retval FALSE The CPU feature is not set in CpuBitMask.
1175
1176 **/
1177 BOOLEAN
1178 IsCpuFeatureSetInCpuPcd (
1179 IN UINT8 *CpuBitMask,
1180 IN UINTN CpuBitMaskSize,
1181 IN UINT32 Feature
1182 )
1183 {
1184 if ((Feature >> 3) >= CpuBitMaskSize) {
1185 return FALSE;
1186 }
1187 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
1188 }
1189
1190 /**
1191 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
1192 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
1193 associated with that feature should be optimized away if compiler
1194 optimizations are enabled.
1195
1196 @param[in] Feature The bit number of the CPU feature to check in the PCD
1197 PcdCpuFeaturesSupport
1198
1199 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
1200 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
1201
1202 @note This service could be called by BSP only.
1203 **/
1204 BOOLEAN
1205 EFIAPI
1206 IsCpuFeatureSupported (
1207 IN UINT32 Feature
1208 )
1209 {
1210 return IsCpuFeatureSetInCpuPcd (
1211 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
1212 PcdGetSize (PcdCpuFeaturesSupport),
1213 Feature
1214 );
1215 }
1216
1217 /**
1218 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
1219
1220 @param[in] Feature The bit number of the CPU feature to check in the PCD
1221 PcdCpuFeaturesSetting
1222
1223 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
1224 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
1225
1226 @note This service could be called by BSP only.
1227 **/
1228 BOOLEAN
1229 EFIAPI
1230 IsCpuFeatureInSetting (
1231 IN UINT32 Feature
1232 )
1233 {
1234 return IsCpuFeatureSetInCpuPcd (
1235 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
1236 PcdGetSize (PcdCpuFeaturesSetting),
1237 Feature
1238 );
1239 }
1240
1241 /**
1242 Switches to assigned BSP after CPU features initialization.
1243
1244 @param[in] ProcessorNumber The index of the CPU executing this function.
1245
1246 @note This service could be called by BSP only.
1247 **/
1248 VOID
1249 EFIAPI
1250 SwitchBspAfterFeaturesInitialize (
1251 IN UINTN ProcessorNumber
1252 )
1253 {
1254 CPU_FEATURES_DATA *CpuFeaturesData;
1255
1256 CpuFeaturesData = GetCpuFeaturesData ();
1257 CpuFeaturesData->BspNumber = ProcessorNumber;
1258 }
1259