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