UefiCpuPkg: Add PEI/DXE Register CPU Features Library instances
PEI Register CPU Features Library instance is used to register/manager/program CPU features on PEI phase. DXE Register CPU Features Library instance is used to register/manager/program CPU features on DXE phase. v2: Format debug messages. v3: Trim white space at end of line. v4: Remove unused local variable. 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>
This commit is contained in:
@@ -0,0 +1,770 @@
|
||||
/** @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;
|
||||
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);
|
||||
//
|
||||
// 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 UINT32 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 = Index;
|
||||
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 UINT32 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 UINT32 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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user