From nobody Tue Feb 10 09:01:50 2026 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+71415+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+71415+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1612745611; cv=none; d=zohomail.com; s=zohoarc; b=O8c/EH9REdDVSS0sHtzF6TZuX3bCE03w8kRcFat0mbnXvE3OJpKuWYqg6sa8V8LGUus6VESsxIRD1DDNvtA8yNbJjK58ib1lsHoYzY/JIOa0Q6JSXn293c/AxFNuL/FzGWpPZ5P4OxzWrsTjnVZ8/ixsHCHBjkukgb3eHRmGQHg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1612745611; 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=BM43DYT4iFUTbdTV85zqNJmCIt+Z2KHVD0L/ECG7k5o=; b=bhTde/At0Q4o6DJpZkqOMw0zEc/sotccs6QNqik6xzqBI8KU54+AMZIYJxH56FhbSOL7tA2gV3SZ0/ru+zB1PJxMVzjva9mG+8oS8GQ904FRhFjx8dTQaIaX5Ka32v6xNAJ8QESfXGBLXH1SWq8zFgjdcWiHS3IkTsFR8Zmcl7Q= 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+71415+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1612745611099767.1613182215756; Sun, 7 Feb 2021 16:53:31 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id cDYMYY1788612xmb1MnjB2Hq; Sun, 07 Feb 2021 16:53:30 -0800 X-Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) by mx.groups.io with SMTP id smtpd.web11.29137.1612745610164017595 for ; Sun, 07 Feb 2021 16:53:30 -0800 X-Received: by mail-pj1-f47.google.com with SMTP id q72so7290021pjq.2 for ; Sun, 07 Feb 2021 16:53:30 -0800 (PST) X-Gm-Message-State: XfPHXD2IrOeTWOQO2vBkVWPYx1787277AA= X-Google-Smtp-Source: ABdhPJzFWAhA9IwzWYAq59RehdTqei0edPqn4RkH4ppW0840rPqwxycj3Ap56Jdob9EJPbvls/uDUw== X-Received: by 2002:a17:90a:9414:: with SMTP id r20mr14588208pjo.158.1612745608688; Sun, 07 Feb 2021 16:53:28 -0800 (PST) X-Received: from cube.int.bluestop.org (c-174-52-16-57.hsd1.ut.comcast.net. [174.52.16.57]) by smtp.gmail.com with ESMTPSA id c6sm11095883pjd.21.2021.02.07.16.53.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 16:53:27 -0800 (PST) From: "Rebecca Cran" To: devel@edk2.groups.io Cc: Rebecca Cran , leif@nuviainc.com, Ard Biesheuvel , nd@arm.com, Sami Mujawar , Liming Gao , Michael D Kinney , Zhiguang Liu , Samer El-Haj-Mahmoud , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [edk2-devel] [PATCH v8 13/21] ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe Date: Sun, 7 Feb 2021 17:52:46 -0700 Message-Id: <20210208005254.12176-14-rebecca@nuviainc.com> In-Reply-To: <20210208005254.12176-1-rebecca@nuviainc.com> References: <20210208005254.12176-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=1612745610; bh=Fo2ZrxoxLbI1bUyCOIF1P2TCWqYFPn6LGW3Ye0JrASg=; h=Cc:Date:From:Reply-To:Subject:To; b=YXM+Dwxcj4n0523jwQwJ0g0VrNpdzL6Vx53f1V1CVSDSfpO2pjBbQPnef6D4Ky3vb/M Mje67G6sk6sbndrF2UBTDDAVrxs3RHWaD4ADsR7UyNUOPOeQ/3Jzzwzv9EvQC/E9CQBX0 VhenMNRC5JiadZGq/QNJoo9z+Qlnl0BxWzU= 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 = | 66 ++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h = | 102 +++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c = | 752 ++++++++++++++++++++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c = | 93 +++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c = | 99 +++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c = | 249 +++++++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni = | 24 + 8 files changed, 1387 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..c7cacece6f06 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf @@ -0,0 +1,66 @@ +#/** @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] + SmbiosProcessorArmCommon.c + ProcessorSubClass.c + ProcessorSubClassStrings.uni + SmbiosProcessor.h + +[Sources.AARCH64] + SmbiosProcessorAArch64.c + +[Sources.ARM] + SmbiosProcessorArm.c + +[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/SmbiosProcessor.h= b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h new file mode 100644 index 000000000000..f64d5cd1a170 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h @@ -0,0 +1,102 @@ +/** @file + SMBIOS Processor Related Functions. + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMBIOS_PROCESSOR_H_ +#define SMBIOS_PROCESSOR_H_ + +#include +#include + +/** Returns the maximum cache level implemented by the current CPU. + + @return The maximum cache level implemented. +**/ +UINT8 +SmbiosProcessorGetMaxCacheLevel ( + VOID + ); + +/** Returns whether or not the specified cache level has separate I/D cach= es. + + @param CacheLevel The cache level (L1, L2 etc.). + + @return TRUE if the cache level has separate I/D caches, FALSE otherwi= se. +**/ +BOOLEAN +SmbiosProcessorHasSeparateCaches ( + UINT8 CacheLevel + ); + +/** Gets the size of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). + @param DataCache Whether the cache is a dedicated data cache. + @param UnifiedCache Whether the cache is a unified cache. + + @return The cache size. +**/ +UINT64 +SmbiosProcessorGetCacheSize ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ); + +/** Gets the associativity of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). + @param DataCache Whether the cache is a dedicated data cache. + @param UnifiedCache Whether the cache is a unified cache. + + @return The cache associativity. +**/ +UINT32 +SmbiosProcessorGetCacheAssociativity ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ); + +/** Returns a value for the Processor ID field that conforms to SMBIOS + requirements. + + @return Processor ID. +**/ +UINT64 +SmbiosGetProcessorId (VOID); + +/** Returns the external clock frequency. + + @return The external CPU clock frequency. +**/ +UINTN +SmbiosGetExternalClockFrequency (VOID); + +/** Returns the SMBIOS ProcessorFamily field value. + + @return The value for the ProcessorFamily field. +**/ +UINT8 +SmbiosGetProcessorFamily (VOID); + +/** Returns the ProcessorFamily2 field value. + + @return The value for the ProcessorFamily2 field. +**/ +UINT16 +SmbiosGetProcessorFamily2 (VOID); + +/** Returns the SMBIOS Processor Characteristics. + + @return Processor Characteristics bitfield. +**/ +PROCESSOR_CHARACTERISTIC_FLAGS +SmbiosGetProcessorCharacteristics (VOID); + +#endif // SMBIOS_PROCESSOR_H_ diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass= .c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c new file mode 100644 index 000000000000..d03de12a820e --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c @@ -0,0 +1,752 @@ +/** @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 + +#include "SmbiosProcessor.h" + +extern UINT8 ProcessorSubClassStrings[]; + +#define CACHE_SOCKETED_SHIFT 3 +#define CACHE_LOCATION_SHIFT 5 +#define CACHE_ENABLED_SHIFT 7 +#define CACHE_OPERATION_MODE_SHIFT 8 + +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 +}; + +/** Sets the HII variable `StringId` is `Pcd` isn't empty. + + @param Pcd The FixedAtBuild PCD that contains the string to fetc= h. + @param StringId The string identifier to set. +**/ +#define SET_HII_STRING_IF_PCD_NOT_EMPTY(Pcd, StringId) \ + do { \ + CHAR16 *Str; \ + Str =3D (CHAR16*)PcdGetPtr (Pcd); \ + if (StrLen (Str) > 0) { \ + HiiSetString (mHiiHandle, StringId, Str, NULL); \ + } \ + } while (0) + +/** 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 cache is 0). + @param[in] DataCache Cache is a data cache. + @param[in] UnifiedCache Cache is a unified 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 DataCache, + IN BOOLEAN UnifiedCache, + OUT CHAR16 *CacheSocketStr + ) +{ + UINTN CacheSocketStrLen; + + if (CacheLevel =3D=3D CpuCacheL1 && !DataCache && !UnifiedCache) { + CacheSocketStrLen =3D UnicodeSPrint ( + CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Instruction Cache", + CacheLevel); + } else if (CacheLevel =3D=3D CpuCacheL1 && DataCache) { + CacheSocketStrLen =3D UnicodeSPrint (CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Data Cache", + CacheLevel); + } else { + CacheSocketStrLen =3D UnicodeSPrint (CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Cache", + CacheLevel); + } + + 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, L2). + @param[in] DataCache Cache is a data cache. + @param[in] UnifiedCache Cache is a unified cache. + @param[out] Type7Record The Type 7 record to fill in. + +**/ +VOID +ConfigureCacheArchitectureInformation ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache, + OUT SMBIOS_TABLE_TYPE7 *Type7Record + ) +{ + UINT8 Associativity; + UINT32 CacheSize32; + UINT16 CacheSize16; + UINT64 CacheSize64; + + if (!DataCache && !UnifiedCache) { + Type7Record->SystemCacheType =3D CacheTypeInstruction; + } else if (DataCache) { + Type7Record->SystemCacheType =3D CacheTypeData; + } else if (UnifiedCache) { + Type7Record->SystemCacheType =3D CacheTypeUnified; + } else { + ASSERT(FALSE); + } + + CacheSize64 =3D SmbiosProcessorGetCacheSize (CacheLevel, + DataCache, + UnifiedCache + ); + + Associativity =3D SmbiosProcessorGetCacheAssociativity (CacheLevel, + DataCache, + UnifiedCache + ); + + 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->MaximumCacheSize =3D CacheSize16; + Type7Record->InstalledSize =3D CacheSize16; + Type7Record->MaximumCacheSize2 =3D CacheSize32; + Type7Record->InstalledSize2 =3D CacheSize32; + + switch (Associativity) { + case 2: + Type7Record->Associativity =3D CacheAssociativity2Way; + break; + case 4: + Type7Record->Associativity =3D CacheAssociativity4Way; + break; + case 8: + Type7Record->Associativity =3D CacheAssociativity8Way; + break; + case 12: + Type7Record->Associativity =3D CacheAssociativity12Way; + break; + case 16: + Type7Record->Associativity =3D CacheAssociativity16Way; + break; + case 20: + Type7Record->Associativity =3D CacheAssociativity20Way; + 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; + 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 - 1); +} + + +/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure. + + @param[in] CacheLevel The cache level (L1-L7). + @param[in] DataCache Cache is a data cache. + @param[in] UnifiedCache Cache is a unified cache. + + @return A pointer to the Type 7 structure. Returns NULL on failure. +**/ +SMBIOS_TABLE_TYPE7 * +AllocateAndInitCacheInformation ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ) +{ + 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, + DataCache, + UnifiedCache, + 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 MaxCacheLevel; + BOOLEAN DataCacheType; + BOOLEAN SeparateCaches; + + Status =3D EFI_SUCCESS; + + MaxCacheLevel =3D 0; + + // See if there's an L1 cache present. + MaxCacheLevel =3D SmbiosProcessorGetMaxCacheLevel (); + + if (MaxCacheLevel < 1) { + return; + } + + for (CacheLevel =3D 1; CacheLevel <=3D MaxCacheLevel; CacheLevel++) { + Type7Record =3D NULL; + + SeparateCaches =3D SmbiosProcessorHasSeparateCaches (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 (DataCacheType =3D 0; DataCacheType <=3D 1; DataCacheType++) { + // If there's no separate data/instruction cache, skip the second it= eration + if (DataCacheType =3D=3D 1 && !SeparateCaches) { + continue; + } + + Type7Record =3D AllocateAndInitCacheInformation (CacheLevel, + DataCacheType, + !SeparateCaches + ); + if (Type7Record =3D=3D NULL) { + continue; + } + + ConfigureCacheArchitectureInformation(CacheLevel, + DataCacheType, + !SeparateCaches, + Type7Record + ); + + // Allow the platform to fill in other information such as speed, SR= AM type etc. + if (!OemGetCacheInformation (ProcessorIndex, CacheLevel, + DataCacheType, !SeparateCaches, Type7Re= cord)) { + 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; + } + } + } +} + +/** 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; + + 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, ProcessorManu= ); + 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); + + // 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; + UINT64 *ProcessorId; + PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics; + OEM_MISC_PROCESSOR_DATA MiscProcessorData; + BOOLEAN SocketPopulated; + + 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)(SmbiosGetExternalClockFrequency () / 1000 / 1000); + + ProcessorId =3D (UINT64*)&Type4Record->ProcessorId; + *ProcessorId =3D SmbiosGetProcessorId (); + + ProcessorCharacteristics =3D SmbiosGetProcessorCharacteristics (); + Type4Record->ProcessorCharacteristics |=3D *((UINT64*)&ProcessorCharacte= ristics); + + Type4Record->ProcessorFamily =3D SmbiosGetProcessorFamily (); + Type4Record->ProcessorFamily2 =3D SmbiosGetProcessorFamily2 (); + + 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/SmbiosProcessorAA= rch64.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch= 64.c new file mode 100644 index 000000000000..ddd774b16f83 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c @@ -0,0 +1,93 @@ +/** @file + Functions for AARCH64 processor information + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include "SmbiosProcessor.h" + +/** Gets the size of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). + @param DataCache Whether the cache is a dedicated data cache. + @param UnifiedCache Whether the cache is a unified cache. + + @return The cache size. +**/ +UINT64 +SmbiosProcessorGetCacheSize ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache +) +{ + CCSIDR_DATA Ccsidr; + CSSELR_DATA Csselr; + BOOLEAN CcidxSupported; + UINT64 CacheSize; + + Csselr.Data =3D 0; + Csselr.Bits.Level =3D CacheLevel - 1; + Csselr.Bits.InD =3D (!DataCache && !UnifiedCache); + + Ccsidr.Data =3D ReadCCSIDR (Csselr.Data); + + CcidxSupported =3D ArmHasCcidx (); + + if (CcidxSupported) { + CacheSize =3D (1 << (Ccsidr.BitsCcidxAA64.LineSize + 4)) * + (Ccsidr.BitsCcidxAA64.Associativity + 1) * + (Ccsidr.BitsCcidxAA64.NumSets + 1); + } else { + CacheSize =3D (1 << (Ccsidr.BitsNonCcidx.LineSize + 4)) * + (Ccsidr.BitsNonCcidx.Associativity + 1) * + (Ccsidr.BitsNonCcidx.NumSets + 1); + } + + return CacheSize; +} + +/** Gets the associativity of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). + @param DataCache Whether the cache is a dedicated data cache. + @param UnifiedCache Whether the cache is a unified cache. + + @return The cache associativity. +**/ +UINT32 +SmbiosProcessorGetCacheAssociativity ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ) +{ + CCSIDR_DATA Ccsidr; + CSSELR_DATA Csselr; + BOOLEAN CcidxSupported; + UINT32 Associativity; + + Csselr.Data =3D 0; + Csselr.Bits.Level =3D CacheLevel - 1; + Csselr.Bits.InD =3D (!DataCache && !UnifiedCache); + + Ccsidr.Data =3D ReadCCSIDR (Csselr.Data); + + CcidxSupported =3D ArmHasCcidx (); + + if (CcidxSupported) { + Associativity =3D Ccsidr.BitsCcidxAA64.Associativity + 1; + } else { + Associativity =3D Ccsidr.BitsNonCcidx.Associativity + 1; + } + + return Associativity; +} + diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAr= m.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c new file mode 100644 index 000000000000..0be4403c765f --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c @@ -0,0 +1,99 @@ +/** @file + Functions for ARM processor information + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include "SmbiosProcessor.h" + +/** Gets the size of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). + @param DataCache Whether the cache is a dedicated data cache. + @param UnifiedCache Whether the cache is a unified cache. + + @return The cache size. +**/ +UINT64 +ArmGetCacheSize ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ) +{ + CCSIDR_DATA Ccsidr; + CCSIDR2_DATA Ccsidr2; + CSSELR_DATA Csselr; + BOOLEAN CcidxSupported; + UINT64 CacheSize; + + // Read the CCSIDR register to get the cache architecture + Csselr.Data =3D 0; + Csselr.Bits.Level =3D CacheLevel - 1; + Csselr.Bits.InD =3D (!DataCache && !UnifiedCache); + + Ccsidr.Data =3D ReadCCSIDR (Csselr.Data); + + CcidxSupported =3D ArmHasCcidx (); + + if (CcidxSupported) { + Ccsidr2.Data =3D ReadCCSIDR2 (Csselr.Data); + CacheSize =3D (1 << (Ccsidr.BitsCcidxAA32.LineSize + 4)) * + (Ccsidr.BitsCcidxAA32.Associativity + 1) * + (Ccsidr2.Bits.NumSets + 1); + } else { + CacheSize =3D (1 << (Ccsidr.BitsNonCcidx.LineSize + 4)) * + (Ccsidr.BitsNonCcidx.Associativity + 1) * + (Ccsidr.BitsNonCcidx.NumSets + 1); + } + + return CacheSize; +} + +/** Gets the associativity of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). + @param DataCache Whether the cache is a dedicated data cache. + @param UnifiedCache Whether the cache is a unified cache. + + @return The cache associativity. +**/ +UINT32 +ArmGetCacheAssociativity ( + IN UINT8 CacheLevel, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ) +{ + CCSIDR_DATA Ccsidr; + CCSIDR2_DATA Ccsidr2; + CSSELR_DATA Csselr; + BOOLEAN CcidxSupported; + UINT32 Associativity; + + // Read the CCSIDR register to get the cache architecture + Csselr.Data =3D 0; + Csselr.Bits.Level =3D CacheLevel - 1; + Csselr.Bits.InD =3D (!DataCache && !UnifiedCache); + + Ccsidr.Data =3D ReadCCSIDR (Csselr.Data); + + CcidxSupported =3D ArmHasCcidx (); + + if (CcidxSupported) { + Ccsidr2.Data =3D ReadCCSIDR2 (Csselr.Data); + Associativity =3D Ccsidr.BitsCcidxAA32.Associativity + 1; + } else { + Associativity =3D Ccsidr.BitsNonCcidx.Associativity + 1; + } + + return Associativity; +} + diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAr= mCommon.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm= Common.c new file mode 100644 index 000000000000..bccb21cfbb41 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon= .c @@ -0,0 +1,249 @@ +/** @file + Functions for processor information common to ARM and AARCH64. + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "SmbiosProcessor.h" + +/** Returns the maximum cache level implemented by the current CPU. + + @return The maximum cache level implemented. +**/ +UINT8 +SmbiosProcessorGetMaxCacheLevel ( + VOID + ) +{ + CLIDR_DATA Clidr; + UINT8 CacheLevel; + UINT8 MaxCacheLevel; + + 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, 1) =3D=3D ClidrCacheTypeNone) { + return 0; + } + + for (CacheLevel =3D 1; CacheLevel <=3D MAX_ARM_CACHE_LEVEL; CacheLevel++= ) { + if (CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel) =3D=3D ClidrCacheTyp= eNone) { + MaxCacheLevel =3D CacheLevel; + break; + } + } + + return MaxCacheLevel; +} + +/** Returns whether or not the specified cache level has separate I/D cach= es. + + @param CacheLevel The cache level (L1, L2 etc.). + + @return TRUE if the cache level has separate I/D caches, FALSE otherwi= se. +**/ +BOOLEAN +SmbiosProcessorHasSeparateCaches ( + UINT8 CacheLevel + ) +{ + CLIDR_CACHE_TYPE CacheType; + CLIDR_DATA Clidr; + BOOLEAN SeparateCaches; + + SeparateCaches =3D FALSE; + + Clidr.Data =3D ReadCLIDR (); + + CacheType =3D CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel - 1); + + if (CacheType =3D=3D ClidrCacheTypeSeparate) { + SeparateCaches =3D TRUE; + } + + return SeparateCaches; +} + +/** Checks if ther ARM64 SoC ID SMC call is supported + + @return Whether the ARM64 SoC ID call is supported. +**/ +BOOLEAN +HasSmcArm64SocId ( + VOID + ) +{ + ARM_SMC_ARGS Args; + INT32 SmcCallStatus; + BOOLEAN Arm64SocIdSupported; + + 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) { + Arm64SocIdSupported =3D TRUE; + } + } + + return Arm64SocIdSupported; +} + +/** Fetches the JEP106 code and SoC Revision. + + @param Jep106Code JEP 106 code. + @param SocRevision SoC revision. + + @retval EFI_SUCCESS Succeeded. + @retval EFI_UNSUPPORTED Failed. +**/ +EFI_STATUS +SmbiosGetSmcArm64SocId ( + OUT INT32 *Jep106Code, + OUT INT32 *SocRevision + ) +{ + ARM_SMC_ARGS Args; + INT32 SmcCallStatus; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + Args.Arg0 =3D SMCCC_ARCH_SOC_ID; + Args.Arg1 =3D 0; + ArmCallSmc (&Args); + SmcCallStatus =3D (INT32)Args.Arg0; + + if (SmcCallStatus >=3D 0) { + *Jep106Code =3D (INT32)Args.Arg0; + } else { + Status =3D EFI_UNSUPPORTED; + } + + Args.Arg0 =3D SMCCC_ARCH_SOC_ID; + Args.Arg1 =3D 1; + ArmCallSmc (&Args); + SmcCallStatus =3D (INT32)Args.Arg0; + + if (SmcCallStatus >=3D 0) { + *SocRevision =3D (INT32)Args.Arg0; + } else { + Status =3D EFI_UNSUPPORTED; + } + + return Status; +} + +/** Returns a value for the Processor ID field that conforms to SMBIOS + requirements. + + @return Processor ID. +**/ +UINT64 +SmbiosGetProcessorId ( + VOID + ) +{ + INT32 Jep106Code; + INT32 SocRevision; + UINT64 ProcessorId; + + if (HasSmcArm64SocId ()) { + SmbiosGetSmcArm64SocId (&Jep106Code, &SocRevision); + ProcessorId =3D ((UINT64)Jep106Code << 32) | SocRevision; + } else { + ProcessorId =3D ArmReadMidr (); + } + + return ProcessorId; +} + +/** Returns the external clock frequency. + + @return The external clock frequency. +**/ +UINTN +SmbiosGetExternalClockFrequency ( + VOID + ) +{ + return ArmReadCntFrq (); +} + +/** Returns the SMBIOS ProcessorFamily field value. + + @return The value for the ProcessorFamily field. +**/ +UINT8 +SmbiosGetProcessorFamily ( + VOID + ) +{ + return ProcessorFamilyIndicatorFamily2; +} + +/** Returns the ProcessorFamily2 field value. + + @return The value for the ProcessorFamily2 field. +**/ +UINT16 +SmbiosGetProcessorFamily2 ( + VOID + ) +{ + UINTN MainIdRegister; + UINT16 ProcessorFamily2; + + MainIdRegister =3D ArmReadMidr (); + + if (((MainIdRegister >> 16) & 0xF) < 8) { + ProcessorFamily2 =3D ProcessorFamilyARM; + } else { + if (sizeof (VOID*) =3D=3D 4) { + ProcessorFamily2 =3D ProcessorFamilyARMv7; + } else { + ProcessorFamily2 =3D ProcessorFamilyARMv8; + } + } + + return ProcessorFamily2; +} + +/** Returns the SMBIOS Processor Characteristics. + + @return Processor Characteristics bitfield. +**/ +PROCESSOR_CHARACTERISTIC_FLAGS +SmbiosGetProcessorCharacteristics ( + VOID + ) +{ + PROCESSOR_CHARACTERISTIC_FLAGS Characteristics; + + ZeroMem (&Characteristics, sizeof (Characteristics)); + + Characteristics.ProcessorArm64SocId =3D HasSmcArm64SocId (); + + return Characteristics; +} 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 (#71415): https://edk2.groups.io/g/devel/message/71415 Mute This Topic: https://groups.io/mt/80467482/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-