PcdGetSize() returns UINTN data type. The consumer code should use UINTN data to get its size. This issue is found when PcdCpuFeaturesSupport is configured as patchable. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
			
				
	
	
		
			776 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			776 lines
		
	
	
		
			27 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
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                 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;
 | 
						|
  UINTN                  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;
 | 
						|
  UINTN                      BitMaskSize;
 | 
						|
  BOOLEAN                    FeatureExist;
 | 
						|
 | 
						|
  BitMaskSize     = PcdGetSize (PcdCpuFeaturesSupport);
 | 
						|
  CpuFeaturesData = GetCpuFeaturesData ();
 | 
						|
  if (CpuFeaturesData->FeaturesCount == 0) {
 | 
						|
    InitializeListHead (&CpuFeaturesData->FeatureList);
 | 
						|
    InitializeSpinLock (&CpuFeaturesData->MsrLock);
 | 
						|
    InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);
 | 
						|
    CpuFeaturesData->BitMaskSize = (UINT32) 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;
 | 
						|
}
 | 
						|
 |