summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c')
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c515
1 files changed, 515 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c b/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c
new file mode 100644
index 0000000..f68c151
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c
@@ -0,0 +1,515 @@
+/** @file
+ Processor Cache data records.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuAccess.h"
+#include "CacheData.h"
+#endif
+///
+/// This is the VFR compiler generated header file which defines the
+/// string identifiers.
+///
+#include "CpuInitDxeStrDefs.h"
+
+extern EFI_DATA_HUB_PROTOCOL *mDataHub;
+extern EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader;
+
+EFI_CACHE_CONVERTER mCacheConverter[] = {
+ {
+ 1,
+ 0x09,
+ 32,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeInstruction
+ },
+ {
+ 1,
+ 0x0D,
+ 16,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeData
+ },
+ {
+ 2,
+ 0x21,
+ 256,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 1,
+ 0x2C,
+ 32,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeData
+ },
+ {
+ 2,
+ 0x40,
+ 0,
+ EfiCacheAssociativityUnknown,
+ EfiCacheTypeUnknown
+ },
+ {
+ 3,
+ 0xD0,
+ 512,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD1,
+ 1024,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD2,
+ 2048,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD3,
+ 4096,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD4,
+ 8192,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD6,
+ 1024,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD7,
+ 2048,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD8,
+ 4096,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD9,
+ 8192,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDA,
+ 12288,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDC,
+ 1536,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDD,
+ 3072,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDE,
+ 6144,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDF,
+ 12288,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE0,
+ 18432,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE2,
+ 2048,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE3,
+ 4096,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE4,
+ 8192,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE5,
+ 16384,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE6,
+ 24576,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xEA,
+ 12288,
+ EfiCacheAssociativity24Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xEB,
+ 18432,
+ EfiCacheAssociativity24Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xEC,
+ 24567,
+ EfiCacheAssociativity24Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 0,
+ 0xFF,
+ 0,
+ 0,
+ 0
+ }
+};
+
+///
+/// Convert Cache Type Field to SMBIOS format
+///
+#define SMBIOS_CACHE_TYPE_MAX 5
+UINT8 SmbiosCacheTypeFieldConverter[SMBIOS_CACHE_TYPE_MAX] = {
+ EfiCacheTypeUnknown,
+ EfiCacheTypeData,
+ EfiCacheTypeInstruction,
+ EfiCacheTypeUnified,
+ EfiCacheTypeOther
+};
+
+UINT8 mCacheInstance[EFI_CACHE_LMAX] = { 0, 0, 0, 0 };
+
+EFI_SUBCLASS_TYPE1_HEADER mCacheDataRecordHeader = {
+ EFI_CACHE_SUBCLASS_VERSION, ///< Version
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER), ///< Header Size
+ 0, ///< Instance, Initialize later
+ 0, ///< SubInstance, Initialize later to Cache Level
+ 0 ///< RecordType, Initialize later
+};
+
+/**
+ This function gets called with the processor number and will log all cache data to data hub
+ pertaining to this processor.
+
+ @param[in] CpuNumber - Processor Number
+ @param[in] CacheInformation - Cache information get from cpuid instruction
+
+ @retval EFI_OUT_OF_RESOURCES - Failed to allocate required POOL for record buffer.
+ @retval EFI_SUCCESS - successful to update cache data
+**/
+EFI_STATUS
+InitializeCacheData (
+ IN UINTN CpuNumber,
+ IN EFI_CPUID_REGISTER *CacheInformation
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HeaderSize;
+ UINT32 TotalSize;
+ CPU_CACHE_DATA_RECORD_BUFFER RecordBuffer;
+ UINT8 Index1;
+ UINT8 CacheLevel;
+ UINT8 LxCacheType;
+ UINT32 Ways;
+ UINT32 Partitions;
+ UINT32 LineSets;
+ UINT32 Sets;
+ UINT32 LxCacheSize;
+ EFI_CPUID_REGISTER CpuidRegisters;
+
+ ///
+ /// Only log CPU socket level information.
+ ///
+ if (CpuNumber != 0) {
+ return EFI_SUCCESS;
+ }
+
+ mCacheDataRecordHeader.Instance = (UINT16) (CpuNumber + 1);
+
+ HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
+ RecordBuffer.Raw = AllocatePool (HeaderSize + CPU_CACHE_DATA_MAXIMUM_LENGTH);
+ if (RecordBuffer.Raw == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index1 = 0;; Index1++) {
+ EfiCpuidExt (CPUID_CACHE_PARAMS, Index1, &CpuidRegisters);
+ if ((CpuidRegisters.RegEax & V_CPUID_CACHE_TYPE_MASK) == 0) {
+ break;
+ }
+
+ Ways = ((CpuidRegisters.RegEbx >> B_CPUID_CACHE_PARAMS_WAYS_SHIFT) & 0x3FF) + 1;
+ Partitions = ((CpuidRegisters.RegEbx >> B_CPUID_CACHE_PARAMS_PARTITIONS_SHIFT) & 0x3FF) + 1;
+ LineSets = (CpuidRegisters.RegEbx & 0xFFF) + 1;
+ Sets = CpuidRegisters.RegEcx + 1;
+
+ CacheLevel = (UINT8) (CpuidRegisters.RegEax & V_CPUID_CACHE_LEVEL_MASK) >> B_CPUID_CACHE_LEVEL_SHIFT;
+ LxCacheSize = (Ways * Partitions * LineSets * Sets) / 1024;
+ LxCacheType = (UINT8) (CpuidRegisters.RegEax & V_CPUID_CACHE_TYPE_MASK);
+
+ CopyMem (RecordBuffer.Raw, &mCacheDataRecordHeader, HeaderSize);
+
+ mCacheInstance[CacheLevel - 1]++;
+ RecordBuffer.DataRecord->DataRecordHeader.Instance = mCacheInstance[CacheLevel - 1];
+ RecordBuffer.DataRecord->DataRecordHeader.SubInstance = CacheLevel;
+
+ ///
+ /// Record Type 1
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSizeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SIZE_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheSize.Value = (UINT16) LxCacheSize;
+ RecordBuffer.DataRecord->VariableRecord.CacheSize.Exponent = 10;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 2
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = MaximumSizeCacheRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_MAXIMUM_CACHE_SIZE_DATA);
+ RecordBuffer.DataRecord->VariableRecord.MaximumCacheSize.Value = (UINT16) LxCacheSize;
+ RecordBuffer.DataRecord->VariableRecord.MaximumCacheSize.Exponent = 10;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 3
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSpeedRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SPEED_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheSpeed.Exponent = 0;
+ RecordBuffer.DataRecord->VariableRecord.CacheSpeed.Value = 0;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 4
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSocketRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SOCKET_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheSocket = 0;
+ ///
+ /// CacheDesignation[Index1];
+ ///
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 5
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSramTypeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SRAM_TYPE_DATA);
+ ZeroMem (
+ &RecordBuffer.DataRecord->VariableRecord.CacheSramType,
+ sizeof (EFI_CACHE_SRAM_TYPE_DATA)
+ );
+ RecordBuffer.DataRecord->VariableRecord.CacheSramType.Synchronous = TRUE;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 6, since record same as Type 5
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheInstalledSramTypeRecordType;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 7
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheErrorTypeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_ERROR_TYPE_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheErrorType = EfiCacheErrorSingleBit;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 8
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheTypeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_TYPE_DATA);
+ ///
+ /// If cache type is larger or equal than 5, this is undefined type so mark it as "Other" Cache type.
+ ///
+ if (LxCacheType >= SMBIOS_CACHE_TYPE_MAX) {
+ LxCacheType = SMBIOS_CACHE_TYPE_MAX - 1;
+ }
+ RecordBuffer.DataRecord->VariableRecord.CacheType = SmbiosCacheTypeFieldConverter[LxCacheType];
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 9
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheAssociativityRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_ASSOCIATIVITY_DATA);
+ ///
+ /// Convert Associativity Ways to SMBIOS format
+ ///
+ switch (Ways) {
+ case 2:
+ Ways = EfiCacheAssociativity2Way;
+ break;
+ case 4:
+ Ways = EfiCacheAssociativity4Way;
+ break;
+ case 8:
+ Ways = EfiCacheAssociativity8Way;
+ break;
+ case 12:
+ Ways = EfiCacheAssociativity12Way;
+ break;
+ case 16:
+ Ways = EfiCacheAssociativity16Way;
+ break;
+ case 24:
+ Ways = EfiCacheAssociativity24Way;
+ break;
+ case 32:
+ Ways = EfiCacheAssociativity32Way;
+ break;
+ case 48:
+ Ways = EfiCacheAssociativity48Way;
+ break;
+ case 64:
+ Ways = EfiCacheAssociativity64Way;
+ break;
+ default:
+ Ways = EfiCacheAssociativityOther;
+ break;
+ }
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociativity = Ways;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 10
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheConfigRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_CONFIGURATION_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Level = CacheLevel;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Socketed = EFI_CACHE_NOT_SOCKETED;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Reserved2 = 0;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Location = EfiCacheInternal;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Enable = EFI_CACHE_ENABLED;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.OperationalMode = EfiCacheWriteBack;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Reserved1 = 0;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Cache Association. Processor Record Type 17
+ ///
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_ASSOCIATION_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociation.ProducerName = gEfiProcessorProducerGuid;
+ ///
+ /// RecordBuffer.DataRecord->VariableRecord.CacheAssociation.ProducerInstance = (UINT16)Instance;
+ ///
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociation.Instance = RecordBuffer.DataRecord->DataRecordHeader.Instance;
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociation.SubInstance = RecordBuffer.DataRecord->DataRecordHeader.SubInstance;
+ CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheAssociationRecordType;
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+ }
+
+ FreePool (RecordBuffer.Raw);
+ return EFI_SUCCESS;
+}
+
+/**
+ Log cache data into data hub
+
+ @param[in] DataHub - Pointer to the DataHub protocol that will be updated
+ @param[in] Buffer - Data buffer which will be updated into DataHub
+ @param[in] Size - The size of data buffer
+
+ @retval EFI_STATUS - status code for logging data into dat hub
+**/
+EFI_STATUS
+LogCacheData (
+ EFI_DATA_HUB_PROTOCOL *DataHub,
+ UINT8 *Buffer,
+ UINT32 Size
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiCacheSubClassGuid,
+ &gEfiProcessorProducerGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ Buffer,
+ Size
+ );
+ return Status;
+}