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