diff options
Diffstat (limited to 'UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c')
-rw-r--r-- | UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c | 1550 |
1 files changed, 775 insertions, 775 deletions
diff --git a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c index 7ef0155374..338f1a495c 100644 --- a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c +++ b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c @@ -1,775 +1,775 @@ -/** @file - CPU Register Table Library functions. - - Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "RegisterCpuFeatures.h" - -/** - Checks if two CPU feature bit masks are equal. - - @param[in] FirstFeatureMask The first input CPU feature bit mask - @param[in] SecondFeatureMask The second input CPU feature bit mask - - @retval TRUE Two CPU feature bit masks are equal. - @retval FALSE Two CPU feature bit masks are not equal. -**/ -BOOLEAN -IsCpuFeatureMatch ( - IN UINT8 *FirstFeatureMask, - IN UINT8 *SecondFeatureMask - ) -{ - UINT32 BitMaskSize; - - BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport); - if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) { - return TRUE; - } else { - return FALSE; - } -} - -/** - Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask. - - @param[in] FeatureMask A pointer to the CPU feature bit mask. -**/ -VOID -DumpCpuFeatureMask ( - IN UINT8 *FeatureMask - ) -{ - UINTN Index; - UINT8 *Data8; - UINT32 BitMaskSize; - - BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport); - Data8 = (UINT8 *) FeatureMask; - for (Index = 0; Index < BitMaskSize; Index++) { - DEBUG ((DEBUG_INFO, " %02x ", *Data8++)); - } - DEBUG ((DEBUG_INFO, "\n")); -} - -/** - Dump CPU feature name or CPU feature bit mask. - - @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY -**/ -VOID -DumpCpuFeature ( - IN CPU_FEATURES_ENTRY *CpuFeature - ) -{ - - if (CpuFeature->FeatureName != NULL) { - DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName)); - } else { - DEBUG ((DEBUG_INFO, "FeatureMask = ")); - DumpCpuFeatureMask (CpuFeature->FeatureMask); - } -} - -/** - Determines if the feature bit mask is in dependent CPU feature bit mask buffer. - - @param[in] FeatureMask Pointer to CPU feature bit mask - @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer - - @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer. - @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer. -**/ -BOOLEAN -IsBitMaskMatchCheck ( - IN UINT8 *FeatureMask, - IN UINT8 *DependentBitMask - ) -{ - UINTN Index; - UINTN BitMaskSize; - UINT8 *Data1; - UINT8 *Data2; - - BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport); - - Data1 = FeatureMask; - Data2 = DependentBitMask; - for (Index = 0; Index < BitMaskSize; Index++) { - if (((*(Data1++)) & (*(Data2++))) != 0) { - return TRUE; - } - } - return FALSE; -} - -/** - Checks and adjusts CPU features order per dependency relationship. - - @param[in] FeatureList Pointer to CPU feature list -**/ -VOID -CheckCpuFeaturesDependency ( - IN LIST_ENTRY *FeatureList - ) -{ - LIST_ENTRY *CurrentEntry; - CPU_FEATURES_ENTRY *CpuFeature; - LIST_ENTRY *CheckEntry; - CPU_FEATURES_ENTRY *CheckFeature; - BOOLEAN Swapped; - LIST_ENTRY *TempEntry; - - CurrentEntry = GetFirstNode (FeatureList); - while (!IsNull (FeatureList, CurrentEntry)) { - Swapped = FALSE; - CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry); - if (CpuFeature->BeforeAll) { - // - // Check all features dispatched before this entry - // - CheckEntry = GetFirstNode (FeatureList); - while (CheckEntry != CurrentEntry) { - CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry); - if (!CheckFeature->BeforeAll) { - // - // If this feature has no BeforeAll flag and is dispatched before CpuFeature, - // insert currentEntry before Checked feature - // - RemoveEntryList (CurrentEntry); - InsertTailList (CheckEntry, CurrentEntry); - Swapped = TRUE; - break; - } - CheckEntry = CheckEntry->ForwardLink; - } - if (Swapped) { - continue; - } - } - - if (CpuFeature->AfterAll) { - // - // Check all features dispatched after this entry - // - CheckEntry = GetNextNode (FeatureList, CurrentEntry); - while (!IsNull (FeatureList, CheckEntry)) { - CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry); - if (!CheckFeature->AfterAll) { - // - // If this feature has no AfterAll flag and is dispatched after CpuFeature, - // insert currentEntry after Checked feature - // - TempEntry = GetNextNode (FeatureList, CurrentEntry); - RemoveEntryList (CurrentEntry); - InsertHeadList (CheckEntry, CurrentEntry); - CurrentEntry = TempEntry; - Swapped = TRUE; - break; - } - CheckEntry = CheckEntry->ForwardLink; - } - if (Swapped) { - continue; - } - } - - if (CpuFeature->BeforeFeatureBitMask != NULL) { - // - // Check all features dispatched before this entry - // - CheckEntry = GetFirstNode (FeatureList); - while (CheckEntry != CurrentEntry) { - CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry); - if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) { - // - // If there is dependency, swap them - // - RemoveEntryList (CurrentEntry); - InsertTailList (CheckEntry, CurrentEntry); - Swapped = TRUE; - break; - } - CheckEntry = CheckEntry->ForwardLink; - } - if (Swapped) { - continue; - } - } - - if (CpuFeature->AfterFeatureBitMask != NULL) { - // - // Check all features dispatched after this entry - // - CheckEntry = GetNextNode (FeatureList, CurrentEntry); - while (!IsNull (FeatureList, CheckEntry)) { - CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry); - if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) { - // - // If there is dependency, swap them - // - TempEntry = GetNextNode (FeatureList, CurrentEntry); - RemoveEntryList (CurrentEntry); - InsertHeadList (CheckEntry, CurrentEntry); - CurrentEntry = TempEntry; - Swapped = TRUE; - break; - } - CheckEntry = CheckEntry->ForwardLink; - } - if (Swapped) { - continue; - } - } - // - // No swap happened, check the next feature - // - CurrentEntry = CurrentEntry->ForwardLink; - } -} - -/** - Worker function to register CPU Feature. - - @param[in] CpuFeature Pointer to CPU feature entry - - @retval RETURN_SUCCESS The CPU feature was successfully registered. - @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register - the CPU feature. - @retval RETURN_UNSUPPORTED Registration of the CPU feature is not - supported due to a circular dependency between - BEFORE and AFTER features. -**/ -RETURN_STATUS -RegisterCpuFeatureWorker ( - IN CPU_FEATURES_ENTRY *CpuFeature - ) -{ - EFI_STATUS Status; - CPU_FEATURES_DATA *CpuFeaturesData; - CPU_FEATURES_ENTRY *CpuFeatureEntry; - LIST_ENTRY *Entry; - UINT32 BitMaskSize; - BOOLEAN FeatureExist; - - BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport); - CpuFeaturesData = GetCpuFeaturesData (); - if (CpuFeaturesData->FeaturesCount == 0) { - InitializeListHead (&CpuFeaturesData->FeatureList); - InitializeSpinLock (&CpuFeaturesData->MsrLock); - InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock); - CpuFeaturesData->BitMaskSize = BitMaskSize; - } - ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize); - - FeatureExist = FALSE; - CpuFeatureEntry = NULL; - Entry = GetFirstNode (&CpuFeaturesData->FeatureList); - while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) { - CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry); - if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) { - // - // If this feature already registered - // - FeatureExist = TRUE; - break; - } - Entry = Entry->ForwardLink; - } - - if (!FeatureExist) { - DEBUG ((DEBUG_INFO, "[NEW] ")); - DumpCpuFeature (CpuFeature); - InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link); - CpuFeaturesData->FeaturesCount++; - } else { - DEBUG ((DEBUG_INFO, "[OVERRIDE] ")); - DumpCpuFeature (CpuFeature); - ASSERT (CpuFeatureEntry != NULL); - // - // Overwrite original parameters of CPU feature - // - if (CpuFeature->GetConfigDataFunc != NULL) { - CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc; - } - if (CpuFeature->SupportFunc != NULL) { - CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc; - } - if (CpuFeature->InitializeFunc != NULL) { - CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc; - } - if (CpuFeature->FeatureName != NULL) { - if (CpuFeatureEntry->FeatureName == NULL) { - CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE); - ASSERT (CpuFeatureEntry->FeatureName != NULL); - } - Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName); - ASSERT_EFI_ERROR (Status); - FreePool (CpuFeature->FeatureName); - } - if (CpuFeature->BeforeFeatureBitMask != NULL) { - if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) { - FreePool (CpuFeatureEntry->BeforeFeatureBitMask); - } - CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask; - } - if (CpuFeature->AfterFeatureBitMask != NULL) { - if (CpuFeatureEntry->AfterFeatureBitMask != NULL) { - FreePool (CpuFeatureEntry->AfterFeatureBitMask); - } - CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask; - } - CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll; - CpuFeatureEntry->AfterAll = CpuFeature->AfterAll; - - FreePool (CpuFeature->FeatureMask); - FreePool (CpuFeature); - } - // - // Verify CPU features dependency can change CPU feature order - // - CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList); - return RETURN_SUCCESS; -} - -/** - Sets CPU feature bit mask in CPU feature bit mask buffer. - - @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer - @param[in] Feature The bit number of the CPU feature - @param[in] BitMaskSize CPU feature bit mask buffer size -**/ -VOID -SetCpuFeaturesBitMask ( - IN UINT8 **FeaturesBitMask, - IN UINT32 Feature, - IN UINTN BitMaskSize - ) -{ - UINT8 *CpuFeaturesBitMask; - - ASSERT (FeaturesBitMask != NULL); - CpuFeaturesBitMask = *FeaturesBitMask; - if (CpuFeaturesBitMask == NULL) { - CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize); - ASSERT (CpuFeaturesBitMask != NULL); - *FeaturesBitMask = CpuFeaturesBitMask; - } - - CpuFeaturesBitMask += (Feature / 8); - *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8)); -} - -/** - Registers a CPU Feature. - - @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature - name. - @param[in] GetConfigDataFunc CPU feature get configuration data function. This - is an optional parameter that may be NULL. If NULL, - then the most recently registered function for the - CPU feature is used. If no functions are registered - for a CPU feature, then the CPU configuration data - for the registered feature is NULL. - @param[in] SupportFunc CPU feature support function. This is an optional - parameter that may be NULL. If NULL, then the most - recently registered function for the CPU feature is - used. If no functions are registered for a CPU - feature, then the CPU feature is assumed to be - supported by all CPUs. - @param[in] InitializeFunc CPU feature initialize function. This is an optional - parameter that may be NULL. If NULL, then the most - recently registered function for the CPU feature is - used. If no functions are registered for a CPU - feature, then the CPU feature initialization is - skipped. - @param[in] ... Variable argument list of UINT32 CPU feature value. - Values with no modifiers are the features provided - by the registered functions. - Values with CPU_FEATURE_BEFORE modifier are features - that must be initialized after the features provided - by the registered functions are used. - Values with CPU_FEATURE_AFTER modifier are features - that must be initialized before the features provided - by the registered functions are used. - The last argument in this variable argument list must - always be CPU_FEATURE_END. - - @retval RETURN_SUCCESS The CPU feature was successfully registered. - @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register - the CPU feature. - @retval RETURN_UNSUPPORTED Registration of the CPU feature is not - supported due to a circular dependency between - BEFORE and AFTER features. - - @note This service could be called by BSP only. -**/ -RETURN_STATUS -EFIAPI -RegisterCpuFeature ( - IN CHAR8 *FeatureName, OPTIONAL - IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL - IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL - IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL - ... - ) -{ - EFI_STATUS Status; - VA_LIST Marker; - UINT32 Feature; - UINTN BitMaskSize; - CPU_FEATURES_ENTRY *CpuFeature; - UINT8 *FeatureMask; - UINT8 *BeforeFeatureBitMask; - UINT8 *AfterFeatureBitMask; - BOOLEAN BeforeAll; - BOOLEAN AfterAll; - - FeatureMask = NULL; - BeforeFeatureBitMask = NULL; - AfterFeatureBitMask = NULL; - BeforeAll = FALSE; - AfterAll = FALSE; - - BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport); - - VA_START (Marker, InitializeFunc); - Feature = VA_ARG (Marker, UINT32); - while (Feature != CPU_FEATURE_END) { - ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER)) - != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER)); - ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL)) - != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL)); - if (Feature < CPU_FEATURE_BEFORE) { - BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE; - AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE; - Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL); - ASSERT (FeatureMask == NULL); - SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize); - } else if ((Feature & CPU_FEATURE_BEFORE) != 0) { - SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize); - } else if ((Feature & CPU_FEATURE_AFTER) != 0) { - SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize); - } - Feature = VA_ARG (Marker, UINT32); - } - VA_END (Marker); - - CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY)); - ASSERT (CpuFeature != NULL); - CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE; - CpuFeature->FeatureMask = FeatureMask; - CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask; - CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask; - CpuFeature->BeforeAll = BeforeAll; - CpuFeature->AfterAll = AfterAll; - CpuFeature->GetConfigDataFunc = GetConfigDataFunc; - CpuFeature->SupportFunc = SupportFunc; - CpuFeature->InitializeFunc = InitializeFunc; - if (FeatureName != NULL) { - CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE); - ASSERT (CpuFeature->FeatureName != NULL); - Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName); - ASSERT_EFI_ERROR (Status); - } - - Status = RegisterCpuFeatureWorker (CpuFeature); - ASSERT_EFI_ERROR (Status); - - return RETURN_SUCCESS; -} - -/** - Add an entry in specified register table. - - This function adds an entry in specified register table, with given register type, - register index, bit section and value. - - @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table - If FALSE, entry will be added into register table - @param[in] ProcessorNumber The index of the CPU to add a register table entry - @param[in] RegisterType Type of the register to program - @param[in] Index Index of the register to program - @param[in] ValidBitStart Start of the bit section - @param[in] ValidBitLength Length of the bit section - @param[in] Value Value to write -**/ -VOID -CpuRegisterTableWriteWorker ( - IN BOOLEAN PreSmmFlag, - IN UINTN ProcessorNumber, - IN REGISTER_TYPE RegisterType, - IN UINT64 Index, - IN UINT8 ValidBitStart, - IN UINT8 ValidBitLength, - IN UINT64 Value - ) -{ - EFI_STATUS Status; - CPU_FEATURES_DATA *CpuFeaturesData; - ACPI_CPU_DATA *AcpiCpuData; - CPU_REGISTER_TABLE *RegisterTable; - CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry; - - CpuFeaturesData = GetCpuFeaturesData (); - if (CpuFeaturesData->RegisterTable == NULL) { - AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress); - if (AcpiCpuData == NULL) { - AcpiCpuData = AllocateAcpiCpuData (); - ASSERT (AcpiCpuData != NULL); - // - // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure - // - Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData); - ASSERT_EFI_ERROR (Status); - } - ASSERT (AcpiCpuData->RegisterTable != 0); - CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable; - CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable; - } - - if (PreSmmFlag) { - RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber]; - } else { - RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber]; - } - - if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) { - EnlargeRegisterTable (RegisterTable); - } - - // - // Append entry in the register table. - // - RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry; - RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType; - RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index; - RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32); - RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart; - RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength; - RegisterTableEntry[RegisterTable->TableLength].Value = Value; - - RegisterTable->TableLength++; -} - -/** - Adds an entry in specified register table. - - This function adds an entry in specified register table, with given register type, - register index, bit section and value. - - @param[in] ProcessorNumber The index of the CPU to add a register table entry - @param[in] RegisterType Type of the register to program - @param[in] Index Index of the register to program - @param[in] ValueMask Mask of bits in register to write - @param[in] Value Value to write - - @note This service could be called by BSP only. -**/ -VOID -EFIAPI -CpuRegisterTableWrite ( - IN UINTN ProcessorNumber, - IN REGISTER_TYPE RegisterType, - IN UINT64 Index, - IN UINT64 ValueMask, - IN UINT64 Value - ) -{ - UINT8 Start; - UINT8 End; - UINT8 Length; - - Start = (UINT8)LowBitSet64 (ValueMask); - End = (UINT8)HighBitSet64 (ValueMask); - Length = End - Start + 1; - CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value); -} - -/** - Adds an entry in specified Pre-SMM register table. - - This function adds an entry in specified register table, with given register type, - register index, bit section and value. - - @param[in] ProcessorNumber The index of the CPU to add a register table entry. - @param[in] RegisterType Type of the register to program - @param[in] Index Index of the register to program - @param[in] ValueMask Mask of bits in register to write - @param[in] Value Value to write - - @note This service could be called by BSP only. -**/ -VOID -EFIAPI -PreSmmCpuRegisterTableWrite ( - IN UINTN ProcessorNumber, - IN REGISTER_TYPE RegisterType, - IN UINT64 Index, - IN UINT64 ValueMask, - IN UINT64 Value - ) -{ - UINT8 Start; - UINT8 End; - UINT8 Length; - - Start = (UINT8)LowBitSet64 (ValueMask); - End = (UINT8)HighBitSet64 (ValueMask); - Length = End - Start + 1; - CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value); -} - -/** - Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer. - - @param[in] CpuBitMask CPU feature bit mask buffer - @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer - @param[in] Feature The bit number of the CPU feature - - @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport. - @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport. - -**/ -BOOLEAN -IsCpuFeatureSetInCpuPcd ( - IN UINT8 *CpuBitMask, - IN UINTN CpuBitMaskSize, - IN UINT32 Feature - ) -{ - if ((Feature >> 3) >= CpuBitMaskSize) { - return FALSE; - } - return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0); -} - -/** - Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask. - If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data - associated with that feature should be optimized away if compiler - optimizations are enabled. - - @param[in] Feature The bit number of the CPU feature to check in the PCD - PcdCpuFeaturesSupport - - @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport. - @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport. - - @note This service could be called by BSP only. -**/ -BOOLEAN -EFIAPI -IsCpuFeatureSupported ( - IN UINT32 Feature - ) -{ - return IsCpuFeatureSetInCpuPcd ( - (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport), - PcdGetSize (PcdCpuFeaturesSupport), - Feature - ); -} - -/** - Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask. - - @param[in] Feature The bit number of the CPU feature to check in the PCD - PcdCpuFeaturesSetting - - @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting. - @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting. - - @note This service could be called by BSP only. -**/ -BOOLEAN -EFIAPI -IsCpuFeatureInSetting ( - IN UINT32 Feature - ) -{ - return IsCpuFeatureSetInCpuPcd ( - (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting), - PcdGetSize (PcdCpuFeaturesSetting), - Feature - ); -} - -/** - Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask. - - @param[in] Feature The bit number of the CPU feature to check in the PCD - PcdCpuFeaturesCapability - - @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability. - @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability. - - @note This service could be called by BSP only. -**/ -BOOLEAN -EFIAPI -IsCpuFeatureCapability ( - IN UINT32 Feature - ) -{ - return IsCpuFeatureSetInCpuPcd ( - (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability), - PcdGetSize (PcdCpuFeaturesCapability), - Feature - ); - -} - -/** - Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask. - - @param[in] Feature The bit number of the CPU feature to check in the PCD - PcdCpuFeaturesUserConfiguration - - @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration. - @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration. - - @note This service could be called by BSP only. -**/ -BOOLEAN -EFIAPI -IsCpuFeatureUserConfiguration ( - IN UINT32 Feature - ) -{ - return IsCpuFeatureSetInCpuPcd ( - (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration), - PcdGetSize (PcdCpuFeaturesUserConfiguration), - Feature - ); - -} - -/** - Switches to assigned BSP after CPU features initialization. - - @param[in] ProcessorNumber The index of the CPU executing this function. - - @note This service could be called by BSP only. -**/ -VOID -EFIAPI -SwitchBspAfterFeaturesInitialize ( - IN UINTN ProcessorNumber - ) -{ - CPU_FEATURES_DATA *CpuFeaturesData; - - CpuFeaturesData = GetCpuFeaturesData (); - CpuFeaturesData->BspNumber = ProcessorNumber; -} - +/** @file
+ CPU Register Table Library functions.
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RegisterCpuFeatures.h"
+
+/**
+ Checks if two CPU feature bit masks are equal.
+
+ @param[in] FirstFeatureMask The first input CPU feature bit mask
+ @param[in] SecondFeatureMask The second input CPU feature bit mask
+
+ @retval TRUE Two CPU feature bit masks are equal.
+ @retval FALSE Two CPU feature bit masks are not equal.
+**/
+BOOLEAN
+IsCpuFeatureMatch (
+ IN UINT8 *FirstFeatureMask,
+ IN UINT8 *SecondFeatureMask
+ )
+{
+ UINT32 BitMaskSize;
+
+ BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
+ if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
+
+ @param[in] FeatureMask A pointer to the CPU feature bit mask.
+**/
+VOID
+DumpCpuFeatureMask (
+ IN UINT8 *FeatureMask
+ )
+{
+ UINTN Index;
+ UINT8 *Data8;
+ UINT32 BitMaskSize;
+
+ BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
+ Data8 = (UINT8 *) FeatureMask;
+ for (Index = 0; Index < BitMaskSize; Index++) {
+ DEBUG ((DEBUG_INFO, " %02x ", *Data8++));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/**
+ Dump CPU feature name or CPU feature bit mask.
+
+ @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY
+**/
+VOID
+DumpCpuFeature (
+ IN CPU_FEATURES_ENTRY *CpuFeature
+ )
+{
+
+ if (CpuFeature->FeatureName != NULL) {
+ DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName));
+ } else {
+ DEBUG ((DEBUG_INFO, "FeatureMask = "));
+ DumpCpuFeatureMask (CpuFeature->FeatureMask);
+ }
+}
+
+/**
+ Determines if the feature bit mask is in dependent CPU feature bit mask buffer.
+
+ @param[in] FeatureMask Pointer to CPU feature bit mask
+ @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer
+
+ @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.
+ @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.
+**/
+BOOLEAN
+IsBitMaskMatchCheck (
+ IN UINT8 *FeatureMask,
+ IN UINT8 *DependentBitMask
+ )
+{
+ UINTN Index;
+ UINTN BitMaskSize;
+ UINT8 *Data1;
+ UINT8 *Data2;
+
+ BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
+
+ Data1 = FeatureMask;
+ Data2 = DependentBitMask;
+ for (Index = 0; Index < BitMaskSize; Index++) {
+ if (((*(Data1++)) & (*(Data2++))) != 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks and adjusts CPU features order per dependency relationship.
+
+ @param[in] FeatureList Pointer to CPU feature list
+**/
+VOID
+CheckCpuFeaturesDependency (
+ IN LIST_ENTRY *FeatureList
+ )
+{
+ LIST_ENTRY *CurrentEntry;
+ CPU_FEATURES_ENTRY *CpuFeature;
+ LIST_ENTRY *CheckEntry;
+ CPU_FEATURES_ENTRY *CheckFeature;
+ BOOLEAN Swapped;
+ LIST_ENTRY *TempEntry;
+
+ CurrentEntry = GetFirstNode (FeatureList);
+ while (!IsNull (FeatureList, CurrentEntry)) {
+ Swapped = FALSE;
+ CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);
+ if (CpuFeature->BeforeAll) {
+ //
+ // Check all features dispatched before this entry
+ //
+ CheckEntry = GetFirstNode (FeatureList);
+ while (CheckEntry != CurrentEntry) {
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
+ if (!CheckFeature->BeforeAll) {
+ //
+ // If this feature has no BeforeAll flag and is dispatched before CpuFeature,
+ // insert currentEntry before Checked feature
+ //
+ RemoveEntryList (CurrentEntry);
+ InsertTailList (CheckEntry, CurrentEntry);
+ Swapped = TRUE;
+ break;
+ }
+ CheckEntry = CheckEntry->ForwardLink;
+ }
+ if (Swapped) {
+ continue;
+ }
+ }
+
+ if (CpuFeature->AfterAll) {
+ //
+ // Check all features dispatched after this entry
+ //
+ CheckEntry = GetNextNode (FeatureList, CurrentEntry);
+ while (!IsNull (FeatureList, CheckEntry)) {
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
+ if (!CheckFeature->AfterAll) {
+ //
+ // If this feature has no AfterAll flag and is dispatched after CpuFeature,
+ // insert currentEntry after Checked feature
+ //
+ TempEntry = GetNextNode (FeatureList, CurrentEntry);
+ RemoveEntryList (CurrentEntry);
+ InsertHeadList (CheckEntry, CurrentEntry);
+ CurrentEntry = TempEntry;
+ Swapped = TRUE;
+ break;
+ }
+ CheckEntry = CheckEntry->ForwardLink;
+ }
+ if (Swapped) {
+ continue;
+ }
+ }
+
+ if (CpuFeature->BeforeFeatureBitMask != NULL) {
+ //
+ // Check all features dispatched before this entry
+ //
+ CheckEntry = GetFirstNode (FeatureList);
+ while (CheckEntry != CurrentEntry) {
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
+ if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {
+ //
+ // If there is dependency, swap them
+ //
+ RemoveEntryList (CurrentEntry);
+ InsertTailList (CheckEntry, CurrentEntry);
+ Swapped = TRUE;
+ break;
+ }
+ CheckEntry = CheckEntry->ForwardLink;
+ }
+ if (Swapped) {
+ continue;
+ }
+ }
+
+ if (CpuFeature->AfterFeatureBitMask != NULL) {
+ //
+ // Check all features dispatched after this entry
+ //
+ CheckEntry = GetNextNode (FeatureList, CurrentEntry);
+ while (!IsNull (FeatureList, CheckEntry)) {
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);
+ if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {
+ //
+ // If there is dependency, swap them
+ //
+ TempEntry = GetNextNode (FeatureList, CurrentEntry);
+ RemoveEntryList (CurrentEntry);
+ InsertHeadList (CheckEntry, CurrentEntry);
+ CurrentEntry = TempEntry;
+ Swapped = TRUE;
+ break;
+ }
+ CheckEntry = CheckEntry->ForwardLink;
+ }
+ if (Swapped) {
+ continue;
+ }
+ }
+ //
+ // No swap happened, check the next feature
+ //
+ CurrentEntry = CurrentEntry->ForwardLink;
+ }
+}
+
+/**
+ Worker function to register CPU Feature.
+
+ @param[in] CpuFeature Pointer to CPU feature entry
+
+ @retval RETURN_SUCCESS The CPU feature was successfully registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
+ the CPU feature.
+ @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
+ supported due to a circular dependency between
+ BEFORE and AFTER features.
+**/
+RETURN_STATUS
+RegisterCpuFeatureWorker (
+ IN CPU_FEATURES_ENTRY *CpuFeature
+ )
+{
+ EFI_STATUS Status;
+ CPU_FEATURES_DATA *CpuFeaturesData;
+ CPU_FEATURES_ENTRY *CpuFeatureEntry;
+ LIST_ENTRY *Entry;
+ UINT32 BitMaskSize;
+ BOOLEAN FeatureExist;
+
+ BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
+ CpuFeaturesData = GetCpuFeaturesData ();
+ if (CpuFeaturesData->FeaturesCount == 0) {
+ InitializeListHead (&CpuFeaturesData->FeatureList);
+ InitializeSpinLock (&CpuFeaturesData->MsrLock);
+ InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);
+ CpuFeaturesData->BitMaskSize = BitMaskSize;
+ }
+ ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);
+
+ FeatureExist = FALSE;
+ CpuFeatureEntry = NULL;
+ Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
+ while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
+ CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
+ if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {
+ //
+ // If this feature already registered
+ //
+ FeatureExist = TRUE;
+ break;
+ }
+ Entry = Entry->ForwardLink;
+ }
+
+ if (!FeatureExist) {
+ DEBUG ((DEBUG_INFO, "[NEW] "));
+ DumpCpuFeature (CpuFeature);
+ InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);
+ CpuFeaturesData->FeaturesCount++;
+ } else {
+ DEBUG ((DEBUG_INFO, "[OVERRIDE] "));
+ DumpCpuFeature (CpuFeature);
+ ASSERT (CpuFeatureEntry != NULL);
+ //
+ // Overwrite original parameters of CPU feature
+ //
+ if (CpuFeature->GetConfigDataFunc != NULL) {
+ CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;
+ }
+ if (CpuFeature->SupportFunc != NULL) {
+ CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;
+ }
+ if (CpuFeature->InitializeFunc != NULL) {
+ CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;
+ }
+ if (CpuFeature->FeatureName != NULL) {
+ if (CpuFeatureEntry->FeatureName == NULL) {
+ CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
+ ASSERT (CpuFeatureEntry->FeatureName != NULL);
+ }
+ Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (CpuFeature->FeatureName);
+ }
+ if (CpuFeature->BeforeFeatureBitMask != NULL) {
+ if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {
+ FreePool (CpuFeatureEntry->BeforeFeatureBitMask);
+ }
+ CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;
+ }
+ if (CpuFeature->AfterFeatureBitMask != NULL) {
+ if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {
+ FreePool (CpuFeatureEntry->AfterFeatureBitMask);
+ }
+ CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;
+ }
+ CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;
+ CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;
+
+ FreePool (CpuFeature->FeatureMask);
+ FreePool (CpuFeature);
+ }
+ //
+ // Verify CPU features dependency can change CPU feature order
+ //
+ CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);
+ return RETURN_SUCCESS;
+}
+
+/**
+ Sets CPU feature bit mask in CPU feature bit mask buffer.
+
+ @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer
+ @param[in] Feature The bit number of the CPU feature
+ @param[in] BitMaskSize CPU feature bit mask buffer size
+**/
+VOID
+SetCpuFeaturesBitMask (
+ IN UINT8 **FeaturesBitMask,
+ IN UINT32 Feature,
+ IN UINTN BitMaskSize
+ )
+{
+ UINT8 *CpuFeaturesBitMask;
+
+ ASSERT (FeaturesBitMask != NULL);
+ CpuFeaturesBitMask = *FeaturesBitMask;
+ if (CpuFeaturesBitMask == NULL) {
+ CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);
+ ASSERT (CpuFeaturesBitMask != NULL);
+ *FeaturesBitMask = CpuFeaturesBitMask;
+ }
+
+ CpuFeaturesBitMask += (Feature / 8);
+ *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));
+}
+
+/**
+ Registers a CPU Feature.
+
+ @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature
+ name.
+ @param[in] GetConfigDataFunc CPU feature get configuration data function. This
+ is an optional parameter that may be NULL. If NULL,
+ then the most recently registered function for the
+ CPU feature is used. If no functions are registered
+ for a CPU feature, then the CPU configuration data
+ for the registered feature is NULL.
+ @param[in] SupportFunc CPU feature support function. This is an optional
+ parameter that may be NULL. If NULL, then the most
+ recently registered function for the CPU feature is
+ used. If no functions are registered for a CPU
+ feature, then the CPU feature is assumed to be
+ supported by all CPUs.
+ @param[in] InitializeFunc CPU feature initialize function. This is an optional
+ parameter that may be NULL. If NULL, then the most
+ recently registered function for the CPU feature is
+ used. If no functions are registered for a CPU
+ feature, then the CPU feature initialization is
+ skipped.
+ @param[in] ... Variable argument list of UINT32 CPU feature value.
+ Values with no modifiers are the features provided
+ by the registered functions.
+ Values with CPU_FEATURE_BEFORE modifier are features
+ that must be initialized after the features provided
+ by the registered functions are used.
+ Values with CPU_FEATURE_AFTER modifier are features
+ that must be initialized before the features provided
+ by the registered functions are used.
+ The last argument in this variable argument list must
+ always be CPU_FEATURE_END.
+
+ @retval RETURN_SUCCESS The CPU feature was successfully registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register
+ the CPU feature.
+ @retval RETURN_UNSUPPORTED Registration of the CPU feature is not
+ supported due to a circular dependency between
+ BEFORE and AFTER features.
+
+ @note This service could be called by BSP only.
+**/
+RETURN_STATUS
+EFIAPI
+RegisterCpuFeature (
+ IN CHAR8 *FeatureName, OPTIONAL
+ IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL
+ IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL
+ IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+ UINT32 Feature;
+ UINTN BitMaskSize;
+ CPU_FEATURES_ENTRY *CpuFeature;
+ UINT8 *FeatureMask;
+ UINT8 *BeforeFeatureBitMask;
+ UINT8 *AfterFeatureBitMask;
+ BOOLEAN BeforeAll;
+ BOOLEAN AfterAll;
+
+ FeatureMask = NULL;
+ BeforeFeatureBitMask = NULL;
+ AfterFeatureBitMask = NULL;
+ BeforeAll = FALSE;
+ AfterAll = FALSE;
+
+ BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
+
+ VA_START (Marker, InitializeFunc);
+ Feature = VA_ARG (Marker, UINT32);
+ while (Feature != CPU_FEATURE_END) {
+ ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))
+ != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));
+ ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))
+ != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));
+ if (Feature < CPU_FEATURE_BEFORE) {
+ BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;
+ AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;
+ Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);
+ ASSERT (FeatureMask == NULL);
+ SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);
+ } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {
+ SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);
+ } else if ((Feature & CPU_FEATURE_AFTER) != 0) {
+ SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);
+ }
+ Feature = VA_ARG (Marker, UINT32);
+ }
+ VA_END (Marker);
+
+ CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));
+ ASSERT (CpuFeature != NULL);
+ CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;
+ CpuFeature->FeatureMask = FeatureMask;
+ CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;
+ CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;
+ CpuFeature->BeforeAll = BeforeAll;
+ CpuFeature->AfterAll = AfterAll;
+ CpuFeature->GetConfigDataFunc = GetConfigDataFunc;
+ CpuFeature->SupportFunc = SupportFunc;
+ CpuFeature->InitializeFunc = InitializeFunc;
+ if (FeatureName != NULL) {
+ CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);
+ ASSERT (CpuFeature->FeatureName != NULL);
+ Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = RegisterCpuFeatureWorker (CpuFeature);
+ ASSERT_EFI_ERROR (Status);
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Add an entry in specified register table.
+
+ This function adds an entry in specified register table, with given register type,
+ register index, bit section and value.
+
+ @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table
+ If FALSE, entry will be added into register table
+ @param[in] ProcessorNumber The index of the CPU to add a register table entry
+ @param[in] RegisterType Type of the register to program
+ @param[in] Index Index of the register to program
+ @param[in] ValidBitStart Start of the bit section
+ @param[in] ValidBitLength Length of the bit section
+ @param[in] Value Value to write
+**/
+VOID
+CpuRegisterTableWriteWorker (
+ IN BOOLEAN PreSmmFlag,
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT64 Index,
+ IN UINT8 ValidBitStart,
+ IN UINT8 ValidBitLength,
+ IN UINT64 Value
+ )
+{
+ EFI_STATUS Status;
+ CPU_FEATURES_DATA *CpuFeaturesData;
+ ACPI_CPU_DATA *AcpiCpuData;
+ CPU_REGISTER_TABLE *RegisterTable;
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
+
+ CpuFeaturesData = GetCpuFeaturesData ();
+ if (CpuFeaturesData->RegisterTable == NULL) {
+ AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
+ if (AcpiCpuData == NULL) {
+ AcpiCpuData = AllocateAcpiCpuData ();
+ ASSERT (AcpiCpuData != NULL);
+ //
+ // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
+ //
+ Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
+ ASSERT_EFI_ERROR (Status);
+ }
+ ASSERT (AcpiCpuData->RegisterTable != 0);
+ CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;
+ CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;
+ }
+
+ if (PreSmmFlag) {
+ RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];
+ } else {
+ RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
+ }
+
+ if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
+ EnlargeRegisterTable (RegisterTable);
+ }
+
+ //
+ // Append entry in the register table.
+ //
+ RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
+ RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
+ RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;
+ RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);
+ RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
+ RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
+ RegisterTableEntry[RegisterTable->TableLength].Value = Value;
+
+ RegisterTable->TableLength++;
+}
+
+/**
+ Adds an entry in specified register table.
+
+ This function adds an entry in specified register table, with given register type,
+ register index, bit section and value.
+
+ @param[in] ProcessorNumber The index of the CPU to add a register table entry
+ @param[in] RegisterType Type of the register to program
+ @param[in] Index Index of the register to program
+ @param[in] ValueMask Mask of bits in register to write
+ @param[in] Value Value to write
+
+ @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+CpuRegisterTableWrite (
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT64 Index,
+ IN UINT64 ValueMask,
+ IN UINT64 Value
+ )
+{
+ UINT8 Start;
+ UINT8 End;
+ UINT8 Length;
+
+ Start = (UINT8)LowBitSet64 (ValueMask);
+ End = (UINT8)HighBitSet64 (ValueMask);
+ Length = End - Start + 1;
+ CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
+}
+
+/**
+ Adds an entry in specified Pre-SMM register table.
+
+ This function adds an entry in specified register table, with given register type,
+ register index, bit section and value.
+
+ @param[in] ProcessorNumber The index of the CPU to add a register table entry.
+ @param[in] RegisterType Type of the register to program
+ @param[in] Index Index of the register to program
+ @param[in] ValueMask Mask of bits in register to write
+ @param[in] Value Value to write
+
+ @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+PreSmmCpuRegisterTableWrite (
+ IN UINTN ProcessorNumber,
+ IN REGISTER_TYPE RegisterType,
+ IN UINT64 Index,
+ IN UINT64 ValueMask,
+ IN UINT64 Value
+ )
+{
+ UINT8 Start;
+ UINT8 End;
+ UINT8 Length;
+
+ Start = (UINT8)LowBitSet64 (ValueMask);
+ End = (UINT8)HighBitSet64 (ValueMask);
+ Length = End - Start + 1;
+ CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);
+}
+
+/**
+ Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.
+
+ @param[in] CpuBitMask CPU feature bit mask buffer
+ @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer
+ @param[in] Feature The bit number of the CPU feature
+
+ @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
+ @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
+
+**/
+BOOLEAN
+IsCpuFeatureSetInCpuPcd (
+ IN UINT8 *CpuBitMask,
+ IN UINTN CpuBitMaskSize,
+ IN UINT32 Feature
+ )
+{
+ if ((Feature >> 3) >= CpuBitMaskSize) {
+ return FALSE;
+ }
+ return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);
+}
+
+/**
+ Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
+ If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
+ associated with that feature should be optimized away if compiler
+ optimizations are enabled.
+
+ @param[in] Feature The bit number of the CPU feature to check in the PCD
+ PcdCpuFeaturesSupport
+
+ @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.
+ @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.
+
+ @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureSupported (
+ IN UINT32 Feature
+ )
+{
+ return IsCpuFeatureSetInCpuPcd (
+ (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),
+ PcdGetSize (PcdCpuFeaturesSupport),
+ Feature
+ );
+}
+
+/**
+ Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
+
+ @param[in] Feature The bit number of the CPU feature to check in the PCD
+ PcdCpuFeaturesSetting
+
+ @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.
+ @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.
+
+ @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureInSetting (
+ IN UINT32 Feature
+ )
+{
+ return IsCpuFeatureSetInCpuPcd (
+ (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),
+ PcdGetSize (PcdCpuFeaturesSetting),
+ Feature
+ );
+}
+
+/**
+ Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
+
+ @param[in] Feature The bit number of the CPU feature to check in the PCD
+ PcdCpuFeaturesCapability
+
+ @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.
+ @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.
+
+ @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureCapability (
+ IN UINT32 Feature
+ )
+{
+ return IsCpuFeatureSetInCpuPcd (
+ (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),
+ PcdGetSize (PcdCpuFeaturesCapability),
+ Feature
+ );
+
+}
+
+/**
+ Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
+
+ @param[in] Feature The bit number of the CPU feature to check in the PCD
+ PcdCpuFeaturesUserConfiguration
+
+ @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.
+ @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
+
+ @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureUserConfiguration (
+ IN UINT32 Feature
+ )
+{
+ return IsCpuFeatureSetInCpuPcd (
+ (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),
+ PcdGetSize (PcdCpuFeaturesUserConfiguration),
+ Feature
+ );
+
+}
+
+/**
+ Switches to assigned BSP after CPU features initialization.
+
+ @param[in] ProcessorNumber The index of the CPU executing this function.
+
+ @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+SwitchBspAfterFeaturesInitialize (
+ IN UINTN ProcessorNumber
+ )
+{
+ CPU_FEATURES_DATA *CpuFeaturesData;
+
+ CpuFeaturesData = GetCpuFeaturesData ();
+ CpuFeaturesData->BspNumber = ProcessorNumber;
+}
+
|