]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
ArmPkg/ArmExceptionLib: use EL0 stack for synchronous exceptions
[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
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**/
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
375 @param GetConfigDataFunc CPU feature get configuration data function. This
376 is an optional parameter that may be NULL. If NULL,
377 then the most recently registered function for the
378 CPU feature is used. If no functions are registered
379 for a CPU feature, then the CPU configuration data
380 for the registered feature is NULL.
381 @param SupportFunc CPU feature support function. This is an optional
382 parameter that may be NULL. If NULL, then the most
383 recently registered function for the CPU feature is
384 used. If no functions are registered for a CPU
385 feature, then the CPU feature is assumed to be
386 supported by all CPUs.
387 @param InitializeFunc CPU feature initialize function. This is an optional
388 parameter that may be NULL. If NULL, then the most
389 recently registered function for the CPU feature is
390 used. If no functions are registered for a CPU
391 feature, then the CPU feature initialization is
392 skipped.
393 @param ... Variable argument list of UINT32 CPU feature value.
394 Values with no modifiers are the features provided
395 by the registered functions.
396 Values with CPU_FEATURE_BEFORE modifier are features
397 that must be initialized after the features provided
398 by the registered functions are used.
399 Values with CPU_FEATURE_AFTER modifier are features
400 that must be initialized before the features provided
401 by the registered functions are used.
402 The last argument in this variable argument list must
403 always be CPU_FEATURE_END.
404
405 @retval RETURN_SUCCESS The CPU feature was successfully registered.
406 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
407 the CPU feature.
408 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
409 supported due to a circular dependency between
410 BEFORE and AFTER features.
411
412 @note This service could be called by BSP only.
413**/
414RETURN_STATUS
415EFIAPI
416RegisterCpuFeature (
417 IN CHAR8 *FeatureName, OPTIONAL
418 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL
419 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL
420 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL
421 ...
422 )
423{
424 EFI_STATUS Status;
425 VA_LIST Marker;
426 UINT32 Feature;
427 UINTN BitMaskSize;
428 CPU_FEATURES_ENTRY *CpuFeature;
429 UINT8 *FeatureMask;
430 UINT8 *BeforeFeatureBitMask;
431 UINT8 *AfterFeatureBitMask;
432 BOOLEAN BeforeAll;
433 BOOLEAN AfterAll;
434
435 FeatureMask = NULL;
436 BeforeFeatureBitMask = NULL;
437 AfterFeatureBitMask = NULL;
438 BeforeAll = FALSE;
439 AfterAll = FALSE;
440
441 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
442
443 VA_START (Marker, InitializeFunc);
444 Feature = VA_ARG (Marker, UINT32);
445 while (Feature != CPU_FEATURE_END) {
446 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))
447 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));
448 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))
449 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));
450 if (Feature < CPU_FEATURE_BEFORE) {
451 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;
452 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;
453 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
454 ASSERT (FeatureMask == NULL);
455 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);
456 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {
457 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);
458 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {
459 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);
460 }
461 Feature = VA_ARG (Marker, UINT32);
462 }
463 VA_END (Marker);
464
465 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));
466 ASSERT (CpuFeature != NULL);
467 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;
468 CpuFeature->FeatureMask = FeatureMask;
469 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;
470 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;
471 CpuFeature->BeforeAll = BeforeAll;
472 CpuFeature->AfterAll = AfterAll;
473 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;
474 CpuFeature->SupportFunc = SupportFunc;
475 CpuFeature->InitializeFunc = InitializeFunc;
476 if (FeatureName != NULL) {
477 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
478 ASSERT (CpuFeature->FeatureName != NULL);
479 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);
480 ASSERT_EFI_ERROR (Status);
481 }
482
483 Status = RegisterCpuFeatureWorker (CpuFeature);
484 ASSERT_EFI_ERROR (Status);
485
486 return RETURN_SUCCESS;
487}
488
489/**
490 Add an entry in specified register table.
491
492 This function adds an entry in specified register table, with given register type,
493 register index, bit section and value.
494
495 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
496 If FALSE, entry will be added into register table
497 @param[in] ProcessorNumber The index of the CPU to add a register table entry
498 @param[in] RegisterType Type of the register to program
499 @param[in] Index Index of the register to program
500 @param[in] ValidBitStart Start of the bit section
501 @param[in] ValidBitLength Length of the bit section
502 @param[in] Value Value to write
503**/
504VOID
505CpuRegisterTableWriteWorker (
506 IN BOOLEAN PreSmmFlag,
507 IN UINTN ProcessorNumber,
508 IN REGISTER_TYPE RegisterType,
98387f54 509 IN UINT64 Index,
eff78ac3
JF
510 IN UINT8 ValidBitStart,
511 IN UINT8 ValidBitLength,
512 IN UINT64 Value
513 )
514{
515 EFI_STATUS Status;
516 CPU_FEATURES_DATA *CpuFeaturesData;
517 ACPI_CPU_DATA *AcpiCpuData;
518 CPU_REGISTER_TABLE *RegisterTable;
519 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
520
521 CpuFeaturesData = GetCpuFeaturesData ();
522 if (CpuFeaturesData->RegisterTable == NULL) {
523 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
524 if (AcpiCpuData == NULL) {
525 AcpiCpuData = AllocateAcpiCpuData ();
526 ASSERT (AcpiCpuData != NULL);
527 //
528 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
529 //
530 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
531 ASSERT_EFI_ERROR (Status);
532 }
533 ASSERT (AcpiCpuData->RegisterTable != 0);
534 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;
535 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;
536 }
537
538 if (PreSmmFlag) {
539 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
540 } else {
541 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
542 }
543
544 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
545 EnlargeRegisterTable (RegisterTable);
546 }
547
548 //
549 // Append entry in the register table.
550 //
551 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
552 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
98387f54 553 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;
30b7a50b 554 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);
eff78ac3
JF
555 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
556 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
557 RegisterTableEntry[RegisterTable->TableLength].Value = Value;
558
559 RegisterTable->TableLength++;
560}
561
562/**
563 Adds an entry in specified register table.
564
565 This function adds an entry in specified register table, with given register type,
566 register index, bit section and value.
567
568 @param[in] ProcessorNumber The index of the CPU to add a register table entry
569 @param[in] RegisterType Type of the register to program
570 @param[in] Index Index of the register to program
571 @param[in] ValueMask Mask of bits in register to write
572 @param[in] Value Value to write
573
574 @note This service could be called by BSP only.
575**/
576VOID
577EFIAPI
578CpuRegisterTableWrite (
579 IN UINTN ProcessorNumber,
580 IN REGISTER_TYPE RegisterType,
98387f54 581 IN UINT64 Index,
eff78ac3
JF
582 IN UINT64 ValueMask,
583 IN UINT64 Value
584 )
585{
586 UINT8 Start;
587 UINT8 End;
588 UINT8 Length;
589
590 Start = (UINT8)LowBitSet64 (ValueMask);
591 End = (UINT8)HighBitSet64 (ValueMask);
592 Length = End - Start + 1;
593 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
594}
595
596/**
597 Adds an entry in specified Pre-SMM register table.
598
599 This function adds an entry in specified register table, with given register type,
600 register index, bit section and value.
601
602 @param[in] ProcessorNumber The index of the CPU to add a register table entry.
603 @param[in] RegisterType Type of the register to program
604 @param[in] Index Index of the register to program
605 @param[in] ValueMask Mask of bits in register to write
606 @param[in] Value Value to write
607
608 @note This service could be called by BSP only.
609**/
610VOID
611EFIAPI
612PreSmmCpuRegisterTableWrite (
613 IN UINTN ProcessorNumber,
614 IN REGISTER_TYPE RegisterType,
98387f54 615 IN UINT64 Index,
eff78ac3
JF
616 IN UINT64 ValueMask,
617 IN UINT64 Value
618 )
619{
620 UINT8 Start;
621 UINT8 End;
622 UINT8 Length;
623
624 Start = (UINT8)LowBitSet64 (ValueMask);
625 End = (UINT8)HighBitSet64 (ValueMask);
626 Length = End - Start + 1;
627 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
628}
629
630/**
631 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
632
633 @param[in] CpuBitMask CPU feature bit mask buffer
634 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
635 @param[in] Feature The bit number of the CPU feature
636
637 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
638 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
639
640**/
641BOOLEAN
642IsCpuFeatureSetInCpuPcd (
643 IN UINT8 *CpuBitMask,
644 IN UINTN CpuBitMaskSize,
645 IN UINT32 Feature
646 )
647{
648 if ((Feature >> 3) >= CpuBitMaskSize) {
649 return FALSE;
650 }
651 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
652}
653
654/**
655 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
656 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
657 associated with that feature should be optimized away if compiler
658 optimizations are enabled.
659
660 @param[in] Feature The bit number of the CPU feature to check in the PCD
661 PcdCpuFeaturesSupport
662
663 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
664 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
665
666 @note This service could be called by BSP only.
667**/
668BOOLEAN
669EFIAPI
670IsCpuFeatureSupported (
671 IN UINT32 Feature
672 )
673{
674 return IsCpuFeatureSetInCpuPcd (
675 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
676 PcdGetSize (PcdCpuFeaturesSupport),
677 Feature
678 );
679}
680
681/**
682 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
683
684 @param[in] Feature The bit number of the CPU feature to check in the PCD
685 PcdCpuFeaturesSetting
686
687 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
688 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
689
690 @note This service could be called by BSP only.
691**/
692BOOLEAN
693EFIAPI
694IsCpuFeatureInSetting (
695 IN UINT32 Feature
696 )
697{
698 return IsCpuFeatureSetInCpuPcd (
699 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
700 PcdGetSize (PcdCpuFeaturesSetting),
701 Feature
702 );
703}
704
705/**
706 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
707
708 @param[in] Feature The bit number of the CPU feature to check in the PCD
709 PcdCpuFeaturesCapability
710
711 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
712 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
713
714 @note This service could be called by BSP only.
715**/
716BOOLEAN
717EFIAPI
718IsCpuFeatureCapability (
719 IN UINT32 Feature
720 )
721{
722 return IsCpuFeatureSetInCpuPcd (
723 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
724 PcdGetSize (PcdCpuFeaturesCapability),
725 Feature
726 );
727
728}
729
730/**
731 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
732
733 @param[in] Feature The bit number of the CPU feature to check in the PCD
734 PcdCpuFeaturesUserConfiguration
735
736 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
737 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
738
739 @note This service could be called by BSP only.
740**/
741BOOLEAN
742EFIAPI
743IsCpuFeatureUserConfiguration (
744 IN UINT32 Feature
745 )
746{
747 return IsCpuFeatureSetInCpuPcd (
748 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
749 PcdGetSize (PcdCpuFeaturesUserConfiguration),
750 Feature
751 );
752
753}
754
755/**
756 Switches to assigned BSP after CPU features initialization.
757
758 @param[in] ProcessorNumber The index of the CPU executing this function.
759
760 @note This service could be called by BSP only.
761**/
762VOID
763EFIAPI
764SwitchBspAfterFeaturesInitialize (
765 IN UINTN ProcessorNumber
766 )
767{
768 CPU_FEATURES_DATA *CpuFeaturesData;
769
770 CpuFeaturesData = GetCpuFeaturesData ();
771 CpuFeaturesData->BspNumber = ProcessorNumber;
772}
773