]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
ShellPkg/setvar: Add assertion indicating TempData shouldn't be NULL
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / RegisterCpuFeaturesLib.c
CommitLineData
eff78ac3
JF
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**/
26BOOLEAN
27IsCpuFeatureMatch (
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**/
47VOID
48DumpCpuFeatureMask (
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**/
69VOID
70DumpCpuFeature (
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**/
92BOOLEAN
93IsBitMaskMatchCheck (
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**/
120VOID
121CheckCpuFeaturesDependency (
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
8d5df9d7 243 @param[in] CpuFeature Pointer to CPU feature entry
eff78ac3
JF
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**/
252RETURN_STATUS
253RegisterCpuFeatureWorker (
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;
cab6b79c 275 CpuFeatureEntry = NULL;
eff78ac3
JF
276 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
277 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
278 CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
279 if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {
280 //
281 // If this feature already registered
282 //
283 FeatureExist = TRUE;
284 break;
285 }
286 Entry = Entry->ForwardLink;
287 }
288
289 if (!FeatureExist) {
290 DEBUG ((DEBUG_INFO, "[NEW] "));
291 DumpCpuFeature (CpuFeature);
292 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
293 CpuFeaturesData->FeaturesCount++;
294 } else {
295 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
296 DumpCpuFeature (CpuFeature);
cab6b79c 297 ASSERT (CpuFeatureEntry != NULL);
eff78ac3
JF
298 //
299 // Overwrite original parameters of CPU feature
300 //
301 if (CpuFeature->GetConfigDataFunc != NULL) {
302 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
303 }
304 if (CpuFeature->SupportFunc != NULL) {
305 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
306 }
307 if (CpuFeature->InitializeFunc != NULL) {
308 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
309 }
310 if (CpuFeature->FeatureName != NULL) {
311 if (CpuFeatureEntry->FeatureName == NULL) {
312 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
313 ASSERT (CpuFeatureEntry->FeatureName != NULL);
314 }
315 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
316 ASSERT_EFI_ERROR (Status);
317 FreePool (CpuFeature->FeatureName);
318 }
319 if (CpuFeature->BeforeFeatureBitMask != NULL) {
320 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
321 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
322 }
323 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
324 }
325 if (CpuFeature->AfterFeatureBitMask != NULL) {
326 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
327 FreePool (CpuFeatureEntry->AfterFeatureBitMask);
328 }
329 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
330 }
331 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
332 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;
333
334 FreePool (CpuFeature->FeatureMask);
335 FreePool (CpuFeature);
336 }
337 //
338 // Verify CPU features dependency can change CPU feature order
339 //
340 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
341 return RETURN_SUCCESS;
342}
343
344/**
345 Sets CPU feature bit mask in CPU feature bit mask buffer.
346
347 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
348 @param[in] Feature The bit number of the CPU feature
349 @param[in] BitMaskSize CPU feature bit mask buffer size
350**/
351VOID
352SetCpuFeaturesBitMask (
353 IN UINT8 **FeaturesBitMask,
354 IN UINT32 Feature,
355 IN UINTN BitMaskSize
356 )
357{
358 UINT8 *CpuFeaturesBitMask;
359
360 ASSERT (FeaturesBitMask != NULL);
361 CpuFeaturesBitMask = *FeaturesBitMask;
362 if (CpuFeaturesBitMask == NULL) {
363 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
364 ASSERT (CpuFeaturesBitMask != NULL);
365 *FeaturesBitMask = CpuFeaturesBitMask;
366 }
367
368 CpuFeaturesBitMask += (Feature / 8);
369 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
370}
371
372/**
373 Registers a CPU Feature.
374
8d5df9d7
JF
375 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
376 name.
377 @param[in] GetConfigDataFunc CPU feature get configuration data function. This
378 is an optional parameter that may be NULL. If NULL,
379 then the most recently registered function for the
380 CPU feature is used. If no functions are registered
381 for a CPU feature, then the CPU configuration data
382 for the registered feature is NULL.
383 @param[in] SupportFunc CPU feature support function. This is an optional
384 parameter that may be NULL. If NULL, then the most
385 recently registered function for the CPU feature is
386 used. If no functions are registered for a CPU
387 feature, then the CPU feature is assumed to be
388 supported by all CPUs.
389 @param[in] InitializeFunc CPU feature initialize function. This is an optional
390 parameter that may be NULL. If NULL, then the most
391 recently registered function for the CPU feature is
392 used. If no functions are registered for a CPU
393 feature, then the CPU feature initialization is
394 skipped.
395 @param[in] ... Variable argument list of UINT32 CPU feature value.
396 Values with no modifiers are the features provided
397 by the registered functions.
398 Values with CPU_FEATURE_BEFORE modifier are features
399 that must be initialized after the features provided
400 by the registered functions are used.
401 Values with CPU_FEATURE_AFTER modifier are features
402 that must be initialized before the features provided
403 by the registered functions are used.
404 The last argument in this variable argument list must
405 always be CPU_FEATURE_END.
eff78ac3
JF
406
407 @retval RETURN_SUCCESS The CPU feature was successfully registered.
408 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
409 the CPU feature.
410 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
411 supported due to a circular dependency between
412 BEFORE and AFTER features.
413
414 @note This service could be called by BSP only.
415**/
416RETURN_STATUS
417EFIAPI
418RegisterCpuFeature (
419 IN CHAR8 *FeatureName, OPTIONAL
420 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL
421 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL
422 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL
423 ...
424 )
425{
426 EFI_STATUS Status;
427 VA_LIST Marker;
428 UINT32 Feature;
429 UINTN BitMaskSize;
430 CPU_FEATURES_ENTRY *CpuFeature;
431 UINT8 *FeatureMask;
432 UINT8 *BeforeFeatureBitMask;
433 UINT8 *AfterFeatureBitMask;
434 BOOLEAN BeforeAll;
435 BOOLEAN AfterAll;
436
437 FeatureMask = NULL;
438 BeforeFeatureBitMask = NULL;
439 AfterFeatureBitMask = NULL;
440 BeforeAll = FALSE;
441 AfterAll = FALSE;
442
443 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
444
445 VA_START (Marker, InitializeFunc);
446 Feature = VA_ARG (Marker, UINT32);
447 while (Feature != CPU_FEATURE_END) {
448 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))
449 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));
450 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))
451 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));
452 if (Feature < CPU_FEATURE_BEFORE) {
453 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;
454 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;
455 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
456 ASSERT (FeatureMask == NULL);
457 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);
458 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {
459 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);
460 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {
461 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);
462 }
463 Feature = VA_ARG (Marker, UINT32);
464 }
465 VA_END (Marker);
466
467 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));
468 ASSERT (CpuFeature != NULL);
469 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;
470 CpuFeature->FeatureMask = FeatureMask;
471 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;
472 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;
473 CpuFeature->BeforeAll = BeforeAll;
474 CpuFeature->AfterAll = AfterAll;
475 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;
476 CpuFeature->SupportFunc = SupportFunc;
477 CpuFeature->InitializeFunc = InitializeFunc;
478 if (FeatureName != NULL) {
479 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
480 ASSERT (CpuFeature->FeatureName != NULL);
481 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);
482 ASSERT_EFI_ERROR (Status);
483 }
484
485 Status = RegisterCpuFeatureWorker (CpuFeature);
486 ASSERT_EFI_ERROR (Status);
487
488 return RETURN_SUCCESS;
489}
490
491/**
492 Add an entry in specified register table.
493
494 This function adds an entry in specified register table, with given register type,
495 register index, bit section and value.
496
497 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
498 If FALSE, entry will be added into register table
499 @param[in] ProcessorNumber The index of the CPU to add a register table entry
500 @param[in] RegisterType Type of the register to program
501 @param[in] Index Index of the register to program
502 @param[in] ValidBitStart Start of the bit section
503 @param[in] ValidBitLength Length of the bit section
504 @param[in] Value Value to write
505**/
506VOID
507CpuRegisterTableWriteWorker (
508 IN BOOLEAN PreSmmFlag,
509 IN UINTN ProcessorNumber,
510 IN REGISTER_TYPE RegisterType,
98387f54 511 IN UINT64 Index,
eff78ac3
JF
512 IN UINT8 ValidBitStart,
513 IN UINT8 ValidBitLength,
514 IN UINT64 Value
515 )
516{
517 EFI_STATUS Status;
518 CPU_FEATURES_DATA *CpuFeaturesData;
519 ACPI_CPU_DATA *AcpiCpuData;
520 CPU_REGISTER_TABLE *RegisterTable;
521 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
522
523 CpuFeaturesData = GetCpuFeaturesData ();
524 if (CpuFeaturesData->RegisterTable == NULL) {
525 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
526 if (AcpiCpuData == NULL) {
527 AcpiCpuData = AllocateAcpiCpuData ();
528 ASSERT (AcpiCpuData != NULL);
529 //
530 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
531 //
532 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
533 ASSERT_EFI_ERROR (Status);
534 }
535 ASSERT (AcpiCpuData->RegisterTable != 0);
536 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;
537 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;
538 }
539
540 if (PreSmmFlag) {
541 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
542 } else {
543 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
544 }
545
546 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
547 EnlargeRegisterTable (RegisterTable);
548 }
549
550 //
551 // Append entry in the register table.
552 //
553 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
554 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
98387f54 555 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;
30b7a50b 556 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);
eff78ac3
JF
557 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
558 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
559 RegisterTableEntry[RegisterTable->TableLength].Value = Value;
560
561 RegisterTable->TableLength++;
562}
563
564/**
565 Adds an entry in specified register table.
566
567 This function adds an entry in specified register table, with given register type,
568 register index, bit section and value.
569
570 @param[in] ProcessorNumber The index of the CPU to add a register table entry
571 @param[in] RegisterType Type of the register to program
572 @param[in] Index Index of the register to program
573 @param[in] ValueMask Mask of bits in register to write
574 @param[in] Value Value to write
575
576 @note This service could be called by BSP only.
577**/
578VOID
579EFIAPI
580CpuRegisterTableWrite (
581 IN UINTN ProcessorNumber,
582 IN REGISTER_TYPE RegisterType,
98387f54 583 IN UINT64 Index,
eff78ac3
JF
584 IN UINT64 ValueMask,
585 IN UINT64 Value
586 )
587{
588 UINT8 Start;
589 UINT8 End;
590 UINT8 Length;
591
592 Start = (UINT8)LowBitSet64 (ValueMask);
593 End = (UINT8)HighBitSet64 (ValueMask);
594 Length = End - Start + 1;
595 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
596}
597
598/**
599 Adds an entry in specified Pre-SMM register table.
600
601 This function adds an entry in specified register table, with given register type,
602 register index, bit section and value.
603
604 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
605 @param[in] RegisterType Type of the register to program
606 @param[in] Index Index of the register to program
607 @param[in] ValueMask Mask of bits in register to write
608 @param[in] Value Value to write
609
610 @note This service could be called by BSP only.
611**/
612VOID
613EFIAPI
614PreSmmCpuRegisterTableWrite (
615 IN UINTN ProcessorNumber,
616 IN REGISTER_TYPE RegisterType,
98387f54 617 IN UINT64 Index,
eff78ac3
JF
618 IN UINT64 ValueMask,
619 IN UINT64 Value
620 )
621{
622 UINT8 Start;
623 UINT8 End;
624 UINT8 Length;
625
626 Start = (UINT8)LowBitSet64 (ValueMask);
627 End = (UINT8)HighBitSet64 (ValueMask);
628 Length = End - Start + 1;
629 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
630}
631
632/**
633 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
634
635 @param[in] CpuBitMask CPU feature bit mask buffer
636 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
637 @param[in] Feature The bit number of the CPU feature
638
639 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
640 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
641
642**/
643BOOLEAN
644IsCpuFeatureSetInCpuPcd (
645 IN UINT8 *CpuBitMask,
646 IN UINTN CpuBitMaskSize,
647 IN UINT32 Feature
648 )
649{
650 if ((Feature >> 3) >= CpuBitMaskSize) {
651 return FALSE;
652 }
653 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
654}
655
656/**
657 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
658 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
659 associated with that feature should be optimized away if compiler
660 optimizations are enabled.
661
662 @param[in] Feature The bit number of the CPU feature to check in the PCD
663 PcdCpuFeaturesSupport
664
665 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
666 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
667
668 @note This service could be called by BSP only.
669**/
670BOOLEAN
671EFIAPI
672IsCpuFeatureSupported (
673 IN UINT32 Feature
674 )
675{
676 return IsCpuFeatureSetInCpuPcd (
677 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
678 PcdGetSize (PcdCpuFeaturesSupport),
679 Feature
680 );
681}
682
683/**
684 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
685
686 @param[in] Feature The bit number of the CPU feature to check in the PCD
687 PcdCpuFeaturesSetting
688
689 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
690 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
691
692 @note This service could be called by BSP only.
693**/
694BOOLEAN
695EFIAPI
696IsCpuFeatureInSetting (
697 IN UINT32 Feature
698 )
699{
700 return IsCpuFeatureSetInCpuPcd (
701 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
702 PcdGetSize (PcdCpuFeaturesSetting),
703 Feature
704 );
705}
706
707/**
708 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
709
710 @param[in] Feature The bit number of the CPU feature to check in the PCD
711 PcdCpuFeaturesCapability
712
713 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
714 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
715
716 @note This service could be called by BSP only.
717**/
718BOOLEAN
719EFIAPI
720IsCpuFeatureCapability (
721 IN UINT32 Feature
722 )
723{
724 return IsCpuFeatureSetInCpuPcd (
725 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
726 PcdGetSize (PcdCpuFeaturesCapability),
727 Feature
728 );
729
730}
731
732/**
733 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
734
735 @param[in] Feature The bit number of the CPU feature to check in the PCD
736 PcdCpuFeaturesUserConfiguration
737
738 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
739 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
740
741 @note This service could be called by BSP only.
742**/
743BOOLEAN
744EFIAPI
745IsCpuFeatureUserConfiguration (
746 IN UINT32 Feature
747 )
748{
749 return IsCpuFeatureSetInCpuPcd (
750 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
751 PcdGetSize (PcdCpuFeaturesUserConfiguration),
752 Feature
753 );
754
755}
756
757/**
758 Switches to assigned BSP after CPU features initialization.
759
760 @param[in] ProcessorNumber The index of the CPU executing this function.
761
762 @note This service could be called by BSP only.
763**/
764VOID
765EFIAPI
766SwitchBspAfterFeaturesInitialize (
767 IN UINTN ProcessorNumber
768 )
769{
770 CPU_FEATURES_DATA *CpuFeaturesData;
771
772 CpuFeaturesData = GetCpuFeaturesData ();
773 CpuFeaturesData->BspNumber = ProcessorNumber;
774}
775