Jeff Fan 30b7a50bac UefiCpuPkg/AcpiCpuData.h: Support >4GB MMIO address
The current CPU_REGISTER_TABLE_ENTRY structure only defined UINT32 Index to
indicate MSR/MMIO address. It's ok for MSR because MSR address is UINT32 type
actually. But for MMIO address, UINT32 limits MMIO address exceeds 4GB.

This update on CPU_REGISTER_TABLE_ENTRY is to add additional UINT32 field
HighIndex to indicate the high 32bit MMIO address and original Index still
indicate the low 32bit MMIO address.

This update makes use of original padding space between ValidBitLength and
Value to add HighIndex.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
2017-03-27 16:18:04 +08:00

774 lines
26 KiB
C

/** @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 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 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 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 ... 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;
}