REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the UefiCpuPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			501 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			501 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Provides cache info for each package, core type, cache level and cache type.
 | |
| 
 | |
|   Copyright (c) 2020 - 2021, 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 (FA|DM) CacheSizeinKB  CacheCount |\n"));
 | |
|   DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));
 | |
| 
 | |
|   for (Index = 0; Index < CpuCacheInfoCount; Index++) {
 | |
|     DEBUG ((
 | |
|       DEBUG_INFO,
 | |
|       "| %4x  | %4x       %2x        %2x          %2x       %4x     ( %x| %x) %8x         %4x     |\n",
 | |
|       Index,
 | |
|       CpuCacheInfo[Index].Package,
 | |
|       CpuCacheInfo[Index].CoreType,
 | |
|       CpuCacheInfo[Index].CacheLevel,
 | |
|       CpuCacheInfo[Index].CacheType,
 | |
|       CpuCacheInfo[Index].CacheWays,
 | |
|       CpuCacheInfo[Index].FullyAssociativeCache,
 | |
|       CpuCacheInfo[Index].DirectMappedCache,
 | |
|       CpuCacheInfo[Index].CacheSizeinKB,
 | |
|       CpuCacheInfo[Index].CacheCount
 | |
|       ));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function to compare CPU package ID, core type, cache level and cache type for use in QuickSort.
 | |
| 
 | |
|   @param[in]  Buffer1             pointer to CPU_CACHE_INFO poiner to compare
 | |
|   @param[in]  Buffer2             pointer to second CPU_CACHE_INFO pointer to compare
 | |
| 
 | |
|   @retval  0                      Buffer1 equal to Buffer2
 | |
|   @retval  1                      Buffer1 is greater than Buffer2
 | |
|   @retval  -1                     Buffer1 is less than Buffer2
 | |
| **/
 | |
| INTN
 | |
| EFIAPI
 | |
| CpuCacheInfoCompare (
 | |
|   IN CONST VOID  *Buffer1,
 | |
|   IN CONST VOID  *Buffer2
 | |
|   )
 | |
| {
 | |
|   CPU_CACHE_INFO_COMPARATOR  Comparator1, Comparator2;
 | |
| 
 | |
|   ZeroMem (&Comparator1, sizeof (Comparator1));
 | |
|   ZeroMem (&Comparator2, sizeof (Comparator2));
 | |
| 
 | |
|   Comparator1.Bits.Package    = ((CPU_CACHE_INFO *)Buffer1)->Package;
 | |
|   Comparator1.Bits.CoreType   = ((CPU_CACHE_INFO *)Buffer1)->CoreType;
 | |
|   Comparator1.Bits.CacheLevel = ((CPU_CACHE_INFO *)Buffer1)->CacheLevel;
 | |
|   Comparator1.Bits.CacheType  = ((CPU_CACHE_INFO *)Buffer1)->CacheType;
 | |
| 
 | |
|   Comparator2.Bits.Package    = ((CPU_CACHE_INFO *)Buffer2)->Package;
 | |
|   Comparator2.Bits.CoreType   = ((CPU_CACHE_INFO *)Buffer2)->CoreType;
 | |
|   Comparator2.Bits.CacheLevel = ((CPU_CACHE_INFO *)Buffer2)->CacheLevel;
 | |
|   Comparator2.Bits.CacheType  = ((CPU_CACHE_INFO *)Buffer2)->CacheType;
 | |
| 
 | |
|   if (Comparator1.Uint64 == Comparator2.Uint64) {
 | |
|     return 0;
 | |
|   } else if (Comparator1.Uint64 > Comparator2.Uint64) {
 | |
|     return 1;
 | |
|   } else {
 | |
|     return -1;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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, out] Buffer              The pointer to private data buffer.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| CpuCacheInfoCollectCoreAndCacheData (
 | |
|   IN OUT VOID  *Buffer
 | |
|   )
 | |
| {
 | |
|   UINTN                                    ProcessorIndex;
 | |
|   UINT32                                   CpuidMaxInput;
 | |
|   UINT8                                    CacheParamLeafIndex;
 | |
|   CPUID_CACHE_PARAMS_EAX                   CacheParamEax;
 | |
|   CPUID_CACHE_PARAMS_EBX                   CacheParamEbx;
 | |
|   UINT32                                   CacheParamEcx;
 | |
|   CPUID_CACHE_PARAMS_EDX                   CacheParamEdx;
 | |
|   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_MAIN_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, &CacheParamEdx.Uint32);
 | |
| 
 | |
|     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].FullyAssociativeCache = (UINT8)CacheParamEax.Bits.FullyAssociativeCache;
 | |
|     CacheData[CacheParamLeafIndex].DirectMappedCache     = (UINT8)(CacheParamEdx.Bits.ComplexCacheIndexing == 0);
 | |
|     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;
 | |
|   CPU_CACHE_INFO  SortBuffer;
 | |
| 
 | |
|   //
 | |
|   // 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].FullyAssociativeCache = CacheData[Index].FullyAssociativeCache;
 | |
|       LocalCacheInfo[LocalCacheInfoCount].DirectMappedCache     = CacheData[Index].DirectMappedCache;
 | |
|       LocalCacheInfo[LocalCacheInfoCount].CacheSizeinKB         = CacheData[Index].CacheSizeinKB;
 | |
|       LocalCacheInfo[LocalCacheInfoCount].CacheCount            = 1;
 | |
| 
 | |
|       LocalCacheInfoCount++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (*CacheInfoCount < LocalCacheInfoCount) {
 | |
|     Status = EFI_BUFFER_TOO_SMALL;
 | |
|   } else {
 | |
|     //
 | |
|     // Sort LocalCacheInfo array by CPU package ID, core type, cache level and cache type.
 | |
|     //
 | |
|     QuickSort (LocalCacheInfo, LocalCacheInfoCount, sizeof (*LocalCacheInfo), CpuCacheInfoCompare, (VOID *)&SortBuffer);
 | |
|     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. The array is sorted by CPU package ID, core type, cache level and cache type.
 | |
| 
 | |
|   @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_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.
 | |
|   //
 | |
|   CpuCacheInfoGetMpServices (&Context.MpServices);
 | |
| 
 | |
|   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;
 | |
| }
 |