/*++
Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
Module Name:
MiscProcessorCacheFunction.c
Abstract:
BIOS processor cache details.
Misc. subclass type 7.
SMBIOS type 7.
--*/
#include "CommonHeader.h"
#include "MiscSubclassDriver.h"
#include
MISC_SMBIOS_TABLE_FUNCTION(MiscProcessorCache)
{
EFI_SMBIOS_HANDLE SmbiosHandle;
SMBIOS_TABLE_TYPE7 *SmbiosRecord;
EFI_CACHE_SRAM_TYPE_DATA CacheSramType;
CHAR16 *SocketDesignation;
CHAR8 *OptionalStrStart;
UINTN SocketStrLen;
STRING_REF TokenToGet;
UINT32 SubIndex;
CPUID_CACHE_PARAMS_EAX CacheParamsEax;
CPUID_CACHE_PARAMS_EBX CacheParamsEbx;
UINT32 RegisterEcx;
CPUID_CACHE_PARAMS_EDX CacheParamsEdx;
UINT8 SystemCacheType;
UINTN Size;
//
// Memory Device Locator
//
TokenToGet = STRING_TOKEN (STR_SOCKET_DESIGNATION);
SocketDesignation = SmbiosMiscGetString (TokenToGet);
SocketStrLen = StrLen(SocketDesignation);
if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) {
return EFI_UNSUPPORTED;
}
//
// Retrieve cache level information using CPUID
//
for (SubIndex = 0; ; SubIndex++) {
AsmCpuidEx (
CPUID_CACHE_PARAMS,
SubIndex,
&CacheParamsEax.Uint32,
&CacheParamsEbx.Uint32,
&RegisterEcx,
&CacheParamsEdx.Uint32
);
//
// Terminate loop when CacheType is CPUID_CACHE_PARAMS_CACHE_TYPE_NULL
//
if (CacheParamsEax.Bits.CacheType == CPUID_CACHE_PARAMS_CACHE_TYPE_NULL) {
break;
}
//
// Allocate and zero SMBIOS TYPE 7 Record
//
SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE7) + 7 + 1 + 1);
ASSERT (SmbiosRecord != NULL);
//
// Compute cache size in bytes
//
Size = (CacheParamsEbx.Bits.Ways + 1) *
(CacheParamsEbx.Bits.LinePartitions + 1) *
(CacheParamsEbx.Bits.LineSize + 1) *
(RegisterEcx + 1);
DEBUG ((DEBUG_INFO, "MiscProcessorCache(): Cache Type = %d Cache Level = %d Size = %x\n", CacheParamsEax.Bits.CacheType, CacheParamsEax.Bits.CacheLevel, Size));
//
// Determine SMBIOS SystemCacheType
//
switch (CacheParamsEax.Bits.CacheType) {
case 1:
SystemCacheType = CacheTypeData;
break;
case 2:
SystemCacheType = CacheTypeInstruction;
break;
case 3:
SystemCacheType = CacheTypeUnified;
break;
default:
SystemCacheType = CacheTypeUnknown;
}
//
// Update cache sizes in KB
//
switch (CacheParamsEax.Bits.CacheLevel) {
case 1:
SmbiosRecord->InstalledSize = (UINT16)(Size >> 10);
SmbiosRecord->MaximumCacheSize = SmbiosRecord->InstalledSize;
SmbiosRecord->SystemCacheType = SystemCacheType;
SmbiosRecord->Associativity = CacheAssociativity8Way;
SmbiosRecord->CacheConfiguration = 0x0180;
break;
case 2:
SmbiosRecord->InstalledSize = (UINT16)(Size >> 10);
SmbiosRecord->MaximumCacheSize = SmbiosRecord->InstalledSize;
SmbiosRecord->SystemCacheType = SystemCacheType;
SmbiosRecord->Associativity = CacheAssociativity16Way;
SmbiosRecord->CacheConfiguration = 0x0281;
//
//VLV2 incorporates two SLM modules (quad cores) in the SoC.
// 2 cores share BIU/L2 cache
//
SmbiosRecord->InstalledSize = SmbiosRecord->InstalledSize / 2;
SmbiosRecord->MaximumCacheSize = SmbiosRecord->InstalledSize;
break;
default:
DEBUG ((DEBUG_ERROR, "MiscProcessorCache(): Unexpected cache level %d\n", CacheParamsEax.Bits.CacheLevel));
break;
}
//
//Filling SMBIOS type 7 information for different cache levels.
//
SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;
SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE7);
SmbiosRecord->Hdr.Handle = 0;
SmbiosRecord->SocketDesignation = 0x01;
SmbiosRecord->CacheSpeed = 0;
ZeroMem (&CacheSramType, sizeof (EFI_CACHE_SRAM_TYPE_DATA));
CacheSramType.Synchronous = 1;
CopyMem(&SmbiosRecord->SupportedSRAMType, &CacheSramType, 2);
CopyMem(&SmbiosRecord->CurrentSRAMType, &CacheSramType, 2);
SmbiosRecord->ErrorCorrectionType = EfiCacheErrorSingleBit;
//
// Adding SMBIOS type 7 records to SMBIOS table.
//
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
UnicodeStrToAsciiStrS (SocketDesignation, OptionalStrStart, + 7 + 1 + 1);
Smbios->Add(
Smbios,
NULL,
&SmbiosHandle,
(EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
);
}
return EFI_SUCCESS;
}