From nobody Mon Nov 25 12:34:41 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+70309+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+70309+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1610642220; cv=none; d=zohomail.com; s=zohoarc; b=OEvWfj5x0uL4SgFKJzO3KZbEZd8K8tYaRbxZ1QAu7BUR+pexApfECMF8YOPebZ0R5mVRyjt3ABMgB53CoDktRj2ZAAvie3Aau6WcrJeMu8+MOyZppldx/ruSQq4gYQxBUwvrkIa07Zj9IrPEcp5BS+Tpkq8OdnyCTM5jY/4Ekh4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1610642220; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=kjN8kJo5QrbS55JQ6BikuUm1CKRVnkFeopEobg/u+SM=; b=bWfDCti/9/Rs7OoQJrq4X7oSPW5bd+HqAmFM45Qm3s8fzPoo6rax2va944J88PnzCw3x0SlQ2bgHkjOz2rW4OCZ5K8qDq15918UhCG3v2CRsaflNP52xBDM90ut217EQv48cADYRs5SPb/S3I2dLZXneCyQygk+jIMpiSWIR0ts= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+70309+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1610642219994502.8664717930242; Thu, 14 Jan 2021 08:36:59 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id yXFSYY1788612x94Tgl4Sv01; Thu, 14 Jan 2021 08:36:59 -0800 X-Received: from mail-io1-f54.google.com (mail-io1-f54.google.com [209.85.166.54]) by mx.groups.io with SMTP id smtpd.web11.4159.1610642216282718489 for ; Thu, 14 Jan 2021 08:36:56 -0800 X-Received: by mail-io1-f54.google.com with SMTP id y19so12419103iov.2 for ; Thu, 14 Jan 2021 08:36:56 -0800 (PST) X-Gm-Message-State: r3nYpf6B7wEuMMdHulIWbXePx1787277AA= X-Google-Smtp-Source: ABdhPJxJO/iHM2okw3A4qDTxjsdInvsKDs2qnDeF4d8DgA6v7TF8YsQsC6fOr6nTzute988yHzzEBw== X-Received: by 2002:a92:77c9:: with SMTP id s192mr7159547ilc.75.1610642214917; Thu, 14 Jan 2021 08:36:54 -0800 (PST) X-Received: from cube.nuviainc.com (c-174-52-16-57.hsd1.ut.comcast.net. [174.52.16.57]) by smtp.gmail.com with ESMTPSA id y5sm3711920ilj.35.2021.01.14.08.36.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 08:36:54 -0800 (PST) From: "Rebecca Cran" To: devel@edk2.groups.io Cc: Rebecca Cran , Leif Lindholm , Ard Biesheuvel , nd@arm.com, Sami Mujawar , Liming Gao , Michael D Kinney , Zhiguang Liu , Samer El-Haj-Mahmoud Subject: [edk2-devel] [PATCH v6 14/22] ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe Date: Thu, 14 Jan 2021 09:36:20 -0700 Message-Id: <20210114163628.31952-15-rebecca@nuviainc.com> In-Reply-To: <20210114163628.31952-1-rebecca@nuviainc.com> References: <20210114163628.31952-1-rebecca@nuviainc.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,rebecca@nuviainc.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1610642219; bh=5FbOyRC4r7JVBOp5EtdM4xznPuoiaDxk/YMO40OoYqo=; h=Cc:Date:From:Reply-To:Subject:To; b=IA/Bz23FGERrwE+p4Cm7ViKbat90BzgcqWWqS3iCCAonJQ7//NsXiH6EdXVK6pCw8M1 I1EtYHdipFzwaDNqxo4uz8Zz35I3wc9q0fY2MHcFNNpNxqJDPqLH4TGNq+x5/Q9TkiczL 1c+CY5MCKSreXXkAvXUb+pScyIAUVewp+YY= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" ProcessorSubClassDxe provides SMBIOS CPU information using generic methods combined with calls into OemMiscLib. Signed-off-by: Rebecca Cran Reviewed-by: Samer El-Haj-Mahmoud --- ArmPkg/ArmPkg.dsc = | 2 + ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf = | 58 ++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c = | 863 ++++++++++++++++++++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni = | 24 + 4 files changed, 947 insertions(+) diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index 0f77a6da4483..fce86cb6d710 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -148,6 +148,8 @@ [Components.common] ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf =20 + ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf + [Components.AARCH64] ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass= Dxe.inf b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe= .inf new file mode 100644 index 000000000000..c8ef3ee56b72 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf @@ -0,0 +1,58 @@ +#/** @file +# ProcessorSubClassDxe.inf +# +# Copyright (c) 2021, NUVIA Inc. All rights reserved. +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + + +[Defines] + INF_VERSION =3D 1.29 + BASE_NAME =3D ProcessorSubClass + FILE_GUID =3D f3fe0e33-ea38-4069-9fb5-be23407207c7 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D ProcessorSubClassEntryPoint + +[Sources] + ProcessorSubClass.c + ProcessorSubClassStrings.uni + +[Packages] + ArmPkg/ArmPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + ArmSmcLib + BaseLib + BaseMemoryLib + DebugLib + HiiLib + IoLib + MemoryAllocationLib + OemMiscLib + PcdLib + PrintLib + UefiDriverEntryPoint + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[Pcd] + gArmTokenSpaceGuid.PcdProcessorManufacturer + gArmTokenSpaceGuid.PcdProcessorVersion + gArmTokenSpaceGuid.PcdProcessorSerialNumber + gArmTokenSpaceGuid.PcdProcessorAssetTag + gArmTokenSpaceGuid.PcdProcessorPartNumber + +[Guids] + + +[Depex] + gEfiSmbiosProtocolGuid diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass= .c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c new file mode 100644 index 000000000000..85cbe2a67f37 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c @@ -0,0 +1,863 @@ +/** @file + ProcessorSubClass.c + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ Copyright (c) 2015, Hisilicon Limited. All rights reserved. + Copyright (c) 2015, Linaro Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern UINT8 ProcessorSubClassStrings[]; + +#define CACHE_SOCKETED_SHIFT 3 +#define CACHE_LOCATION_SHIFT 5 +#define CACHE_ENABLED_SHIFT 7 +#define CACHE_OPERATION_MODE_SHIFT 8 + +// Sets the HII variable `x` if `pcd` isn't empty +#define SET_HII_STRING_IF_PCD_NOT_EMPTY(pcd, x) \ + x##Str =3D (CHAR16 *)PcdGetPtr (pcd); \ + if (StrLen (x##Str) > 0) { \ + HiiSetString (mHiiHandle, x, x##Str, NULL); \ + } \ + +typedef enum { + CacheModeWriteThrough =3D 0, ///< Cache is write-through + CacheModeWriteBack, ///< Cache is write-back + CacheModeVariesWithAddress, ///< Cache mode varies by address + CacheModeUnknown, ///< Cache mode is unknown + CacheModeMax +} CACHE_OPERATION_MODE; + +typedef enum { + CacheLocationInternal =3D 0, ///< Cache is internal to the processor + CacheLocationExternal, ///< Cache is external to the processor + CacheLocationReserved, ///< Reserved + CacheLocationUnknown, ///< Cache location is unknown + CacheLocationMax +} CACHE_LOCATION; + +EFI_HII_HANDLE mHiiHandle; + +EFI_SMBIOS_PROTOCOL *mSmbios; + +SMBIOS_TABLE_TYPE4 mSmbiosProcessorTableTemplate =3D { + { // Hdr + EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // Type + sizeof (SMBIOS_TABLE_TYPE4), // Length + 0 // Handle + }, + 1, // Socket + CentralProcessor, // ProcessorType + ProcessorFamilyIndicatorFamily2, // ProcessorFamily + 2, // ProcessorManufacture + { // ProcessorId + { // Signature + 0 + }, + { // FeatureFlags + 0 + } + }, + 3, // ProcessorVersion + { // Voltage + 0 + }, + 0, // ExternalClock + 0, // MaxSpeed + 0, // CurrentSpeed + 0, // Status + ProcessorUpgradeUnknown, // ProcessorUpgrade + 0xFFFF, // L1CacheHandle + 0xFFFF, // L2CacheHandle + 0xFFFF, // L3CacheHandle + 4, // SerialNumber + 5, // AssetTag + 6, // PartNumber + 0, // CoreCount + 0, //EnabledCoreCount + 0, // ThreadCount + 0, // ProcessorCharacteristics + ProcessorFamilyARM, // ProcessorFamily2 + 0, // CoreCount2 + 0, // EnabledCoreCount2 + 0 // ThreadCount2 +}; + + +/** Fetches the specified processor's frequency in Hz. + + @param ProcessorNumber The processor number + + @return The clock frequency in MHz + +**/ +UINT16 +GetCpuFrequency ( + IN UINT8 ProcessorNumber + ) +{ + return (UINT16)(OemGetCpuFreq (ProcessorNumber) / 1000 / 1000); +} + +/** Gets a description of the specified cache. + + @param[in] CacheLevel Zero-based cache level (e.g. L1 c= ache is 0) + @param[in] InstructionOrUnifiedCache Whether this is an instruction or= unified + cache, or a data cache + @param[out] CacheSocketStr The description of the specified = cache + + @return The number of Unicode characters in CacheSocketStr not including= the + terminating NUL +**/ +UINTN +GetCacheSocketStr ( + IN UINT8 CacheLevel, + IN BOOLEAN InstructionOrUnifiedCache, + OUT CHAR16 *CacheSocketStr + ) +{ + UINTN CacheSocketStrLen; + + if (CacheLevel =3D=3D CpuCacheL1 + && InstructionOrUnifiedCache) { + CacheSocketStrLen =3D UnicodeSPrint ( + CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Instruction Cache", + CacheLevel + 1); + } else if (CacheLevel =3D=3D CpuCacheL1 && !InstructionOrUnifiedCache) { + CacheSocketStrLen =3D UnicodeSPrint (CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Data Cache", + CacheLevel + 1); + } else { + CacheSocketStrLen =3D UnicodeSPrint (CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Cache", + CacheLevel + 1); + } + + return CacheSocketStrLen; +} + +/** Fills in the Type 7 record with the cache architecture information + read from the CPU registers. + + @param[in] CacheLevel Cache level (e.g. L1) + @param[in] InstructionOrUnifiedCache Cache type is instruction or + unified, not data cache + @param[in] CcidxSupported Whether CCIDX is supported + @param[in] CacheType The type of cache supported at this cache = level + @param[out] Type7Record The Type 7 record to fill in + +**/ +VOID +SetCacheArchitectureInformation ( + IN UINT8 CacheLevel, + IN BOOLEAN InstructionOrUnifiedCache, + IN BOOLEAN CcidxSupported, + IN CLIDR_CACHE_TYPE CacheType, + OUT SMBIOS_TABLE_TYPE7 *Type7Record + ) +{ + CSSELR_DATA Csselr; + CCSIDR_DATA Ccsidr; +#if defined(MDE_CPU_ARM) + CSSIDR2_DATA Ccsidr2; +#endif + UINT8 Associativity; + UINT32 CacheSize32; + UINT16 CacheSize16; + UINT64 CacheSize64; + + Csselr.Data =3D 0; + Csselr.Bits.Level =3D CacheLevel; + + if (InstructionOrUnifiedCache) { + if (CacheType =3D=3D ClidrCacheTypeInstructionOnly || + CacheType =3D=3D ClidrCacheTypeSeparate) { + + Csselr.Bits.InD =3D CsselrCacheTypeInstruction; + Type7Record->SystemCacheType =3D CacheTypeInstruction; + } else { + Csselr.Bits.InD =3D CsselrCacheTypeDataOrUnified; + if (CacheType =3D=3D ClidrCacheTypeDataOnly) { + Type7Record->SystemCacheType =3D CacheTypeData; + } else { + Type7Record->SystemCacheType =3D CacheTypeUnified; + } + } + } else { + Type7Record->SystemCacheType =3D CacheTypeData; + Csselr.Bits.InD =3D CsselrCacheTypeDataOrUnified; + } + + // Read the CCSIDR register to get the cache architecture + Ccsidr.Data =3D ReadCCSIDR (Csselr.Data); + + if (CcidxSupported) { +#if defined(MDE_CPU_ARM) + Ccsidr2.Data =3D ReadCCSIDR2 (Csselr.Data); + CacheSize64 =3D (UINT64)(1 << (Ccsidr.BitsCcidxAA32.LineSize + 4)) * + (Ccsidr.BitsCcidxAA32.Associativity + 1) * + (Ccsidr2.Bits.NumSets + 1); + Associativity =3D Ccsidr.BitsCcidxAA32.Associativity; +#else + CacheSize64 =3D (UINT64)(1 << (Ccsidr.BitsCcidxAA64.LineSize + 4)) * + (Ccsidr.BitsCcidxAA64.Associativity + 1) * + (Ccsidr.BitsCcidxAA64.NumSets + 1); + Associativity =3D Ccsidr.BitsCcidxAA64.Associativity; +#endif + } else { + CacheSize64 =3D (1 << (Ccsidr.BitsNonCcidx.LineSize + 4)) * + (Ccsidr.BitsNonCcidx.Associativity + 1) * + (Ccsidr.BitsNonCcidx.NumSets + 1); + Associativity =3D Ccsidr.BitsNonCcidx.Associativity; + } + + CacheSize64 /=3D 1024; // Minimum granularity is 1K + + // Encode the cache size into the format SMBIOS wants + if (CacheSize64 < MAX_INT16) { + CacheSize16 =3D CacheSize64; + CacheSize32 =3D CacheSize16; + } else if ((CacheSize64 / 64) < MAX_INT16) { + CacheSize16 =3D (1 << 15) | (CacheSize64 / 64); + CacheSize32 =3D CacheSize16; + } else { + if ((CacheSize64 / 1024) <=3D 2047) { + CacheSize32 =3D CacheSize64; + } else { + CacheSize32 =3D (1 << 31) | (CacheSize64 / 64); + } + + CacheSize16 =3D -1; + } + + Type7Record->Associativity =3D Associativity + 1; + Type7Record->MaximumCacheSize =3D CacheSize16; + Type7Record->InstalledSize =3D CacheSize16; + Type7Record->MaximumCacheSize2 =3D CacheSize32; + Type7Record->InstalledSize2 =3D CacheSize32; + + switch (Associativity + 1) { + case 2: + Type7Record->Associativity =3D CacheAssociativity2Way; + break; + case 4: + Type7Record->Associativity =3D CacheAssociativity4Way; + break; + case 8: + Type7Record->Associativity =3D CacheAssociativity8Way; + break; + case 16: + Type7Record->Associativity =3D CacheAssociativity16Way; + break; + case 12: + Type7Record->Associativity =3D CacheAssociativity12Way; + break; + case 24: + Type7Record->Associativity =3D CacheAssociativity24Way; + break; + case 32: + Type7Record->Associativity =3D CacheAssociativity32Way; + break; + case 48: + Type7Record->Associativity =3D CacheAssociativity48Way; + break; + case 64: + Type7Record->Associativity =3D CacheAssociativity64Way; + break; + case 20: + Type7Record->Associativity =3D CacheAssociativity20Way; + break; + default: + Type7Record->Associativity =3D CacheAssociativityOther; + break; + } + + Type7Record->CacheConfiguration =3D (CacheModeUnknown << CACHE_OPERATION= _MODE_SHIFT) | + (1 << CACHE_ENABLED_SHIFT) | + (CacheLocationUnknown << CACHE_LOCATIO= N_SHIFT) | + (0 << CACHE_SOCKETED_SHIFT) | + CacheLevel; +} + + +/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure + + @param[in] CacheLevel The cache level (L1-L7) + @param[in] InstructionOrUnifiedCache The cache type is instruction or + unified, not a data cache. + + @return A pointer to the Type 7 structure. Returns NULL on failure. + +**/ +SMBIOS_TABLE_TYPE7 * +AllocateAndInitCacheInformation ( + IN UINT8 CacheLevel, + IN BOOLEAN InstructionOrUnifiedCache + ) +{ + SMBIOS_TABLE_TYPE7 *Type7Record; + EFI_STRING CacheSocketStr; + UINTN CacheSocketStrLen; + UINTN StringBufferSize; + CHAR8 *OptionalStrStart; + UINTN TableSize; + + // Allocate and fetch the cache description + StringBufferSize =3D sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH; + CacheSocketStr =3D AllocateZeroPool (StringBufferSize); + if (CacheSocketStr =3D=3D NULL) { + return NULL; + } + + CacheSocketStrLen =3D GetCacheSocketStr (CacheLevel, + InstructionOrUnifiedCache, + CacheSocketStr); + + TableSize =3D sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1; + Type7Record =3D AllocateZeroPool (TableSize); + if (Type7Record =3D=3D NULL) { + FreePool(CacheSocketStr); + return NULL; + } + + Type7Record->Hdr.Type =3D EFI_SMBIOS_TYPE_CACHE_INFORMATION; + Type7Record->Hdr.Length =3D sizeof (SMBIOS_TABLE_TYPE7); + Type7Record->Hdr.Handle =3D SMBIOS_HANDLE_PI_RESERVED; + + Type7Record->SocketDesignation =3D 1; + + Type7Record->SupportedSRAMType.Unknown =3D 1; + Type7Record->CurrentSRAMType.Unknown =3D 1; + Type7Record->CacheSpeed =3D 0; + Type7Record->ErrorCorrectionType =3D CacheErrorUnknown; + + OptionalStrStart =3D (CHAR8 *)(Type7Record + 1); + UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrL= en + 1); + FreePool (CacheSocketStr); + + return Type7Record; +} + + +/** + Add Type 7 SMBIOS Record for Cache Information. + + @param[in] ProcessorIndex Processor number of specified processo= r. + @param[out] L1CacheHandle Pointer to the handle of the L1 Cache = SMBIOS record. + @param[out] L2CacheHandle Pointer to the handle of the L2 Cache = SMBIOS record. + @param[out] L3CacheHandle Pointer to the handle of the L3 Cache = SMBIOS record. + +**/ +VOID +AddSmbiosCacheTypeTable ( + IN UINTN ProcessorIndex, + OUT EFI_SMBIOS_HANDLE *L1CacheHandle, + OUT EFI_SMBIOS_HANDLE *L2CacheHandle, + OUT EFI_SMBIOS_HANDLE *L3CacheHandle + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_TYPE7 *Type7Record; + EFI_SMBIOS_HANDLE SmbiosHandle; + UINT8 CacheLevel; + UINT8 CacheSubLevel; + CLIDR_DATA Clidr; + BOOLEAN CcidxSupported; + UINT8 MaxCacheLevel; + CLIDR_CACHE_TYPE CacheType; + + Status =3D EFI_SUCCESS; + + MaxCacheLevel =3D 0; + + // Read the CLIDR register to find out what caches are present. + Clidr.Data =3D ReadCLIDR (); + + // Get the cache type for the L1 cache. If it's 0, there are no caches. + if (CLIDR_GET_CACHE_TYPE (Clidr.Data, 0) =3D=3D ClidrCacheTypeNone) { + return; + } + + for (CacheLevel =3D 1; CacheLevel < MAX_ARM_CACHE_LEVEL; CacheLevel++) { + if (CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel) =3D=3D ClidrCacheTyp= eNone) { + MaxCacheLevel =3D CacheLevel; + break; + } + } + + CcidxSupported =3D ArmHasCcidx (); + + for (CacheLevel =3D 0; CacheLevel < MaxCacheLevel; CacheLevel++) { + Type7Record =3D NULL; + + CacheType =3D CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel); + + // At each level of cache, we can have a single type (unified, instruc= tion or data), + // or two types - separate data and instruction caches. If we have sep= arate + // instruction and data caches, then on the first iteration (CacheSubL= evel =3D 0) + // process the instruction cache. + for (CacheSubLevel =3D 0; CacheSubLevel <=3D 1; CacheSubLevel++) { + // If there's no separate data/instruction cache, skip the second it= eration + if (CacheSubLevel > 0 && CacheType !=3D ClidrCacheTypeSeparate) { + continue; + } + + Type7Record =3D AllocateAndInitCacheInformation (CacheLevel, + (CacheSubLevel =3D=3D= 0)); + if (Type7Record =3D=3D NULL) { + continue; + } + + SetCacheArchitectureInformation(CacheLevel, + (CacheSubLevel =3D=3D 0), + CcidxSupported, + CacheType, + Type7Record); + + // Allow the platform to fill in other information such as speed, SR= AM type etc. + if (!OemGetCacheInformation (ProcessorIndex, CacheLevel, + (CacheSubLevel =3D=3D 0), Type7Record)) { + continue; + } + + SmbiosHandle =3D SMBIOS_HANDLE_PI_RESERVED; + // Finally, install the table + Status =3D mSmbios->Add (mSmbios, NULL, &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)Type7Record); + if (EFI_ERROR (Status)) { + continue; + } + + // Config L1/L2/L3 Cache Handle + switch (CacheLevel) { + case CpuCacheL1: + *L1CacheHandle =3D SmbiosHandle; + break; + case CpuCacheL2: + *L2CacheHandle =3D SmbiosHandle; + break; + case CpuCacheL3: + *L3CacheHandle =3D SmbiosHandle; + break; + default: + break; + } + } + } +} + +/** Fills in the Type 4 CPU processor ID field. + + @param[out] Type4Record The SMBIOS Type 4 record to fill in + +**/ +VOID +SetProcessorIdField ( + OUT SMBIOS_TABLE_TYPE4 *Type4Record +) +{ + ARM_SMC_ARGS Args; + INT32 SmcCallStatus; + INT32 Jep106Code; + INT32 SocRevision; + BOOLEAN Arm64SocIdSupported; + UINT64 *ProcessorId; + PROCESSOR_CHARACTERISTIC_FLAGS *ProcessorCharacteristicFlags; + + Arm64SocIdSupported =3D FALSE; + + Args.Arg0 =3D SMCCC_VERSION; + ArmCallSmc (&Args); + SmcCallStatus =3D (INT32)Args.Arg0; + + if (SmcCallStatus < 0 || (SmcCallStatus >> 16) >=3D 1) { + Args.Arg0 =3D SMCCC_ARCH_FEATURES; + Args.Arg1 =3D SMCCC_ARCH_SOC_ID; + ArmCallSmc (&Args); + + if (Args.Arg0 >=3D 0) { + ProcessorCharacteristicFlags =3D + (PROCESSOR_CHARACTERISTIC_FLAGS*)&Type4Record->ProcessorCharacteri= stics; + Args.Arg0 =3D SMCCC_ARCH_SOC_ID; + Args.Arg1 =3D 0; + ArmCallSmc (&Args); + SmcCallStatus =3D (int)Args.Arg0; + + if (SmcCallStatus >=3D 0) { + Arm64SocIdSupported =3D TRUE; + ProcessorCharacteristicFlags->ProcessorArm64SocId =3D 1; + Jep106Code =3D (int)Args.Arg0; + } else { + ProcessorCharacteristicFlags->ProcessorArm64SocId =3D 0; + } + Args.Arg0 =3D SMCCC_ARCH_SOC_ID; + Args.Arg1 =3D 1; + ArmCallSmc (&Args); + SmcCallStatus =3D (int)Args.Arg0; + + if (SmcCallStatus >=3D 0) { + SocRevision =3D (int)Args.Arg0; + } + } + } + + ProcessorId =3D (UINT64 *)&Type4Record->ProcessorId; + + if (Arm64SocIdSupported) { + *ProcessorId =3D ((UINT64)Jep106Code << 32) | SocRevision; + } else { + *ProcessorId =3D ArmReadMidr (); + } +} + + +/** Allocates a Type 4 Processor Information structure and sets the + strings following the data fields. + + @param[out] Type4Record The Type 4 structure to allocate and initiali= ze + @param[in] ProcessorIndex The index of the processor socket + @param[in] Populated Whether the specified processor socket is + populated. + + @retval EFI_SUCCESS The Type 4 structure was successfully + allocated and the strings initialized. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory needed. +**/ +EFI_STATUS +AllocateType4AndSetProcessorInformationStrings ( + SMBIOS_TABLE_TYPE4 **Type4Record, + UINT8 ProcessorIndex, + BOOLEAN Populated + ) +{ + EFI_STATUS Status; + EFI_STRING_ID ProcessorManu; + EFI_STRING_ID ProcessorVersion; + EFI_STRING_ID SerialNumber; + EFI_STRING_ID AssetTag; + EFI_STRING_ID PartNumber; + EFI_STRING ProcessorSocketStr; + EFI_STRING ProcessorManuStr; + EFI_STRING ProcessorVersionStr; + EFI_STRING SerialNumberStr; + EFI_STRING AssetTagStr; + EFI_STRING PartNumberStr; + CHAR8 *OptionalStrStart; + CHAR8 *StrStart; + UINTN ProcessorSocketStrLen; + UINTN ProcessorManuStrLen; + UINTN ProcessorVersionStrLen; + UINTN SerialNumberStrLen; + UINTN AssetTagStrLen; + UINTN PartNumberStrLen; + UINTN TotalSize; + UINTN StringBufferSize; + + Status =3D EFI_SUCCESS; + + ProcessorManuStr =3D NULL; + ProcessorVersionStr =3D NULL; + SerialNumberStr =3D NULL; + AssetTagStr =3D NULL; + PartNumberStr =3D NULL; + + if (Populated) { + ProcessorManu =3D STRING_TOKEN (STR_PROCESSOR_MANUFACTURE); + ProcessorVersion =3D STRING_TOKEN (STR_PROCESSOR_VERSION); + SerialNumber =3D STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER); + AssetTag =3D STRING_TOKEN (STR_PROCESSOR_ASSET_TAG); + PartNumber =3D STRING_TOKEN (STR_PROCESSOR_PART_NUMBER); + + SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorManufacturer, ProcessorMan= u); + SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorVersion, ProcessorVersion); + SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorSerialNumber, SerialNumber= ); + SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorAssetTag, AssetTag); + SET_HII_STRING_IF_PCD_NOT_EMPTY(PcdProcessorPartNumber, PartNumber); + } else { + ProcessorManu =3D STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + ProcessorVersion =3D STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + SerialNumber =3D STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + AssetTag =3D STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + PartNumber =3D STRING_TOKEN (STR_PROCESSOR_UNKNOWN); + } + + // Processor Socket Designation + StringBufferSize =3D sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH; + ProcessorSocketStr =3D AllocateZeroPool (StringBufferSize); + if (ProcessorSocketStr =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ProcessorSocketStrLen =3D UnicodeSPrint (ProcessorSocketStr, StringBuffe= rSize, + L"CPU%02d", ProcessorIndex + 1); + + // Processor Manufacture + ProcessorManuStr =3D HiiGetPackageString (&gEfiCallerIdGuid, ProcessorMa= nu, NULL); + ProcessorManuStrLen =3D StrLen (ProcessorManuStr); + + // Processor Version + ProcessorVersionStr =3D HiiGetPackageString (&gEfiCallerIdGuid, Processo= rVersion, NULL); + ProcessorVersionStrLen =3D StrLen (ProcessorVersionStr); + + // Serial Number + SerialNumberStr =3D HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber= , NULL); + SerialNumberStrLen =3D StrLen (SerialNumberStr); + + // Asset Tag + AssetTagStr =3D HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL); + AssetTagStrLen =3D StrLen (AssetTagStr); + + // Part Number + PartNumberStr =3D HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NU= LL); + PartNumberStrLen =3D StrLen (PartNumberStr); + + TotalSize =3D sizeof (SMBIOS_TABLE_TYPE4) + + ProcessorSocketStrLen + 1 + + ProcessorManuStrLen + 1 + + ProcessorVersionStrLen + 1 + + SerialNumberStrLen + 1 + + AssetTagStrLen + 1 + + PartNumberStrLen + 1 + 1; + + *Type4Record =3D AllocateZeroPool (TotalSize); + if (*Type4Record =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Exit; + } + + CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TA= BLE_TYPE4)); + + OptionalStrStart =3D (CHAR8 *)(*Type4Record + 1); + UnicodeStrToAsciiStrS ( + ProcessorSocketStr, + OptionalStrStart, + ProcessorSocketStrLen + 1 + ); + + StrStart =3D OptionalStrStart + ProcessorSocketStrLen + 1; + UnicodeStrToAsciiStrS ( + ProcessorManuStr, + StrStart, + ProcessorManuStrLen + 1 + ); + + StrStart +=3D ProcessorManuStrLen + 1; + UnicodeStrToAsciiStrS ( + ProcessorVersionStr, + StrStart, + ProcessorVersionStrLen + 1 + ); + + StrStart +=3D ProcessorVersionStrLen + 1; + UnicodeStrToAsciiStrS ( + SerialNumberStr, + StrStart, + SerialNumberStrLen + 1 + ); + + StrStart +=3D SerialNumberStrLen + 1; + UnicodeStrToAsciiStrS ( + AssetTagStr, + StrStart, + AssetTagStrLen + 1 + ); + + StrStart +=3D AssetTagStrLen + 1; + UnicodeStrToAsciiStrS ( + PartNumberStr, + StrStart, + PartNumberStrLen + 1 + ); + +Exit: + FreePool (ProcessorSocketStr); + FreePool (ProcessorManuStr); + FreePool (ProcessorVersionStr); + FreePool (SerialNumberStr); + FreePool (AssetTagStr); + FreePool (PartNumberStr); + + return Status; +} + +/** + Add Type 4 SMBIOS Record for Processor Information. + + @param[in] ProcessorIndex Processor index of specified processor. + +**/ +EFI_STATUS +AddSmbiosProcessorTypeTable ( + IN UINTN ProcessorIndex + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_TYPE4 *Type4Record; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_HANDLE L1CacheHandle; + EFI_SMBIOS_HANDLE L2CacheHandle; + EFI_SMBIOS_HANDLE L3CacheHandle; + UINT8 *LegacyVoltage; + PROCESSOR_STATUS_DATA ProcessorStatus; + OEM_MISC_PROCESSOR_DATA MiscProcessorData; + BOOLEAN SocketPopulated; + UINTN MainIdRegister; + + Type4Record =3D NULL; + + MiscProcessorData.Voltage =3D 0; + MiscProcessorData.CurrentSpeed =3D 0; + MiscProcessorData.CoreCount =3D 0; + MiscProcessorData.CoresEnabled =3D 0; + MiscProcessorData.ThreadCount =3D 0; + MiscProcessorData.MaxSpeed =3D 0; + L1CacheHandle =3D 0xFFFF; + L2CacheHandle =3D 0xFFFF; + L3CacheHandle =3D 0xFFFF; + + SocketPopulated =3D OemIsSocketPresent(ProcessorIndex); + + Status =3D AllocateType4AndSetProcessorInformationStrings ( + &Type4Record, + ProcessorIndex, + SocketPopulated + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OemGetProcessorInformation (ProcessorIndex, + &ProcessorStatus, + (PROCESSOR_CHARACTERISTIC_FLAGS*) + &Type4Record->ProcessorCharacteristics, + &MiscProcessorData); + + if (SocketPopulated) { + AddSmbiosCacheTypeTable (ProcessorIndex, &L1CacheHandle, + &L2CacheHandle, &L3CacheHandle); + } + + LegacyVoltage =3D (UINT8*)&Type4Record->Voltage; + + *LegacyVoltage =3D MiscProcessorData.Voltage; + Type4Record->CurrentSpeed =3D MiscProcessorData.CurrentSpeed; + Type4Record->MaxSpeed =3D MiscProcessorData.MaxSpeed; + Type4Record->Status =3D ProcessorStatus.Data; + Type4Record->L1CacheHandle =3D L1CacheHandle; + Type4Record->L2CacheHandle =3D L2CacheHandle; + Type4Record->L3CacheHandle =3D L3CacheHandle; + Type4Record->CoreCount =3D MiscProcessorData.CoreCount; + Type4Record->CoreCount2 =3D MiscProcessorData.CoreCount; + Type4Record->EnabledCoreCount =3D MiscProcessorData.CoresEnabled; + Type4Record->EnabledCoreCount2 =3D MiscProcessorData.CoresEnabled; + Type4Record->ThreadCount =3D MiscProcessorData.ThreadCount; + Type4Record->ThreadCount2 =3D MiscProcessorData.ThreadCount; + + Type4Record->CurrentSpeed =3D GetCpuFrequency (ProcessorIndex); + Type4Record->ExternalClock =3D (UINT16)(ArmReadCntFrq () / 1000 /= 1000); + + SetProcessorIdField (Type4Record); + + MainIdRegister =3D ArmReadMidr (); + if (((MainIdRegister >> 16) & 0xF) < 8) { + Type4Record->ProcessorFamily2 =3D ProcessorFamilyARM; + } else { + if (sizeof (VOID*) =3D=3D 4) { + Type4Record->ProcessorFamily2 =3D ProcessorFamilyARMv7; + } else { + Type4Record->ProcessorFamily2 =3D ProcessorFamilyARMv8; + } + } + + SmbiosHandle =3D SMBIOS_HANDLE_PI_RESERVED; + Status =3D mSmbios->Add (mSmbios, NULL, &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *)Type4Record); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n= ", + __FUNCTION__, __LINE__, Status)); + } + FreePool (Type4Record); + + return Status; +} + +/** + Standard EFI driver point. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The data was successfully stored. + +**/ +EFI_STATUS +EFIAPI +ProcessorSubClassEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 SocketIndex; + + // + // Locate dependent protocols + // + Status =3D gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&= mSmbios); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status= )); + return Status; + } + + // + // Add our default strings to the HII database. They will be modified la= ter. + // + mHiiHandle =3D HiiAddPackages (&gEfiCallerIdGuid, + NULL, + ProcessorSubClassStrings, + NULL, + NULL + ); + if (mHiiHandle =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Add SMBIOS tables for populated sockets. + // + for (SocketIndex =3D 0; SocketIndex < OemGetProcessorMaxSockets(); Socke= tIndex++) { + Status =3D AddSmbiosProcessorTypeTable (SocketIndex); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Stat= us)); + return Status; + } + } + + return Status; +} diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass= Strings.uni b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClas= sStrings.uni new file mode 100644 index 000000000000..22b3c64d9fe2 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings= .uni @@ -0,0 +1,24 @@ +/** @file + SMBIOS Type 4 strings + + Copyright (c) 2021, NUVIA Inc. All rights reserved. + Copyright (c) 2015, Hisilicon Limited. All rights reserved. + Copyright (c) 2015, Linaro Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/=3D# + +#langdef en-US "English" + +// +// Processor Information +// +#string STR_PROCESSOR_SOCKET_DESIGNATION #language en-US "Not Specifie= d" +#string STR_PROCESSOR_MANUFACTURE #language en-US "Not Specifie= d" +#string STR_PROCESSOR_VERSION #language en-US "Not Specifie= d" +#string STR_PROCESSOR_SERIAL_NUMBER #language en-US "Not Specifie= d" +#string STR_PROCESSOR_ASSET_TAG #language en-US "Not Specifie= d" +#string STR_PROCESSOR_PART_NUMBER #language en-US "Not Specifie= d" +#string STR_PROCESSOR_UNKNOWN #language en-US "Unknown" --=20 2.26.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#70309): https://edk2.groups.io/g/devel/message/70309 Mute This Topic: https://groups.io/mt/79679256/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-