6ec26e1e92a1de0c220add8fcd627ede4e4bb5f9
[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 CPU feature is valid.
85
86 @param[in] Feature Pointer to CPU feature
87
88 @retval TRUE The CPU feature is valid.
89 @retval FALSE The CPU feature is invalid.
90 **/
91 BOOLEAN
92 RegisterCpuFeatureLibIsFeatureValid (
93 IN UINT32 Feature
94 )
95 {
96 UINT32 Data;
97
98 Data = Feature;
99 Data &= ~(CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER | CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
100 //
101 // Currently, CPU_FEATURE_PROC_TRACE is the MAX feature we support.
102 // If you define a feature bigger than it, please replace it at below.
103 //
104 if (Data > CPU_FEATURE_PROC_TRACE) {
105 DEBUG ((DEBUG_ERROR, "Invalid CPU feature: 0x%x ", Feature));
106 return FALSE;
107 }
108 return TRUE;
109 }
110
111 /**
112 Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
113
114 @param[in] FeatureMask Pointer to CPU feature bit mask
115 @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer
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 IsBitMaskMatchCheck (
122 IN UINT8 *FeatureMask,
123 IN UINT8 *DependentBitMask
124 )
125 {
126 UINTN Index;
127 UINTN BitMaskSize;
128 UINT8 *Data1;
129 UINT8 *Data2;
130
131 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
132
133 Data1 = FeatureMask;
134 Data2 = DependentBitMask;
135 for (Index = 0; Index < BitMaskSize; Index++) {
136 if (((*(Data1++)) & (*(Data2++))) != 0) {
137 return TRUE;
138 }
139 }
140 return FALSE;
141 }
142
143 /**
144 Checks and adjusts CPU features order per dependency relationship.
145
146 @param[in] FeatureList Pointer to CPU feature list
147 **/
148 VOID
149 CheckCpuFeaturesDependency (
150 IN LIST_ENTRY *FeatureList
151 )
152 {
153 LIST_ENTRY *CurrentEntry;
154 CPU_FEATURES_ENTRY *CpuFeature;
155 LIST_ENTRY *CheckEntry;
156 CPU_FEATURES_ENTRY *CheckFeature;
157 BOOLEAN Swapped;
158 LIST_ENTRY *TempEntry;
159
160 CurrentEntry = GetFirstNode (FeatureList);
161 while (!IsNull (FeatureList, CurrentEntry)) {
162 Swapped = FALSE;
163 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
164 if (CpuFeature->BeforeAll) {
165 //
166 // Check all features dispatched before this entry
167 //
168 CheckEntry = GetFirstNode (FeatureList);
169 while (CheckEntry != CurrentEntry) {
170 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
171 if (!CheckFeature->BeforeAll) {
172 //
173 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
174 // insert currentEntry before Checked feature
175 //
176 RemoveEntryList (CurrentEntry);
177 InsertTailList (CheckEntry, CurrentEntry);
178 Swapped = TRUE;
179 break;
180 }
181 CheckEntry = CheckEntry->ForwardLink;
182 }
183 if (Swapped) {
184 continue;
185 }
186 }
187
188 if (CpuFeature->AfterAll) {
189 //
190 // Check all features dispatched after this entry
191 //
192 CheckEntry = GetNextNode (FeatureList, CurrentEntry);
193 while (!IsNull (FeatureList, CheckEntry)) {
194 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
195 if (!CheckFeature->AfterAll) {
196 //
197 // If this feature has no AfterAll flag and is dispatched after CpuFeature,
198 // insert currentEntry after Checked feature
199 //
200 TempEntry = GetNextNode (FeatureList, CurrentEntry);
201 RemoveEntryList (CurrentEntry);
202 InsertHeadList (CheckEntry, CurrentEntry);
203 CurrentEntry = TempEntry;
204 Swapped = TRUE;
205 break;
206 }
207 CheckEntry = CheckEntry->ForwardLink;
208 }
209 if (Swapped) {
210 continue;
211 }
212 }
213
214 if (CpuFeature->BeforeFeatureBitMask != NULL) {
215 //
216 // Check all features dispatched before this entry
217 //
218 CheckEntry = GetFirstNode (FeatureList);
219 while (CheckEntry != CurrentEntry) {
220 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
221 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {
222 //
223 // If there is dependency, swap them
224 //
225 RemoveEntryList (CurrentEntry);
226 InsertTailList (CheckEntry, CurrentEntry);
227 Swapped = TRUE;
228 break;
229 }
230 CheckEntry = CheckEntry->ForwardLink;
231 }
232 if (Swapped) {
233 continue;
234 }
235 }
236
237 if (CpuFeature->AfterFeatureBitMask != NULL) {
238 //
239 // Check all features dispatched after this entry
240 //
241 CheckEntry = GetNextNode (FeatureList, CurrentEntry);
242 while (!IsNull (FeatureList, CheckEntry)) {
243 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
244 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {
245 //
246 // If there is dependency, swap them
247 //
248 TempEntry = GetNextNode (FeatureList, CurrentEntry);
249 RemoveEntryList (CurrentEntry);
250 InsertHeadList (CheckEntry, CurrentEntry);
251 CurrentEntry = TempEntry;
252 Swapped = TRUE;
253 break;
254 }
255 CheckEntry = CheckEntry->ForwardLink;
256 }
257 if (Swapped) {
258 continue;
259 }
260 }
261 //
262 // No swap happened, check the next feature
263 //
264 CurrentEntry = CurrentEntry->ForwardLink;
265 }
266 }
267
268 /**
269 Worker function to register CPU Feature.
270
271 @param[in] CpuFeature Pointer to CPU feature entry
272
273 @retval RETURN_SUCCESS The CPU feature was successfully registered.
274 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
275 the CPU feature.
276 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
277 supported due to a circular dependency between
278 BEFORE and AFTER features.
279 **/
280 RETURN_STATUS
281 RegisterCpuFeatureWorker (
282 IN CPU_FEATURES_ENTRY *CpuFeature
283 )
284 {
285 EFI_STATUS Status;
286 CPU_FEATURES_DATA *CpuFeaturesData;
287 CPU_FEATURES_ENTRY *CpuFeatureEntry;
288 LIST_ENTRY *Entry;
289 UINTN BitMaskSize;
290 BOOLEAN FeatureExist;
291
292 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
293 CpuFeaturesData = GetCpuFeaturesData ();
294 if (CpuFeaturesData->FeaturesCount == 0) {
295 InitializeListHead (&CpuFeaturesData->FeatureList);
296 InitializeSpinLock (&CpuFeaturesData->MsrLock);
297 InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);
298 CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;
299 }
300 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);
301
302 FeatureExist = FALSE;
303 CpuFeatureEntry = NULL;
304 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
305 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
306 CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
307 if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {
308 //
309 // If this feature already registered
310 //
311 FeatureExist = TRUE;
312 break;
313 }
314 Entry = Entry->ForwardLink;
315 }
316
317 if (!FeatureExist) {
318 DEBUG ((DEBUG_INFO, "[NEW] "));
319 DumpCpuFeature (CpuFeature);
320 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
321 CpuFeaturesData->FeaturesCount++;
322 } else {
323 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
324 DumpCpuFeature (CpuFeature);
325 ASSERT (CpuFeatureEntry != NULL);
326 //
327 // Overwrite original parameters of CPU feature
328 //
329 if (CpuFeature->GetConfigDataFunc != NULL) {
330 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
331 }
332 if (CpuFeature->SupportFunc != NULL) {
333 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
334 }
335 if (CpuFeature->InitializeFunc != NULL) {
336 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
337 }
338 if (CpuFeature->FeatureName != NULL) {
339 if (CpuFeatureEntry->FeatureName == NULL) {
340 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
341 ASSERT (CpuFeatureEntry->FeatureName != NULL);
342 }
343 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
344 ASSERT_EFI_ERROR (Status);
345 FreePool (CpuFeature->FeatureName);
346 }
347 if (CpuFeature->BeforeFeatureBitMask != NULL) {
348 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
349 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
350 }
351 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
352 }
353 if (CpuFeature->AfterFeatureBitMask != NULL) {
354 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
355 FreePool (CpuFeatureEntry->AfterFeatureBitMask);
356 }
357 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
358 }
359 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
360 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;
361
362 FreePool (CpuFeature->FeatureMask);
363 FreePool (CpuFeature);
364 }
365 //
366 // Verify CPU features dependency can change CPU feature order
367 //
368 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
369 return RETURN_SUCCESS;
370 }
371
372 /**
373 Sets CPU feature bit mask in CPU feature bit mask buffer.
374
375 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
376 @param[in] Feature The bit number of the CPU feature
377 @param[in] BitMaskSize CPU feature bit mask buffer size
378 **/
379 VOID
380 SetCpuFeaturesBitMask (
381 IN UINT8 **FeaturesBitMask,
382 IN UINT32 Feature,
383 IN UINTN BitMaskSize
384 )
385 {
386 UINT8 *CpuFeaturesBitMask;
387
388 ASSERT (FeaturesBitMask != NULL);
389 CpuFeaturesBitMask = *FeaturesBitMask;
390 if (CpuFeaturesBitMask == NULL) {
391 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
392 ASSERT (CpuFeaturesBitMask != NULL);
393 *FeaturesBitMask = CpuFeaturesBitMask;
394 }
395
396 CpuFeaturesBitMask += (Feature / 8);
397 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
398 }
399
400 /**
401 Registers a CPU Feature.
402
403 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
404 name.
405 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
406 is an optional parameter that may be NULL. If NULL,
407 then the most recently registered function for the
408 CPU feature is used. If no functions are registered
409 for a CPU feature, then the CPU configuration data
410 for the registered feature is NULL.
411 @param[in] SupportFunc CPU feature support function. This is an optional
412 parameter that may be NULL. If NULL, then the most
413 recently registered function for the CPU feature is
414 used. If no functions are registered for a CPU
415 feature, then the CPU feature is assumed to be
416 supported by all CPUs.
417 @param[in] InitializeFunc CPU feature initialize function. This is an optional
418 parameter that may be NULL. If NULL, then the most
419 recently registered function for the CPU feature is
420 used. If no functions are registered for a CPU
421 feature, then the CPU feature initialization is
422 skipped.
423 @param[in] ... Variable argument list of UINT32 CPU feature value.
424 Values with no modifiers are the features provided
425 by the registered functions.
426 Values with CPU_FEATURE_BEFORE modifier are features
427 that must be initialized after the features provided
428 by the registered functions are used.
429 Values with CPU_FEATURE_AFTER modifier are features
430 that must be initialized before the features provided
431 by the registered functions are used.
432 The last argument in this variable argument list must
433 always be CPU_FEATURE_END.
434
435 @retval RETURN_SUCCESS The CPU feature was successfully registered.
436 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
437 the CPU feature.
438 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
439 supported due to a circular dependency between
440 BEFORE and AFTER features.
441
442 @note This service could be called by BSP only.
443 **/
444 RETURN_STATUS
445 EFIAPI
446 RegisterCpuFeature (
447 IN CHAR8 *FeatureName, OPTIONAL
448 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL
449 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL
450 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL
451 ...
452 )
453 {
454 EFI_STATUS Status;
455 VA_LIST Marker;
456 UINT32 Feature;
457 UINTN BitMaskSize;
458 CPU_FEATURES_ENTRY *CpuFeature;
459 UINT8 *FeatureMask;
460 UINT8 *BeforeFeatureBitMask;
461 UINT8 *AfterFeatureBitMask;
462 BOOLEAN BeforeAll;
463 BOOLEAN AfterAll;
464
465 FeatureMask = NULL;
466 BeforeFeatureBitMask = NULL;
467 AfterFeatureBitMask = NULL;
468 BeforeAll = FALSE;
469 AfterAll = FALSE;
470
471 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
472
473 VA_START (Marker, InitializeFunc);
474 Feature = VA_ARG (Marker, UINT32);
475 ASSERT (RegisterCpuFeatureLibIsFeatureValid(Feature));
476 while (Feature != CPU_FEATURE_END) {
477 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))
478 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));
479 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))
480 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));
481 if (Feature < CPU_FEATURE_BEFORE) {
482 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;
483 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;
484 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
485 ASSERT (FeatureMask == NULL);
486 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);
487 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {
488 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);
489 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {
490 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);
491 }
492 Feature = VA_ARG (Marker, UINT32);
493 }
494 VA_END (Marker);
495
496 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));
497 ASSERT (CpuFeature != NULL);
498 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;
499 CpuFeature->FeatureMask = FeatureMask;
500 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;
501 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;
502 CpuFeature->BeforeAll = BeforeAll;
503 CpuFeature->AfterAll = AfterAll;
504 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;
505 CpuFeature->SupportFunc = SupportFunc;
506 CpuFeature->InitializeFunc = InitializeFunc;
507 if (FeatureName != NULL) {
508 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
509 ASSERT (CpuFeature->FeatureName != NULL);
510 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);
511 ASSERT_EFI_ERROR (Status);
512 }
513
514 Status = RegisterCpuFeatureWorker (CpuFeature);
515 ASSERT_EFI_ERROR (Status);
516
517 return RETURN_SUCCESS;
518 }
519
520 /**
521 Add an entry in specified register table.
522
523 This function adds an entry in specified register table, with given register type,
524 register index, bit section and value.
525
526 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
527 If FALSE, entry will be added into register table
528 @param[in] ProcessorNumber The index of the CPU to add a register table entry
529 @param[in] RegisterType Type of the register to program
530 @param[in] Index Index of the register to program
531 @param[in] ValidBitStart Start of the bit section
532 @param[in] ValidBitLength Length of the bit section
533 @param[in] Value Value to write
534 **/
535 VOID
536 CpuRegisterTableWriteWorker (
537 IN BOOLEAN PreSmmFlag,
538 IN UINTN ProcessorNumber,
539 IN REGISTER_TYPE RegisterType,
540 IN UINT64 Index,
541 IN UINT8 ValidBitStart,
542 IN UINT8 ValidBitLength,
543 IN UINT64 Value
544 )
545 {
546 EFI_STATUS Status;
547 CPU_FEATURES_DATA *CpuFeaturesData;
548 ACPI_CPU_DATA *AcpiCpuData;
549 CPU_REGISTER_TABLE *RegisterTable;
550 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
551
552 CpuFeaturesData = GetCpuFeaturesData ();
553 if (CpuFeaturesData->RegisterTable == NULL) {
554 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
555 if (AcpiCpuData == NULL) {
556 AcpiCpuData = AllocateAcpiCpuData ();
557 ASSERT (AcpiCpuData != NULL);
558 //
559 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
560 //
561 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
562 ASSERT_EFI_ERROR (Status);
563 }
564 ASSERT (AcpiCpuData->RegisterTable != 0);
565 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;
566 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;
567 }
568
569 if (PreSmmFlag) {
570 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
571 } else {
572 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
573 }
574
575 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
576 EnlargeRegisterTable (RegisterTable);
577 }
578
579 //
580 // Append entry in the register table.
581 //
582 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
583 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
584 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;
585 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);
586 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
587 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
588 RegisterTableEntry[RegisterTable->TableLength].Value = Value;
589
590 RegisterTable->TableLength++;
591 }
592
593 /**
594 Adds an entry in specified register table.
595
596 This function adds an entry in specified register table, with given register type,
597 register index, bit section and value.
598
599 @param[in] ProcessorNumber The index of the CPU to add a register table entry
600 @param[in] RegisterType Type of the register to program
601 @param[in] Index Index of the register to program
602 @param[in] ValueMask Mask of bits in register to write
603 @param[in] Value Value to write
604
605 @note This service could be called by BSP only.
606 **/
607 VOID
608 EFIAPI
609 CpuRegisterTableWrite (
610 IN UINTN ProcessorNumber,
611 IN REGISTER_TYPE RegisterType,
612 IN UINT64 Index,
613 IN UINT64 ValueMask,
614 IN UINT64 Value
615 )
616 {
617 UINT8 Start;
618 UINT8 End;
619 UINT8 Length;
620
621 Start = (UINT8)LowBitSet64 (ValueMask);
622 End = (UINT8)HighBitSet64 (ValueMask);
623 Length = End - Start + 1;
624 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
625 }
626
627 /**
628 Adds an entry in specified Pre-SMM register table.
629
630 This function adds an entry in specified register table, with given register type,
631 register index, bit section and value.
632
633 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
634 @param[in] RegisterType Type of the register to program
635 @param[in] Index Index of the register to program
636 @param[in] ValueMask Mask of bits in register to write
637 @param[in] Value Value to write
638
639 @note This service could be called by BSP only.
640 **/
641 VOID
642 EFIAPI
643 PreSmmCpuRegisterTableWrite (
644 IN UINTN ProcessorNumber,
645 IN REGISTER_TYPE RegisterType,
646 IN UINT64 Index,
647 IN UINT64 ValueMask,
648 IN UINT64 Value
649 )
650 {
651 UINT8 Start;
652 UINT8 End;
653 UINT8 Length;
654
655 Start = (UINT8)LowBitSet64 (ValueMask);
656 End = (UINT8)HighBitSet64 (ValueMask);
657 Length = End - Start + 1;
658 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
659 }
660
661 /**
662 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
663
664 @param[in] CpuBitMask CPU feature bit mask buffer
665 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
666 @param[in] Feature The bit number of the CPU feature
667
668 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
669 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
670
671 **/
672 BOOLEAN
673 IsCpuFeatureSetInCpuPcd (
674 IN UINT8 *CpuBitMask,
675 IN UINTN CpuBitMaskSize,
676 IN UINT32 Feature
677 )
678 {
679 if ((Feature >> 3) >= CpuBitMaskSize) {
680 return FALSE;
681 }
682 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
683 }
684
685 /**
686 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
687 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
688 associated with that feature should be optimized away if compiler
689 optimizations are enabled.
690
691 @param[in] Feature The bit number of the CPU feature to check in the PCD
692 PcdCpuFeaturesSupport
693
694 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
695 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
696
697 @note This service could be called by BSP only.
698 **/
699 BOOLEAN
700 EFIAPI
701 IsCpuFeatureSupported (
702 IN UINT32 Feature
703 )
704 {
705 return IsCpuFeatureSetInCpuPcd (
706 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
707 PcdGetSize (PcdCpuFeaturesSupport),
708 Feature
709 );
710 }
711
712 /**
713 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
714
715 @param[in] Feature The bit number of the CPU feature to check in the PCD
716 PcdCpuFeaturesSetting
717
718 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
719 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
720
721 @note This service could be called by BSP only.
722 **/
723 BOOLEAN
724 EFIAPI
725 IsCpuFeatureInSetting (
726 IN UINT32 Feature
727 )
728 {
729 return IsCpuFeatureSetInCpuPcd (
730 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
731 PcdGetSize (PcdCpuFeaturesSetting),
732 Feature
733 );
734 }
735
736 /**
737 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
738
739 @param[in] Feature The bit number of the CPU feature to check in the PCD
740 PcdCpuFeaturesCapability
741
742 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
743 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
744
745 @note This service could be called by BSP only.
746 **/
747 BOOLEAN
748 EFIAPI
749 IsCpuFeatureCapability (
750 IN UINT32 Feature
751 )
752 {
753 return IsCpuFeatureSetInCpuPcd (
754 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
755 PcdGetSize (PcdCpuFeaturesCapability),
756 Feature
757 );
758
759 }
760
761 /**
762 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
763
764 @param[in] Feature The bit number of the CPU feature to check in the PCD
765 PcdCpuFeaturesUserConfiguration
766
767 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
768 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
769
770 @note This service could be called by BSP only.
771 **/
772 BOOLEAN
773 EFIAPI
774 IsCpuFeatureUserConfiguration (
775 IN UINT32 Feature
776 )
777 {
778 return IsCpuFeatureSetInCpuPcd (
779 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
780 PcdGetSize (PcdCpuFeaturesUserConfiguration),
781 Feature
782 );
783
784 }
785
786 /**
787 Switches to assigned BSP after CPU features initialization.
788
789 @param[in] ProcessorNumber The index of the CPU executing this function.
790
791 @note This service could be called by BSP only.
792 **/
793 VOID
794 EFIAPI
795 SwitchBspAfterFeaturesInitialize (
796 IN UINTN ProcessorNumber
797 )
798 {
799 CPU_FEATURES_DATA *CpuFeaturesData;
800
801 CpuFeaturesData = GetCpuFeaturesData ();
802 CpuFeaturesData->BspNumber = ProcessorNumber;
803 }
804