[edk2-devel] [PATCH v5 2/2] UefiCpuPkg/CpuCacheInfoLib: Add new CpuCacheInfoLib.

Ni, Ray ray.ni at intel.com
Wed Jan 13 04:01:44 UTC 2021


Laszlo,
Have you given Acked-by or Reviewed-by before? I cannot find it.

This version is good to me. I will create pull request once MdePkg maintainers 
and you approve.

Thanks,
Ray

> -----Original Message-----
> From: Lou, Yun <yun.lou at intel.com>
> Sent: Thursday, January 7, 2021 11:23 AM
> To: devel at edk2.groups.io
> Cc: Lou, Yun <yun.lou at intel.com>; Ni, Ray <ray.ni at intel.com>; Dong, Eric
> <eric.dong at intel.com>; Laszlo Ersek <lersek at redhat.com>; Kumar, Rahul1
> <rahul1.kumar at intel.com>
> Subject: [PATCH v5 2/2] UefiCpuPkg/CpuCacheInfoLib: Add new
> CpuCacheInfoLib.
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3105
> 
> This new library uses a platform agnostic algorithm to get CPU
> cache information. It provides user with an API(GetCpuCacheInfo)
> to get detailed CPU cache information by each package, each core
> type included in this package, and each cache level & type.
> This library can be used by code that produces SMBIOS_TABLE_TYPE7
> SMBIOS table.
> 
> Signed-off-by: Jason Lou <yun.lou at intel.com>
> Cc: Ray Ni <ray.ni at intel.com>
> Cc: Eric Dong <eric.dong at intel.com>
> Cc: Laszlo Ersek <lersek at redhat.com>
> Cc: Rahul Kumar <rahul1.kumar at intel.com>
> ---
>  UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c         | 440
> ++++++++++++++++++++
>  UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c      | 120 ++++++
>  UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c      | 119 ++++++
>  UefiCpuPkg/Include/Library/CpuCacheInfoLib.h                 |  76 ++++
>  UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni       |  15 +
>  UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf    |  43 ++
>  UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h | 159
> +++++++
>  UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf    |  43 ++
>  UefiCpuPkg/UefiCpuPkg.dec                                    |   3 +
>  UefiCpuPkg/UefiCpuPkg.dsc                                    |   4 +
>  10 files changed, 1022 insertions(+)
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
> b/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
> new file mode 100644
> index 000000000000..ec506cda471c
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
> @@ -0,0 +1,440 @@
> +/** @file
> 
> +  Provides cache info for each package, core type, cache level and cache type.
> 
> +
> 
> +  Copyright (c) 2020 Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCpuCacheInfoLib.h"
> 
> +
> 
> +/**
> 
> +  Print CpuCacheInfo array.
> 
> +
> 
> +  @param[in]  CpuCacheInfo        Pointer to the CpuCacheInfo array.
> 
> +  @param[in]  CpuCacheInfoCount   The length of CpuCacheInfo array.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoPrintCpuCacheInfoTable (
> 
> +  IN CPU_CACHE_INFO         *CpuCacheInfo,
> 
> +  IN UINTN                  CpuCacheInfoCount
> 
> +  )
> 
> +{
> 
> +  UINTN                     Index;
> 
> +
> 
> +  DEBUG ((DEBUG_INFO, "+-------+----------------------------------------------------------
> ---------------------+\n"));
> 
> +  DEBUG ((DEBUG_INFO, "| Index | Packge  CoreType  CacheLevel  CacheType
> CacheWays  CacheSizeinKB  CacheCount |\n"));
> 
> +  DEBUG ((DEBUG_INFO, "+-------+----------------------------------------------------------
> ---------------------+\n"));
> 
> +
> 
> +  for (Index = 0; Index < CpuCacheInfoCount; Index++) {
> 
> +    DEBUG ((DEBUG_INFO, "| %4x
> | %4x       %2x        %2x          %2x       %4x      %8x         %4x     |\n", Index,
> 
> +        CpuCacheInfo[Index].Package, CpuCacheInfo[Index].CoreType,
> CpuCacheInfo[Index].CacheLevel,
> 
> +        CpuCacheInfo[Index].CacheType, CpuCacheInfo[Index].CacheWays,
> CpuCacheInfo[Index].CacheSizeinKB,
> 
> +        CpuCacheInfo[Index].CacheCount));
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_INFO, "+-------+----------------------------------------------------------
> ---------------------+\n"));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get the total number of package and package ID in the platform.
> 
> +
> 
> +  @param[in]      ProcessorInfo       Pointer to the ProcessorInfo array.
> 
> +  @param[in]      NumberOfProcessors  Total number of logical processors in
> the platform.
> 
> +  @param[in, out] Package             Pointer to the Package array.
> 
> +
> 
> +  @retval  Return the total number of package and package ID in the platform.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoGetNumberOfPackages (
> 
> +  IN CPUID_PROCESSOR_INFO   *ProcessorInfo,
> 
> +  IN UINTN                  NumberOfProcessors,
> 
> +  IN OUT UINT32             *Package
> 
> +  )
> 
> +{
> 
> +  UINTN                     ProcessorIndex;
> 
> +  UINT32                    PackageIndex;
> 
> +  UINT32                    PackageCount;
> 
> +  UINT32                    CurrentPackage;
> 
> +
> 
> +  PackageCount = 0;
> 
> +
> 
> +  for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors;
> ProcessorIndex++) {
> 
> +    CurrentPackage = ProcessorInfo[ProcessorIndex].Package;
> 
> +
> 
> +    //
> 
> +    // For the package that already exists in Package array, break out the loop.
> 
> +    //
> 
> +    for (PackageIndex = 0; PackageIndex < PackageCount; PackageIndex++) {
> 
> +      if (CurrentPackage == Package[PackageIndex]) {
> 
> +        break;
> 
> +      }
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // For the new package, save it in Package array.
> 
> +    //
> 
> +    if (PackageIndex == PackageCount) {
> 
> +      ASSERT (PackageCount < MAX_NUM_OF_PACKAGE);
> 
> +      Package[PackageCount++] = CurrentPackage;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return PackageCount;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get the number of CoreType of requested package.
> 
> +
> 
> +  @param[in]  ProcessorInfo       Pointer to the ProcessorInfo array.
> 
> +  @param[in]  NumberOfProcessors  Total number of logical processors in the
> platform.
> 
> +  @param[in]  Package             The requested package number.
> 
> +
> 
> +  @retval  Return the number of CoreType of requested package.
> 
> +**/
> 
> +UINTN
> 
> +CpuCacheInfoGetNumberOfCoreTypePerPackage(
> 
> +  IN CPUID_PROCESSOR_INFO   *ProcessorInfo,
> 
> +  IN UINTN                  NumberOfProcessors,
> 
> +  IN UINTN                  Package
> 
> +  )
> 
> +{
> 
> +  UINTN                     ProcessorIndex;
> 
> +  //
> 
> +  // Core Type value comes from CPUID.1Ah.EAX[31:24].
> 
> +  // So max number of core types should be MAX_UINT8.
> 
> +  //
> 
> +  UINT8                     CoreType[MAX_UINT8];
> 
> +  UINTN                     CoreTypeIndex;
> 
> +  UINTN                     CoreTypeCount;
> 
> +  UINT8                     CurrentCoreType;
> 
> +
> 
> +  //
> 
> +  // CoreType array is empty.
> 
> +  //
> 
> +  CoreTypeCount = 0;
> 
> +
> 
> +  for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors;
> ProcessorIndex++) {
> 
> +    CurrentCoreType = ProcessorInfo[ProcessorIndex].CoreType;
> 
> +
> 
> +    if (ProcessorInfo[ProcessorIndex].Package != Package) {
> 
> +      continue;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // For the type that already exists in CoreType array, break out the loop.
> 
> +    //
> 
> +    for (CoreTypeIndex = 0; CoreTypeIndex < CoreTypeCount; CoreTypeIndex++)
> {
> 
> +      if (CurrentCoreType == CoreType[CoreTypeIndex]) {
> 
> +        break;
> 
> +      }
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // For the new type, save it in CoreType array.
> 
> +    //
> 
> +    if (CoreTypeIndex == CoreTypeCount) {
> 
> +      ASSERT (CoreTypeCount < MAX_UINT8);
> 
> +      CoreType[CoreTypeCount++] = CurrentCoreType;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return CoreTypeCount;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Collect core and cache information of calling processor via CPUID
> instructions.
> 
> +
> 
> +  @param[in]  Buffer              The pointer to private data buffer.
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoCollectCoreAndCacheData (
> 
> +  IN OUT VOID               *Buffer
> 
> +  )
> 
> +{
> 
> +  UINTN                     ProcessorIndex;
> 
> +  UINT32                    CpuidMaxInput;
> 
> +  UINT8                     CacheParamLeafIndex;
> 
> +  CPUID_CACHE_PARAMS_EAX    CacheParamEax;
> 
> +  CPUID_CACHE_PARAMS_EBX    CacheParamEbx;
> 
> +  UINT32                    CacheParamEcx;
> 
> +  CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX
> NativeModelIdAndCoreTypeEax;
> 
> +  COLLECT_CPUID_CACHE_DATA_CONTEXT  *Context;
> 
> +  CPUID_CACHE_DATA          *CacheData;
> 
> +
> 
> +  Context = (COLLECT_CPUID_CACHE_DATA_CONTEXT *)Buffer;
> 
> +  ProcessorIndex = CpuCacheInfoWhoAmI (Context->MpServices);
> 
> +  CacheData = &Context->CacheData[MAX_NUM_OF_CACHE_PARAMS_LEAF
> * ProcessorIndex];
> 
> +
> 
> +  AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);
> 
> +
> 
> +  //
> 
> +  // get CoreType if CPUID_HYBRID_INFORMATION leaf is supported.
> 
> +  //
> 
> +  Context->ProcessorInfo[ProcessorIndex].CoreType = 0;
> 
> +  if (CpuidMaxInput >= CPUID_HYBRID_INFORMATION) {
> 
> +    AsmCpuidEx (CPUID_HYBRID_INFORMATION,
> CPUID_HYBRID_INFORMATION_SUB_LEAF,
> &NativeModelIdAndCoreTypeEax.Uint32, NULL, NULL, NULL);
> 
> +    Context->ProcessorInfo[ProcessorIndex].CoreType = (UINT8)
> NativeModelIdAndCoreTypeEax.Bits.CoreType;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // cache hierarchy starts with an index value of 0.
> 
> +  //
> 
> +  CacheParamLeafIndex = 0;
> 
> +
> 
> +  while (CacheParamLeafIndex < MAX_NUM_OF_CACHE_PARAMS_LEAF) {
> 
> +    AsmCpuidEx (CPUID_CACHE_PARAMS, CacheParamLeafIndex,
> &CacheParamEax.Uint32, &CacheParamEbx.Uint32, &CacheParamEcx, NULL);
> 
> +
> 
> +    if (CacheParamEax.Bits.CacheType == 0) {
> 
> +      break;
> 
> +    }
> 
> +
> 
> +    CacheData[CacheParamLeafIndex].CacheLevel     =
> (UINT8)CacheParamEax.Bits.CacheLevel;
> 
> +    CacheData[CacheParamLeafIndex].CacheType      =
> (UINT8)CacheParamEax.Bits.CacheType;
> 
> +    CacheData[CacheParamLeafIndex].CacheWays      =
> (UINT16)CacheParamEbx.Bits.Ways;
> 
> +    CacheData[CacheParamLeafIndex].CacheShareBits =
> (UINT16)CacheParamEax.Bits.MaximumAddressableIdsForLogicalProcessors;
> 
> +    CacheData[CacheParamLeafIndex].CacheSizeinKB  =
> (CacheParamEbx.Bits.Ways + 1) *
> 
> +        (CacheParamEbx.Bits.LinePartitions + 1) * (CacheParamEbx.Bits.LineSize
> + 1) * (CacheParamEcx + 1) / SIZE_1KB;
> 
> +
> 
> +    CacheParamLeafIndex++;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Collect CacheInfo data from the CacheData.
> 
> +
> 
> +  @param[in]      CacheData           Pointer to the CacheData array.
> 
> +  @param[in]      ProcessorInfo       Pointer to the ProcessorInfo array.
> 
> +  @param[in]      NumberOfProcessors  Total number of logical processors in
> the platform.
> 
> +  @param[in, out] CacheInfo           Pointer to the CacheInfo array.
> 
> +  @param[in, out] CacheInfoCount      As input, point to the length of response
> CacheInfo array.
> 
> +                                      As output, point to the actual length of response
> CacheInfo array.
> 
> +
> 
> +  @retval         EFI_SUCCESS             Function completed successfully.
> 
> +  @retval         EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> 
> +  @retval         EFI_BUFFER_TOO_SMALL    CacheInfoCount is too small to hold
> the response CacheInfo
> 
> +                                          array. CacheInfoCount has been updated with the
> length needed
> 
> +                                          to complete the request.
> 
> +**/
> 
> +EFI_STATUS
> 
> +CpuCacheInfoCollectCpuCacheInfoData (
> 
> +  IN CPUID_CACHE_DATA       *CacheData,
> 
> +  IN CPUID_PROCESSOR_INFO   *ProcessorInfo,
> 
> +  IN UINTN                  NumberOfProcessors,
> 
> +  IN OUT CPU_CACHE_INFO     *CacheInfo,
> 
> +  IN OUT UINTN              *CacheInfoCount
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINT32                    NumberOfPackage;
> 
> +  UINT32                    Package[MAX_NUM_OF_PACKAGE];
> 
> +  UINTN                     PackageIndex;
> 
> +  UINTN                     TotalNumberOfCoreType;
> 
> +  UINTN                     MaxCacheInfoCount;
> 
> +  CPU_CACHE_INFO            *LocalCacheInfo;
> 
> +  UINTN                     CacheInfoIndex;
> 
> +  UINTN                     LocalCacheInfoCount;
> 
> +  UINTN                     Index;
> 
> +  UINTN                     NextIndex;
> 
> +
> 
> +  //
> 
> +  // Get number of Packages and Package ID.
> 
> +  //
> 
> +  NumberOfPackage = CpuCacheInfoGetNumberOfPackages (ProcessorInfo,
> NumberOfProcessors, Package);
> 
> +
> 
> +  //
> 
> +  // Get number of core types for each package and count the total number.
> 
> +  // E.g. If Package1 and Package2 both have 2 core types, the total number is
> 4.
> 
> +  //
> 
> +  TotalNumberOfCoreType = 0;
> 
> +  for (PackageIndex = 0; PackageIndex < NumberOfPackage; PackageIndex++)
> {
> 
> +    TotalNumberOfCoreType +=
> CpuCacheInfoGetNumberOfCoreTypePerPackage (ProcessorInfo,
> NumberOfProcessors, Package[PackageIndex]);
> 
> +  }
> 
> +
> 
> +  MaxCacheInfoCount = TotalNumberOfCoreType *
> MAX_NUM_OF_CACHE_PARAMS_LEAF;
> 
> +  LocalCacheInfo = AllocatePages (EFI_SIZE_TO_PAGES (MaxCacheInfoCount *
> sizeof (*LocalCacheInfo)));
> 
> +  ASSERT (LocalCacheInfo != NULL);
> 
> +  if (LocalCacheInfo == NULL) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +
> 
> +  LocalCacheInfoCount = 0;
> 
> +
> 
> +  for (Index = 0; Index < NumberOfProcessors *
> MAX_NUM_OF_CACHE_PARAMS_LEAF; Index++) {
> 
> +    if (CacheData[Index].CacheSizeinKB == 0) {
> 
> +      continue;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // For the sharing caches, clear their CacheSize.
> 
> +    //
> 
> +    for (NextIndex = Index + 1; NextIndex < NumberOfProcessors *
> MAX_NUM_OF_CACHE_PARAMS_LEAF; NextIndex++) {
> 
> +      if (CacheData[NextIndex].CacheSizeinKB == 0) {
> 
> +        continue;
> 
> +      }
> 
> +
> 
> +      if (CacheData[Index].CacheLevel == CacheData[NextIndex].CacheLevel &&
> 
> +          CacheData[Index].CacheType == CacheData[NextIndex].CacheType &&
> 
> +          ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package
> == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package
> &&
> 
> +          ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType
> == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType
> &&
> 
> +          (ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId &
> ~CacheData[Index].CacheShareBits) ==
> 
> +          (ProcessorInfo[NextIndex /
> MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId &
> ~CacheData[NextIndex].CacheShareBits)) {
> 
> +        CacheData[NextIndex].CacheSizeinKB = 0; // uses the sharing cache
> 
> +      }
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // For the cache that already exists in LocalCacheInfo, increase its
> CacheCount.
> 
> +    //
> 
> +    for (CacheInfoIndex = 0; CacheInfoIndex < LocalCacheInfoCount;
> CacheInfoIndex++) {
> 
> +      if (LocalCacheInfo[CacheInfoIndex].Package    == ProcessorInfo[Index /
> MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&
> 
> +          LocalCacheInfo[CacheInfoIndex].CoreType   == ProcessorInfo[Index /
> MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&
> 
> +          LocalCacheInfo[CacheInfoIndex].CacheLevel ==
> CacheData[Index].CacheLevel &&
> 
> +          LocalCacheInfo[CacheInfoIndex].CacheType  ==
> CacheData[Index].CacheType) {
> 
> +        LocalCacheInfo[CacheInfoIndex].CacheCount++;
> 
> +        break;
> 
> +      }
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // For the new cache with different Package, CoreType, CacheLevel or
> CacheType, copy its
> 
> +    // data into LocalCacheInfo buffer.
> 
> +    //
> 
> +    if (CacheInfoIndex == LocalCacheInfoCount) {
> 
> +      ASSERT (LocalCacheInfoCount < MaxCacheInfoCount);
> 
> +
> 
> +      LocalCacheInfo[LocalCacheInfoCount].Package       = ProcessorInfo[Index /
> MAX_NUM_OF_CACHE_PARAMS_LEAF].Package;
> 
> +      LocalCacheInfo[LocalCacheInfoCount].CoreType      = ProcessorInfo[Index /
> MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType;
> 
> +      LocalCacheInfo[LocalCacheInfoCount].CacheLevel    =
> CacheData[Index].CacheLevel;
> 
> +      LocalCacheInfo[LocalCacheInfoCount].CacheType     =
> CacheData[Index].CacheType;
> 
> +      LocalCacheInfo[LocalCacheInfoCount].CacheWays     =
> CacheData[Index].CacheWays;
> 
> +      LocalCacheInfo[LocalCacheInfoCount].CacheSizeinKB =
> CacheData[Index].CacheSizeinKB;
> 
> +      LocalCacheInfo[LocalCacheInfoCount].CacheCount    = 1;
> 
> +
> 
> +      LocalCacheInfoCount++;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (*CacheInfoCount < LocalCacheInfoCount) {
> 
> +    Status = EFI_BUFFER_TOO_SMALL;
> 
> +  } else {
> 
> +    CopyMem (CacheInfo, LocalCacheInfo, sizeof (*CacheInfo) *
> LocalCacheInfoCount);
> 
> +    DEBUG_CODE (
> 
> +      CpuCacheInfoPrintCpuCacheInfoTable (CacheInfo, LocalCacheInfoCount);
> 
> +    );
> 
> +    Status = EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  *CacheInfoCount = LocalCacheInfoCount;
> 
> +
> 
> +  FreePages (LocalCacheInfo, EFI_SIZE_TO_PAGES (MaxCacheInfoCount *
> sizeof (*LocalCacheInfo)));
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get CpuCacheInfo data array.
> 
> +
> 
> +  @param[in, out] CpuCacheInfo        Pointer to the CpuCacheInfo array.
> 
> +  @param[in, out] CpuCacheInfoCount   As input, point to the length of
> response CpuCacheInfo array.
> 
> +                                      As output, point to the actual length of response
> CpuCacheInfo array.
> 
> +
> 
> +  @retval         EFI_SUCCESS             Function completed successfully.
> 
> +  @retval         EFI_INVALID_PARAMETER   CpuCacheInfoCount is NULL.
> 
> +  @retval         EFI_INVALID_PARAMETER   CpuCacheInfo is NULL while
> CpuCacheInfoCount contains the value
> 
> +                                          greater than zero.
> 
> +  @retval         EFI_UNSUPPORTED         Processor does not support
> CPUID_CACHE_PARAMS Leaf.
> 
> +  @retval         EFI_NOT_FOUND           EDKII_PEI_MP_SERVICES2_PPI or
> EFI_MP_SERVICES_PROTOCOL interface
> 
> +                                          is not found.
> 
> +  @retval         EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> 
> +  @retval         EFI_BUFFER_TOO_SMALL    CpuCacheInfoCount is too small to
> hold the response CpuCacheInfo
> 
> +                                          array. CpuCacheInfoCount has been updated with
> the length needed
> 
> +                                          to complete the request.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +GetCpuCacheInfo (
> 
> +  IN OUT CPU_CACHE_INFO     *CpuCacheInfo,
> 
> +  IN OUT UINTN              *CpuCacheInfoCount
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINT32                    CpuidMaxInput;
> 
> +  UINT32                    NumberOfProcessors;
> 
> +  UINTN                     CacheDataCount;
> 
> +  UINTN                     ProcessorIndex;
> 
> +  EFI_PROCESSOR_INFORMATION ProcessorInfo;
> 
> +  COLLECT_CPUID_CACHE_DATA_CONTEXT  Context;
> 
> +
> 
> +  if (CpuCacheInfoCount == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  if (*CpuCacheInfoCount != 0 && CpuCacheInfo == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);
> 
> +  if (CpuidMaxInput < CPUID_CACHE_PARAMS) {
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.MpServices.
> 
> +  //
> 
> +  Status = CpuCacheInfoGetMpServices (&Context.MpServices);
> 
> +  if (EFI_ERROR(Status)) {
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  NumberOfProcessors = CpuCacheInfoGetNumberOfProcessors
> (Context.MpServices);
> 
> +
> 
> +  //
> 
> +  // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.ProcessorInfo.
> 
> +  //
> 
> +  Context.ProcessorInfo = AllocatePages (EFI_SIZE_TO_PAGES
> (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));
> 
> +  ASSERT (Context.ProcessorInfo != NULL);
> 
> +  if (Context.ProcessorInfo == NULL) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +  //
> 
> +  // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.CacheData.
> 
> +  // CacheData array consists of CPUID_CACHE_DATA data structure for each
> Cpuid Cache Parameter Leaf
> 
> +  // per logical processor. The array begin with data of each Cache Parameter
> Leaf of processor 0, followed
> 
> +  // by data of each Cache Parameter Leaf of processor 1 ...
> 
> +  //
> 
> +  CacheDataCount = NumberOfProcessors *
> MAX_NUM_OF_CACHE_PARAMS_LEAF;
> 
> +  Context.CacheData = AllocatePages (EFI_SIZE_TO_PAGES (CacheDataCount *
> sizeof (*Context.CacheData)));
> 
> +  ASSERT (Context.CacheData != NULL);
> 
> +  if (Context.CacheData == NULL) {
> 
> +    FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES
> (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +
> 
> +  ZeroMem (Context.CacheData, CacheDataCount * sizeof
> (*Context.CacheData));
> 
> +
> 
> +  //
> 
> +  // Collect Package ID and APIC ID of all processors.
> 
> +  //
> 
> +  for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors;
> ProcessorIndex++) {
> 
> +    CpuCacheInfoGetProcessorInfo (Context.MpServices, ProcessorIndex,
> &ProcessorInfo);
> 
> +    Context.ProcessorInfo[ProcessorIndex].Package =
> ProcessorInfo.Location.Package;
> 
> +    Context.ProcessorInfo[ProcessorIndex].ApicId  = (UINT32)
> ProcessorInfo.ProcessorId;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Wakeup all processors for CacheData(core type and cache data) collection.
> 
> +  //
> 
> +  CpuCacheInfoStartupAllCPUs (Context.MpServices,
> CpuCacheInfoCollectCoreAndCacheData, &Context);
> 
> +
> 
> +  //
> 
> +  // Collect CpuCacheInfo data from CacheData.
> 
> +  //
> 
> +  Status = CpuCacheInfoCollectCpuCacheInfoData (Context.CacheData,
> Context.ProcessorInfo, NumberOfProcessors, CpuCacheInfo,
> CpuCacheInfoCount);
> 
> +
> 
> +  FreePages (Context.CacheData, EFI_SIZE_TO_PAGES (CacheDataCount *
> sizeof (*Context.CacheData)));
> 
> +  FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES
> (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c
> b/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c
> new file mode 100644
> index 000000000000..bb788e36146b
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c
> @@ -0,0 +1,120 @@
> +/** @file
> 
> +  Provides cache info for each package, core type, cache level and cache type.
> 
> +
> 
> +  Copyright (c) 2020 Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <PiDxe.h>
> 
> +#include <Library/BaseLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/UefiBootServicesTableLib.h>
> 
> +#include <Library/CpuCacheInfoLib.h>
> 
> +#include <InternalCpuCacheInfoLib.h>
> 
> +
> 
> +/**
> 
> +  Get EFI_MP_SERVICES_PROTOCOL pointer.
> 
> +
> 
> +  @param[out] MpServices    A pointer to the buffer where
> EFI_MP_SERVICES_PROTOCOL is stored
> 
> +
> 
> +  @retval EFI_SUCCESS       EFI_MP_SERVICES_PROTOCOL interface is
> returned
> 
> +  @retval EFI_NOT_FOUND     EFI_MP_SERVICES_PROTOCOL interface is not
> found
> 
> +**/
> 
> +EFI_STATUS
> 
> +CpuCacheInfoGetMpServices (
> 
> +  OUT MP_SERVICES           *MpServices
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID
> **)&MpServices->Protocol);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Activate all of the logical processors.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +  @param[in]  Procedure           A pointer to the function to be run on enabled
> logical processors.
> 
> +  @param[in]  ProcedureArgument   The parameter passed into Procedure for
> all enabled logical processors.
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoStartupAllCPUs (
> 
> +  IN MP_SERVICES            MpServices,
> 
> +  IN EFI_AP_PROCEDURE       Procedure,
> 
> +  IN VOID                   *ProcedureArgument
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  Status = MpServices.Protocol->StartupAllAPs (MpServices.Protocol,
> Procedure, FALSE, NULL, 0, ProcedureArgument, NULL);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  Procedure (ProcedureArgument);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get detailed information of the requested logical processor.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +  @param[in]  ProcessorNum        The requested logical processor number.
> 
> +  @param[out] ProcessorInfo       A pointer to the buffer where the processor
> information is stored
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoGetProcessorInfo (
> 
> +  IN MP_SERVICES                MpServices,
> 
> +  IN UINTN                      ProcessorNum,
> 
> +  OUT EFI_PROCESSOR_INFORMATION *ProcessorInfo
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  Status = MpServices.Protocol->GetProcessorInfo (MpServices.Protocol,
> ProcessorNum, ProcessorInfo);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get the logical processor number.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +
> 
> +  @retval  Return the logical processor number.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoWhoAmI (
> 
> +  IN MP_SERVICES            MpServices
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINTN                     ProcessorNum;
> 
> +
> 
> +  Status = MpServices.Protocol->WhoAmI (MpServices.Protocol,
> &ProcessorNum);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  return (UINT32)ProcessorNum;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get the total number of logical processors in the platform.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +
> 
> +  @retval  Return the total number of logical processors.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoGetNumberOfProcessors (
> 
> +  IN MP_SERVICES            MpServices
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINTN                     NumberOfProcessor;
> 
> +  UINTN                     NumberOfEnabledProcessor;
> 
> +
> 
> +  Status = MpServices.Protocol->GetNumberOfProcessors
> (MpServices.Protocol, &NumberOfProcessor, &NumberOfEnabledProcessor);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  return (UINT32)NumberOfProcessor;
> 
> +}
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c
> b/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c
> new file mode 100644
> index 000000000000..06c160421b00
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c
> @@ -0,0 +1,119 @@
> +/** @file
> 
> +  Provides cache info for each package, core type, cache level and cache type.
> 
> +
> 
> +  Copyright (c) 2020 Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <PiPei.h>
> 
> +#include <Library/BaseLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/PeiServicesLib.h>
> 
> +#include <Library/PeiServicesTablePointerLib.h>
> 
> +#include <Library/CpuCacheInfoLib.h>
> 
> +#include <InternalCpuCacheInfoLib.h>
> 
> +
> 
> +/**
> 
> +  Get EDKII_PEI_MP_SERVICES2_PPI pointer.
> 
> +
> 
> +  @param[out] MpServices    A pointer to the buffer where
> EDKII_PEI_MP_SERVICES2_PPI is stored
> 
> +
> 
> +  @retval EFI_SUCCESS       EDKII_PEI_MP_SERVICES2_PPI interface is returned
> 
> +  @retval EFI_NOT_FOUND     EDKII_PEI_MP_SERVICES2_PPI interface is not
> found
> 
> +**/
> 
> +EFI_STATUS
> 
> +CpuCacheInfoGetMpServices (
> 
> +  OUT MP_SERVICES           *MpServices
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  Status = PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL,
> (VOID **)&MpServices->Ppi);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Activate all of the logical processors.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +  @param[in]  Procedure           A pointer to the function to be run on enabled
> logical processors.
> 
> +  @param[in]  ProcedureArgument   The parameter passed into Procedure for
> all enabled logical processors.
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoStartupAllCPUs (
> 
> +  IN MP_SERVICES            MpServices,
> 
> +  IN EFI_AP_PROCEDURE       Procedure,
> 
> +  IN VOID                   *ProcedureArgument
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  Status = MpServices.Ppi->StartupAllCPUs (MpServices.Ppi, Procedure, 0,
> ProcedureArgument);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get detailed information of the requested logical processor.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +  @param[in]  ProcessorNum        The requested logical processor number.
> 
> +  @param[out] ProcessorInfo       A pointer to the buffer where the processor
> information is stored
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoGetProcessorInfo (
> 
> +  IN MP_SERVICES                MpServices,
> 
> +  IN UINTN                      ProcessorNum,
> 
> +  OUT EFI_PROCESSOR_INFORMATION *ProcessorInfo
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +
> 
> +  Status = MpServices.Ppi->GetProcessorInfo (MpServices.Ppi, ProcessorNum,
> ProcessorInfo);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get the logical processor number.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +
> 
> +  @retval  Return the logical processor number.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoWhoAmI (
> 
> +  IN MP_SERVICES            MpServices
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINTN                     ProcessorNum;
> 
> +
> 
> +  Status = MpServices.Ppi->WhoAmI (MpServices.Ppi, &ProcessorNum);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  return (UINT32)ProcessorNum;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get the total number of logical processors in the platform.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +
> 
> +  @retval  Return the total number of logical processors.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoGetNumberOfProcessors (
> 
> +  IN MP_SERVICES            MpServices
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                Status;
> 
> +  UINTN                     NumberOfProcessor;
> 
> +  UINTN                     NumberOfEnabledProcessor;
> 
> +
> 
> +  Status = MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi,
> &NumberOfProcessor, &NumberOfEnabledProcessor);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  return (UINT32)NumberOfProcessor;
> 
> +}
> 
> diff --git a/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h
> b/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h
> new file mode 100644
> index 000000000000..a23b8b12b5ee
> --- /dev/null
> +++ b/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h
> @@ -0,0 +1,76 @@
> +/** @file
> 
> +  Header file for CPU Cache info Library.
> 
> +
> 
> +  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef _CPU_CACHE_INFO_LIB_H_
> 
> +#define _CPU_CACHE_INFO_LIB_H_
> 
> +
> 
> +typedef struct {
> 
> +  //
> 
> +  // Package number.
> 
> +  //
> 
> +  UINT32        Package;
> 
> +  //
> 
> +  // Core type of logical processor.
> 
> +  // Value = CPUID.1Ah:EAX[31:24]
> 
> +  //
> 
> +  UINT8         CoreType;
> 
> +  //
> 
> +  // Level of the cache that this package's this type of logical processor
> corresponds to.
> 
> +  // Value = CPUID.04h:EAX[07:05]
> 
> +  //
> 
> +  UINT8         CacheLevel : 3;
> 
> +  //
> 
> +  // Type of the cache that this package's this type of logical processor
> corresponds to.
> 
> +  // Value = CPUID.04h:EAX[04:00]
> 
> +  //
> 
> +  UINT8         CacheType : 5;
> 
> +  //
> 
> +  // Ways of associativity.
> 
> +  // Value = CPUID.04h:EBX[31:22]
> 
> +  //
> 
> +  UINT16        CacheWays;
> 
> +  //
> 
> +  // Size of single cache that this package's this type of logical processor
> corresponds to.
> 
> +  // Value = (CPUID.04h:EBX[31:22] + 1) * (CPUID.04h:EBX[21:12] + 1) *
> 
> +  //         (CPUID.04h:EBX[11:00] + 1) * (CPUID.04h:ECX[31:00] + 1)
> 
> +  //
> 
> +  UINT32        CacheSizeinKB;
> 
> +  //
> 
> +  // Number of the cache that this package's this type of logical processor
> corresponds to.
> 
> +  // Have subtracted the number of caches that are shared.
> 
> +  //
> 
> +  UINT16        CacheCount;
> 
> +} CPU_CACHE_INFO;
> 
> +
> 
> +/**
> 
> +  Get CpuCacheInfo data array.
> 
> +
> 
> +  @param[in, out] CpuCacheInfo        Pointer to the CpuCacheInfo array.
> 
> +  @param[in, out] CpuCacheInfoCount   As input, point to the length of
> response CpuCacheInfo array.
> 
> +                                      As output, point to the actual length of response
> CpuCacheInfo array.
> 
> +
> 
> +  @retval         EFI_SUCCESS             Function completed successfully.
> 
> +  @retval         EFI_INVALID_PARAMETER   CpuCacheInfoCount is NULL.
> 
> +  @retval         EFI_INVALID_PARAMETER   CpuCacheInfo is NULL while
> CpuCacheInfoCount contains the value
> 
> +                                          greater than zero.
> 
> +  @retval         EFI_UNSUPPORTED         Processor does not support
> CPUID_CACHE_PARAMS Leaf.
> 
> +  @retval         EFI_NOT_FOUND           EDKII_PEI_MP_SERVICES2_PPI or
> EFI_MP_SERVICES_PROTOCOL interface
> 
> +                                          is not found.
> 
> +  @retval         EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> 
> +  @retval         EFI_BUFFER_TOO_SMALL    CpuCacheInfoCount is too small to
> hold the response CpuCacheInfo
> 
> +                                          array. CpuCacheInfoCount has been updated with
> the length needed
> 
> +                                          to complete the request.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +GetCpuCacheInfo (
> 
> +  IN OUT CPU_CACHE_INFO     *CpuCacheInfo,
> 
> +  IN OUT UINTN              *CpuCacheInfoCount
> 
> +  );
> 
> +
> 
> +#endif
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni
> b/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni
> new file mode 100644
> index 000000000000..1bc801f15f84
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni
> @@ -0,0 +1,15 @@
> +// /** @file
> 
> +// CPU Cache Info Library
> 
> +//
> 
> +// Provides cache info for each package, core type, cache level and cache type.
> 
> +//
> 
> +// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +//
> 
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +//
> 
> +// **/
> 
> +
> 
> +
> 
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU Cache Info
> Library"
> 
> +
> 
> +#string STR_MODULE_DESCRIPTION          #language en-US "Provides cache
> info for each package, core type, cache level and cache type."
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
> b/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
> new file mode 100644
> index 000000000000..1fd45380b871
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
> @@ -0,0 +1,43 @@
> +## @file
> 
> +#  CPU Cache Info Library instance for DXE driver.
> 
> +#
> 
> +#  Provides cache info for each package, core type, cache level and cache type.
> 
> +#
> 
> +#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 0x00010005
> 
> +  BASE_NAME                      = DxeCpuCacheInfoLib
> 
> +  FILE_GUID                      = B25C288F-C309-41F1-8325-37E64DC5EA3D
> 
> +  MODULE_TYPE                    = DXE_DRIVER
> 
> +  VERSION_STRING                 = 1.0
> 
> +  LIBRARY_CLASS                  = CpuCacheInfoLib|DXE_DRIVER
> UEFI_APPLICATION
> 
> +  MODULE_UNI_FILE                = CpuCacheInfoLib.uni
> 
> +
> 
> +[Sources]
> 
> +  InternalCpuCacheInfoLib.h
> 
> +  CpuCacheInfoLib.c
> 
> +  DxeCpuCacheInfoLib.c
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  UefiCpuPkg/UefiCpuPkg.dec
> 
> +
> 
> +[LibraryClasses]
> 
> +  BaseLib
> 
> +  DebugLib
> 
> +  BaseMemoryLib
> 
> +  MemoryAllocationLib
> 
> +  UefiBootServicesTableLib
> 
> +
> 
> +[Protocols]
> 
> +  gEfiMpServiceProtocolGuid
> 
> +
> 
> +[Pcd]
> 
> +
> 
> +[Depex]
> 
> +  TRUE
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h
> b/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h
> new file mode 100644
> index 000000000000..de56db9c0cbe
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h
> @@ -0,0 +1,159 @@
> +/** @file
> 
> +  Internal header file for CPU Cache info Library.
> 
> +
> 
> +  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef _INTERNAL_CPU_CACHE_INFO_LIB_H_
> 
> +#define _INTERNAL_CPU_CACHE_INFO_LIB_H_
> 
> +
> 
> +#include <PiPei.h>
> 
> +#include <Register/Cpuid.h>
> 
> +#include <Ppi/MpServices2.h>
> 
> +#include <Protocol/MpService.h>
> 
> +#include <Library/BaseLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +#include <Library/CpuCacheInfoLib.h>
> 
> +
> 
> +typedef struct {
> 
> +  //
> 
> +  // Package ID, the information comes from
> 
> +  // EFI_CPU_PHYSICAL_LOCATION.Package
> 
> +  //
> 
> +  UINT32                    Package;
> 
> +  //
> 
> +  // APIC ID, the information comes from
> 
> +  // EFI_PROCESSOR_INFORMATION.ProcessorId
> 
> +  //
> 
> +  UINT32                    ApicId;
> 
> +  //
> 
> +  // Core type of logical processor.
> 
> +  // Value = CPUID.1Ah:EAX[31:24]
> 
> +  //
> 
> +  UINT8                     CoreType;
> 
> +} CPUID_PROCESSOR_INFO;
> 
> +
> 
> +typedef struct {
> 
> +  //
> 
> +  // Level of the cache.
> 
> +  // Value = CPUID.04h:EAX[07:05]
> 
> +  //
> 
> +  UINT8                     CacheLevel : 3;
> 
> +  //
> 
> +  // Type of the cache.
> 
> +  // Value = CPUID.04h:EAX[04:00]
> 
> +  //
> 
> +  UINT8                     CacheType : 5;
> 
> +  //
> 
> +  // Ways of associativity.
> 
> +  // Value = CPUID.04h:EBX[31:22]
> 
> +  //
> 
> +  UINT16                    CacheWays;
> 
> +  //
> 
> +  // Cache share bits.
> 
> +  // Value = CPUID.04h:EAX[25:14]
> 
> +  //
> 
> +  UINT16                    CacheShareBits;
> 
> +  //
> 
> +  // Size of single cache.
> 
> +  // Value = (CPUID.04h:EBX[31:22] + 1) * (CPUID.04h:EBX[21:12] + 1) *
> 
> +  //         (CPUID.04h:EBX[11:00] + 1) * (CPUID.04h:ECX[31:00] + 1)
> 
> +  //
> 
> +  UINT32                    CacheSizeinKB;
> 
> +} CPUID_CACHE_DATA;
> 
> +
> 
> +typedef union {
> 
> +  EDKII_PEI_MP_SERVICES2_PPI    *Ppi;
> 
> +  EFI_MP_SERVICES_PROTOCOL      *Protocol;
> 
> +} MP_SERVICES;
> 
> +
> 
> +typedef struct {
> 
> +  MP_SERVICES               MpServices;
> 
> +  CPUID_PROCESSOR_INFO      *ProcessorInfo;
> 
> +  CPUID_CACHE_DATA          *CacheData;
> 
> +} COLLECT_CPUID_CACHE_DATA_CONTEXT;
> 
> +
> 
> +
> 
> +/*
> 
> +  Defines the maximum count of Deterministic Cache Parameters Leaf of all
> APs and BSP.
> 
> +  To save boot time, skip starting up all APs to calculate each AP's count of
> Deterministic
> 
> +  Cache Parameters Leaf, so use a definition instead.
> 
> +  Anyway, definition value will be checked in
> CpuCacheInfoCollectCoreAndCacheData function.
> 
> +*/
> 
> +#define MAX_NUM_OF_CACHE_PARAMS_LEAF    6
> 
> +
> 
> +/*
> 
> +  Defines the maximum count of packages.
> 
> +*/
> 
> +#define MAX_NUM_OF_PACKAGE              100
> 
> +
> 
> +/**
> 
> +  Get EDKII_PEI_MP_SERVICES2_PPI or EFI_MP_SERVICES_PROTOCOL pointer.
> 
> +
> 
> +  @param[out] MpServices    A pointer to the buffer where
> EDKII_PEI_MP_SERVICES2_PPI or
> 
> +                            EFI_MP_SERVICES_PROTOCOL is stored
> 
> +
> 
> +  @retval EFI_SUCCESS       EDKII_PEI_MP_SERVICES2_PPI or
> EFI_MP_SERVICES_PROTOCOL interface is returned
> 
> +  @retval EFI_NOT_FOUND     EDKII_PEI_MP_SERVICES2_PPI or
> EFI_MP_SERVICES_PROTOCOL interface is not found
> 
> +**/
> 
> +EFI_STATUS
> 
> +CpuCacheInfoGetMpServices (
> 
> +  OUT MP_SERVICES           *MpServices
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Activate all of the logical processors.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +  @param[in]  Procedure           A pointer to the function to be run on enabled
> logical processors.
> 
> +  @param[in]  ProcedureArgument   The parameter passed into Procedure for
> all enabled logical processors.
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoStartupAllCPUs (
> 
> +  IN MP_SERVICES            MpServices,
> 
> +  IN EFI_AP_PROCEDURE       Procedure,
> 
> +  IN VOID                   *ProcedureArgument
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Get detailed information of the requested logical processor.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +  @param[in]  ProcessorNum        The requested logical processor number.
> 
> +  @param[out] ProcessorInfo       A pointer to the buffer where the processor
> information is stored
> 
> +**/
> 
> +VOID
> 
> +CpuCacheInfoGetProcessorInfo (
> 
> +  IN MP_SERVICES                MpServices,
> 
> +  IN UINTN                      ProcessorNum,
> 
> +  OUT EFI_PROCESSOR_INFORMATION *ProcessorInfo
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Get the logical processor number.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +
> 
> +  @retval  Return the logical processor number.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoWhoAmI (
> 
> +  IN MP_SERVICES            MpServices
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Get the total number of logical processors in the platform.
> 
> +
> 
> +  @param[in]  MpServices          MP_SERVICES structure.
> 
> +
> 
> +  @retval  Return the total number of logical processors.
> 
> +**/
> 
> +UINT32
> 
> +CpuCacheInfoGetNumberOfProcessors (
> 
> +  IN MP_SERVICES            MpServices
> 
> +  );
> 
> +#endif
> 
> diff --git a/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
> b/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
> new file mode 100644
> index 000000000000..c8aa33c95a8f
> --- /dev/null
> +++ b/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
> @@ -0,0 +1,43 @@
> +## @file
> 
> +#  CPU Cache Info Library instance for PEI module.
> 
> +#
> 
> +#  Provides cache info for each package, core type, cache level and cache type.
> 
> +#
> 
> +#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 0x00010005
> 
> +  BASE_NAME                      = PeiCpuCacheInfoLib
> 
> +  FILE_GUID                      = CFEE2DBE-53B2-4916-84CA-0BA83C3DDA6E
> 
> +  MODULE_TYPE                    = PEIM
> 
> +  VERSION_STRING                 = 1.0
> 
> +  LIBRARY_CLASS                  = CpuCacheInfoLib|PEIM
> 
> +  MODULE_UNI_FILE                = CpuCacheInfoLib.uni
> 
> +
> 
> +[Sources]
> 
> +  InternalCpuCacheInfoLib.h
> 
> +  CpuCacheInfoLib.c
> 
> +  PeiCpuCacheInfoLib.c
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  UefiCpuPkg/UefiCpuPkg.dec
> 
> +
> 
> +[LibraryClasses]
> 
> +  BaseLib
> 
> +  DebugLib
> 
> +  BaseMemoryLib
> 
> +  MemoryAllocationLib
> 
> +  PeiServicesTablePointerLib
> 
> +
> 
> +[Ppis]
> 
> +  gEdkiiPeiMpServices2PpiGuid
> 
> +
> 
> +[Pcd]
> 
> +
> 
> +[Depex]
> 
> +  TRUE
> 
> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> index d83c084467b3..a639ce5412e4 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dec
> +++ b/UefiCpuPkg/UefiCpuPkg.dec
> @@ -56,6 +56,9 @@ [LibraryClasses.IA32, LibraryClasses.X64]
>    ##  @libraryclass  Provides function to support VMGEXIT processing.
> 
>    VmgExitLib|Include/Library/VmgExitLib.h
> 
> 
> 
> +  ##  @libraryclass  Provides function to get CPU cache information.
> 
> +  CpuCacheInfoLib|Include/Library/CpuCacheInfoLib.h
> 
> +
> 
>  [Guids]
> 
>    gUefiCpuPkgTokenSpaceGuid      = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8,
> 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
> 
>    gMsegSmramGuid                 = { 0x5802bce4, 0xeeee, 0x4e33, { 0xa1, 0x30,
> 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 }}
> 
> diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
> index b2b6d78a71b0..5834eafaa200 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -75,6 +75,7 @@ [LibraryClasses.common.PEIM]
>    LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
> 
>    MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
> 
> 
> RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegist
> erCpuFeaturesLib.inf
> 
> +
> CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
> 
> 
> 
>  [LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM]
> 
> 
> PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiS
> ervicesTablePointerLibIdt.inf
> 
> @@ -86,6 +87,7 @@ [LibraryClasses.common.DXE_DRIVER]
> 
> CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpu
> ExceptionHandlerLib.inf
> 
>    MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
> 
> 
> RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegist
> erCpuFeaturesLib.inf
> 
> +
> CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
> 
> 
> 
>  [LibraryClasses.common.DXE_SMM_DRIVER]
> 
> 
> SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTab
> leLib.inf
> 
> @@ -109,6 +111,8 @@ [Components]
>    UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
> 
>    UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
> 
>    UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
> 
> +  UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
> 
> +  UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
> 
> 
> 
>  [Components.IA32, Components.X64]
> 
>    UefiCpuPkg/CpuDxe/CpuDxe.inf
> 
> --
> 2.28.0.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#70188): https://edk2.groups.io/g/devel/message/70188
Mute This Topic: https://groups.io/mt/79491813/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list