From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) by mx.groups.io with SMTP id smtpd.web09.26076.1612135544829282890 for ; Sun, 31 Jan 2021 15:25:45 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=mwnTpAyJ; spf=pass (domain: nuviainc.com, ip: 209.85.222.172, mailfrom: rebecca@nuviainc.com) Received: by mail-qk1-f172.google.com with SMTP id a7so14581588qkb.13 for ; Sun, 31 Jan 2021 15:25:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zqGHMlqceOInBGjLKKuYSWd363EErW6yUNSghCGlkj8=; b=mwnTpAyJwjtI4+dJAEhKnPzsFYEajq++zCdziHJpXJ+d9F9WNbcruZTxG0gX/oER26 ed/2nY2ib6Bbam3nq7ogmUvOmrK2ce+1bEY5Y1ig4vqHO6m+0Ra7WWLdQymeWuH3Sxa4 1yTIbhl9scbXgLdtguKD5vGBOHIM11EtwoP0Slx3ViBNNNvKcsRk+VBLIQw01forN90y /3OOaRLvU5unkkfVfqgnAOMXwGlgRcDPUBxJ1qaV4S5ZN4k7ZKoe/VpNeSSImU1aa//6 GVhOLtf4/YR3d+BoH54kHKvNmNmdqCKuve7NLOFNBsc5AWNq+pq53Wl3kN91Z+4aHN3b wLAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zqGHMlqceOInBGjLKKuYSWd363EErW6yUNSghCGlkj8=; b=WVH5wz6jG64526Fd6/kEv/u0Vk7up2wqTZVO+U2aK28/2kq0oGA0mjUCyjT+w+a1In McXDXBjqz9gTf9rQ4xMZHvmJy2nTTwLc8FxI38/6l7eQgVliD2O8zzJi92TuIUf+cu+p fLKyg9uzkh5rKQhXzv8Zk3h65opUG+uWPYx0bu/jAtQaGALZi4H8GcpOcUWxQVOfmuKm 8lTuya9VxQvjp7Xd6mao7bneJ5GJpb9C11/hn7izXuvk9/nlCv/klg72ct4kLj8XnSey 8X3Lbyaqoz/F+DfYOsIGK46vH7Nf3z61EKfqeXumzKq7iH0KYOM1eHpnpYBPsKAP0ykU ESeg== X-Gm-Message-State: AOAM5316H9XmQFvZXlQu5GtgQVPF8JfTXnN3wu/fXnnp7RYYbfSFikZA 3oUjyZWl5kpYLvkSweMLaTD6AaC20Agncv2mjnPFb0xA01daOSS+mH9JSe5dHKWqJE4NWbxTRyi D7qZORMtXMN4vFz3sQbbeWloet+lymMbfALlhs6QwEC2nztDu/9TSOwWHMMi6oAXFJB3JdQ== X-Google-Smtp-Source: ABdhPJwVxxGF6gwzfB7bSfU5zJpigSxNq9fjQT43VjcAgRDRasv92k02tn1kTAgicbNPcGEXqjO6Pw== X-Received: by 2002:a05:620a:c0e:: with SMTP id l14mr13300380qki.296.1612135542989; Sun, 31 Jan 2021 15:25:42 -0800 (PST) Return-Path: 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 12sm11809361qkg.39.2021.01.31.15.25.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 31 Jan 2021 15:25:42 -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: [PATCH v7 13/21] ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe Date: Sun, 31 Jan 2021 16:25:03 -0700 Message-Id: <20210131232511.18340-14-rebecca@nuviainc.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210131232511.18340-1-rebecca@nuviainc.com> References: <20210131232511.18340-1-rebecca@nuviainc.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 | 65 ++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h | 106 +++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c | 766 ++++++++++++++++++++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c | 97 +++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c | 103 +++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c | 250 +++++++ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni | 24 + 8 files changed, 1413 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 + 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/ProcessorSubClassDxe.inf b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf new file mode 100644 index 000000000000..d74e365375b3 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf @@ -0,0 +1,65 @@ +#/** @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 = 1.29 + BASE_NAME = ProcessorSubClass + FILE_GUID = f3fe0e33-ea38-4069-9fb5-be23407207c7 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ProcessorSubClassEntryPoint + +[Sources] + SmbiosProcessorArmCommon.c + ProcessorSubClass.c + ProcessorSubClassStrings.uni + +[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..002fd6cc142b --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h @@ -0,0 +1,106 @@ +/** @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 caches. + + @param CacheLevel The cache level (L1, L2 etc.). Zero based. + + @return TRUE if the cache level has separate I/D caches, FALSE otherwise. +**/ +BOOLEAN +SmbiosProcessorHasSeparateCaches ( + UINT8 CacheLevel + ); + +/** Gets the size of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). Zero based. + @param InstructionCache Whether the cache is a dedicated instruction cache. + @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 InstructionCache, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ); + +/** Gets the associativity of the specified cache. + + @param CacheLevel The cache level (L1, L2 etc.). Zero based. + @param InstructionCache Whether the cache is a dedicated instruction cache. + @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 InstructionCache, + 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..ca55bc019f96 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c @@ -0,0 +1,766 @@ +/** @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 = 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 = 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 = { + { // 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 fetch. + @param StringId The string identifier to set. +**/ +#define SET_HII_STRING_IF_PCD_NOT_EMPTY(Pcd, StringId) \ + do { \ + CHAR16 *Str; \ + Str = (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] InstructionCache Cache is an instruction cache. + @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 InstructionCache, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache, + OUT CHAR16 *CacheSocketStr + ) +{ + UINTN CacheSocketStrLen; + + if (CacheLevel == CpuCacheL1 && InstructionCache) { + CacheSocketStrLen = UnicodeSPrint ( + CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Instruction Cache", + CacheLevel + 1); + } else if (CacheLevel == CpuCacheL1 && DataCache) { + CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, + SMBIOS_STRING_MAX_LENGTH - 1, + L"L%x Data Cache", + CacheLevel + 1); + } else { + CacheSocketStrLen = 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, L2). + @param[in] InstructionCache Cache is an instruction cache. + @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 InstructionCache, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache, + OUT SMBIOS_TABLE_TYPE7 *Type7Record + ) +{ + UINT8 Associativity; + UINT32 CacheSize32; + UINT16 CacheSize16; + UINT64 CacheSize64; + + ASSERT (InstructionCache || DataCache || UnifiedCache); + + if (InstructionCache) { + Type7Record->SystemCacheType = CacheTypeInstruction; + } else if (DataCache) { + Type7Record->SystemCacheType = CacheTypeData; + } else if (UnifiedCache) { + Type7Record->SystemCacheType = CacheTypeUnified; + } else { + ASSERT(FALSE); + } + + CacheSize64 = SmbiosProcessorGetCacheSize (CacheLevel, + InstructionCache, + DataCache, + UnifiedCache + ); + + Associativity = SmbiosProcessorGetCacheAssociativity (CacheLevel, + InstructionCache, + DataCache, + UnifiedCache + ); + + CacheSize64 /= 1024; // Minimum granularity is 1K + + // Encode the cache size into the format SMBIOS wants + if (CacheSize64 < MAX_INT16) { + CacheSize16 = CacheSize64; + CacheSize32 = CacheSize16; + } else if ((CacheSize64 / 64) < MAX_INT16) { + CacheSize16 = (1 << 15) | (CacheSize64 / 64); + CacheSize32 = CacheSize16; + } else { + if ((CacheSize64 / 1024) <= 2047) { + CacheSize32 = CacheSize64; + } else { + CacheSize32 = (1 << 31) | (CacheSize64 / 64); + } + + CacheSize16 = -1; + } + + Type7Record->Associativity = Associativity + 1; + Type7Record->MaximumCacheSize = CacheSize16; + Type7Record->InstalledSize = CacheSize16; + Type7Record->MaximumCacheSize2 = CacheSize32; + Type7Record->InstalledSize2 = CacheSize32; + + switch (Associativity + 1) { + case 2: + Type7Record->Associativity = CacheAssociativity2Way; + break; + case 4: + Type7Record->Associativity = CacheAssociativity4Way; + break; + case 8: + Type7Record->Associativity = CacheAssociativity8Way; + break; + case 16: + Type7Record->Associativity = CacheAssociativity16Way; + break; + case 12: + Type7Record->Associativity = CacheAssociativity12Way; + break; + case 24: + Type7Record->Associativity = CacheAssociativity24Way; + break; + case 32: + Type7Record->Associativity = CacheAssociativity32Way; + break; + case 48: + Type7Record->Associativity = CacheAssociativity48Way; + break; + case 64: + Type7Record->Associativity = CacheAssociativity64Way; + break; + case 20: + Type7Record->Associativity = CacheAssociativity20Way; + break; + default: + Type7Record->Associativity = CacheAssociativityOther; + break; + } + + Type7Record->CacheConfiguration = (CacheModeUnknown << CACHE_OPERATION_MODE_SHIFT) | + (1 << CACHE_ENABLED_SHIFT) | + (CacheLocationUnknown << CACHE_LOCATION_SHIFT) | + (0 << CACHE_SOCKETED_SHIFT) | + CacheLevel; +} + + +/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure. + + @param[in] CacheLevel The cache level (L1-L7). + @param[in] InstructionCache Cache is an instruction cache. + @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 InstructionCache, + 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 = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH; + CacheSocketStr = AllocateZeroPool (StringBufferSize); + if (CacheSocketStr == NULL) { + return NULL; + } + + CacheSocketStrLen = GetCacheSocketStr (CacheLevel, + InstructionCache, + DataCache, + UnifiedCache, + CacheSocketStr); + + TableSize = sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1; + Type7Record = AllocateZeroPool (TableSize); + if (Type7Record == NULL) { + FreePool(CacheSocketStr); + return NULL; + } + + Type7Record->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION; + Type7Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE7); + Type7Record->Hdr.Handle = SMBIOS_HANDLE_PI_RESERVED; + + Type7Record->SocketDesignation = 1; + + Type7Record->SupportedSRAMType.Unknown = 1; + Type7Record->CurrentSRAMType.Unknown = 1; + Type7Record->CacheSpeed = 0; + Type7Record->ErrorCorrectionType = CacheErrorUnknown; + + OptionalStrStart = (CHAR8 *)(Type7Record + 1); + UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrLen + 1); + FreePool (CacheSocketStr); + + return Type7Record; +} + +/** + Add Type 7 SMBIOS Record for Cache Information. + + @param[in] ProcessorIndex Processor number of specified processor. + @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 = EFI_SUCCESS; + + MaxCacheLevel = 0; + + // See if there's an L1 cache present. + MaxCacheLevel = SmbiosProcessorGetMaxCacheLevel (); + + if (MaxCacheLevel < 1) { + return; + } + + for (CacheLevel = 0; CacheLevel < MaxCacheLevel; CacheLevel++) { + Type7Record = NULL; + + SeparateCaches = SmbiosProcessorHasSeparateCaches (CacheLevel); + + // At each level of cache, we can have a single type (unified, instruction or data), + // or two types - separate data and instruction caches. If we have separate + // instruction and data caches, then on the first iteration (CacheSubLevel = 0) + // process the instruction cache. + for (DataCacheType = 0; DataCacheType <= 1; DataCacheType++) { + // If there's no separate data/instruction cache, skip the second iteration + if (DataCacheType > 0 && !SeparateCaches) { + continue; + } + + Type7Record = AllocateAndInitCacheInformation (CacheLevel, + DataCacheType == 0 && SeparateCaches, + DataCacheType == 1, + DataCacheType == 0 && !SeparateCaches + ); + if (Type7Record == NULL) { + continue; + } + + ConfigureCacheArchitectureInformation(CacheLevel, + (DataCacheType == 0) && SeparateCaches, + DataCacheType == 1, + (DataCacheType == 0) && !SeparateCaches, + Type7Record + ); + + // Allow the platform to fill in other information such as speed, SRAM type etc. + if (!OemGetCacheInformation (ProcessorIndex, CacheLevel, + DataCacheType == 0, Type7Record)) { + continue; + } + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + // Finally, install the table + Status = 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 = SmbiosHandle; + break; + case CpuCacheL2: + *L2CacheHandle = SmbiosHandle; + break; + case CpuCacheL3: + *L3CacheHandle = 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 initialize + @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 = EFI_SUCCESS; + + ProcessorManuStr = NULL; + ProcessorVersionStr = NULL; + SerialNumberStr = NULL; + AssetTagStr = NULL; + PartNumberStr = NULL; + + ProcessorManu = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE); + ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_VERSION); + SerialNumber = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER); + AssetTag = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG); + PartNumber = 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 = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH; + ProcessorSocketStr = AllocateZeroPool (StringBufferSize); + if (ProcessorSocketStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ProcessorSocketStrLen = UnicodeSPrint (ProcessorSocketStr, StringBufferSize, + L"CPU%02d", ProcessorIndex + 1); + + // Processor Manufacture + ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL); + ProcessorManuStrLen = StrLen (ProcessorManuStr); + + // Processor Version + ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL); + ProcessorVersionStrLen = StrLen (ProcessorVersionStr); + + // Serial Number + SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL); + SerialNumberStrLen = StrLen (SerialNumberStr); + + // Asset Tag + AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL); + AssetTagStrLen = StrLen (AssetTagStr); + + // Part Number + PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL); + PartNumberStrLen = StrLen (PartNumberStr); + + TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + + ProcessorSocketStrLen + 1 + + ProcessorManuStrLen + 1 + + ProcessorVersionStrLen + 1 + + SerialNumberStrLen + 1 + + AssetTagStrLen + 1 + + PartNumberStrLen + 1 + 1; + + *Type4Record = AllocateZeroPool (TotalSize); + if (*Type4Record == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4)); + + OptionalStrStart = (CHAR8 *)(*Type4Record + 1); + UnicodeStrToAsciiStrS ( + ProcessorSocketStr, + OptionalStrStart, + ProcessorSocketStrLen + 1 + ); + + StrStart = OptionalStrStart + ProcessorSocketStrLen + 1; + UnicodeStrToAsciiStrS ( + ProcessorManuStr, + StrStart, + ProcessorManuStrLen + 1 + ); + + StrStart += ProcessorManuStrLen + 1; + UnicodeStrToAsciiStrS ( + ProcessorVersionStr, + StrStart, + ProcessorVersionStrLen + 1 + ); + + StrStart += ProcessorVersionStrLen + 1; + UnicodeStrToAsciiStrS ( + SerialNumberStr, + StrStart, + SerialNumberStrLen + 1 + ); + + StrStart += SerialNumberStrLen + 1; + UnicodeStrToAsciiStrS ( + AssetTagStr, + StrStart, + AssetTagStrLen + 1 + ); + + StrStart += 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 = NULL; + + MiscProcessorData.Voltage = 0; + MiscProcessorData.CurrentSpeed = 0; + MiscProcessorData.CoreCount = 0; + MiscProcessorData.CoresEnabled = 0; + MiscProcessorData.ThreadCount = 0; + MiscProcessorData.MaxSpeed = 0; + L1CacheHandle = 0xFFFF; + L2CacheHandle = 0xFFFF; + L3CacheHandle = 0xFFFF; + + SocketPopulated = OemIsSocketPresent(ProcessorIndex); + + Status = 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 = (UINT8*)&Type4Record->Voltage; + + *LegacyVoltage = MiscProcessorData.Voltage; + Type4Record->CurrentSpeed = MiscProcessorData.CurrentSpeed; + Type4Record->MaxSpeed = MiscProcessorData.MaxSpeed; + Type4Record->Status = ProcessorStatus.Data; + Type4Record->L1CacheHandle = L1CacheHandle; + Type4Record->L2CacheHandle = L2CacheHandle; + Type4Record->L3CacheHandle = L3CacheHandle; + Type4Record->CoreCount = MiscProcessorData.CoreCount; + Type4Record->CoreCount2 = MiscProcessorData.CoreCount; + Type4Record->EnabledCoreCount = MiscProcessorData.CoresEnabled; + Type4Record->EnabledCoreCount2 = MiscProcessorData.CoresEnabled; + Type4Record->ThreadCount = MiscProcessorData.ThreadCount; + Type4Record->ThreadCount2 = MiscProcessorData.ThreadCount; + + Type4Record->CurrentSpeed = GetCpuFrequency (ProcessorIndex); + Type4Record->ExternalClock = + (UINT16)(SmbiosGetExternalClockFrequency () / 1000 / 1000); + + ProcessorId = (UINT64*)&Type4Record->ProcessorId; + *ProcessorId = SmbiosGetProcessorId (); + + ProcessorCharacteristics = SmbiosGetProcessorCharacteristics (); + Type4Record->ProcessorCharacteristics |= *((UINT64*)&ProcessorCharacteristics); + + Type4Record->ProcessorFamily = SmbiosGetProcessorFamily (); + Type4Record->ProcessorFamily2 = SmbiosGetProcessorFamily2 (); + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = 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 = 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 later. + // + mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, + NULL, + ProcessorSubClassStrings, + NULL, + NULL + ); + if (mHiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Add SMBIOS tables for populated sockets. + // + for (SocketIndex = 0; SocketIndex < OemGetProcessorMaxSockets(); SocketIndex++) { + Status = AddSmbiosProcessorTypeTable (SocketIndex); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Status)); + return Status; + } + } + + return Status; +} diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c new file mode 100644 index 000000000000..96f739b2abea --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c @@ -0,0 +1,97 @@ +/** @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.). Zero based. + @param InstructionCache Whether the cache is a dedicated instruction cache. + @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 InstructionCache, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache +) +{ + CCSIDR_DATA Ccsidr; + CSSELR_DATA Csselr; + BOOLEAN CcidxSupported; + UINT64 CacheSize; + + Csselr.Data = 0; + Csselr.Bits.Level = CacheLevel; + Csselr.Bits.InD = InstructionCache; + + Ccsidr.Data = ReadCCSIDR (Csselr.Data); + + CcidxSupported = ArmHasCcidx (); + + if (CcidxSupported) { + CacheSize = (UINT64)(1 << (Ccsidr.BitsCcidxAA64.LineSize + 4)) * + (Ccsidr.BitsCcidxAA64.Associativity + 1) * + (Ccsidr.BitsCcidxAA64.NumSets + 1); + } else { + CacheSize = (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.). Zero based. + @param InstructionCache Whether the cache is a dedicated instruction cache. + @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 InstructionCache, + IN BOOLEAN DataCache, + IN BOOLEAN UnifiedCache + ) +{ + CCSIDR_DATA Ccsidr; + CSSELR_DATA Csselr; + BOOLEAN CcidxSupported; + UINT32 Associativity; + + Csselr.Data = 0; + Csselr.Bits.Level = CacheLevel; + Csselr.Bits.InD = (InstructionCache | UnifiedCache); + + Ccsidr.Data = ReadCCSIDR (Csselr.Data); + + CcidxSupported = ArmHasCcidx (); + + if (CcidxSupported) { + Associativity = Ccsidr.BitsCcidxAA64.Associativity; + } else { + Associativity = Ccsidr.BitsNonCcidx.Associativity; + } + + return Associativity; +} + diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c new file mode 100644 index 000000000000..5222b71f9f68 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c @@ -0,0 +1,103 @@ +/** @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.). Zero based. + @param InstructionCache Whether the cache is a dedicated instruction cache. + @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 InstructionCache, + 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 = 0; + Csselr.Bits.Level = CacheLevel; + Csselr.Bits.InD = (InstructionCache | UnifiedCache); + + Ccsidr.Data = ReadCCSIDR (Csselr.Data); + + CcidxSupported = ArmHasCcidx (); + + if (CcidxSupported) { + Ccsidr2.Data = ReadCCSIDR2 (Csselr.Data); + CacheSize = (UINT64)(1 << (Ccsidr.BitsCcidxAA32.LineSize + 4)) * + (Ccsidr.BitsCcidxAA32.Associativity + 1) * + (Ccsidr2.Bits.NumSets + 1); + } else { + CacheSize = (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.). Zero based. + @param InstructionCache Whether the cache is a dedicated instruction cache. + @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 InstructionCache, + 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 = 0; + Csselr.Bits.Level = CacheLevel; + Csselr.Bits.InD = (InstructionCache | UnifiedCache); + + Ccsidr.Data = ReadCCSIDR (Csselr.Data); + + CcidxSupported = ArmHasCcidx (); + + if (CcidxSupported) { + Ccsidr2.Data = ReadCCSIDR2 (Csselr.Data); + Associativity = Ccsidr.BitsCcidxAA32.Associativity; + } else { + Associativity = Ccsidr.BitsNonCcidx.Associativity; + } + + return Associativity; +} + diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c new file mode 100644 index 000000000000..ed6583c19383 --- /dev/null +++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c @@ -0,0 +1,250 @@ +/** @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 = 0; + + // Read the CLIDR register to find out what caches are present. + Clidr.Data = 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) == ClidrCacheTypeNone) { + return 0; + } + + for (CacheLevel = 1; CacheLevel < MAX_ARM_CACHE_LEVEL; CacheLevel++) { + if (CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel) == ClidrCacheTypeNone) { + MaxCacheLevel = CacheLevel; + break; + } + } + + return MaxCacheLevel; +} + +/** Returns whether or not the specified cache level has separate I/D caches. + + @param CacheLevel The cache level (L1, L2 etc.). Zero based. + + @return TRUE if the cache level has separate I/D caches, FALSE otherwise. +**/ +BOOLEAN +SmbiosProcessorHasSeparateCaches ( + UINT8 CacheLevel + ) +{ + CLIDR_CACHE_TYPE CacheType; + CLIDR_DATA Clidr; + BOOLEAN SeparateCaches; + + SeparateCaches = FALSE; + + Clidr.Data = ReadCLIDR (); + + CacheType = CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel); + + if (CacheType == ClidrCacheTypeSeparate) + { + SeparateCaches = 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 = FALSE; + + Args.Arg0 = SMCCC_VERSION; + ArmCallSmc (&Args); + SmcCallStatus = (INT32)Args.Arg0; + + if (SmcCallStatus < 0 || (SmcCallStatus >> 16) >= 1) { + Args.Arg0 = SMCCC_ARCH_FEATURES; + Args.Arg1 = SMCCC_ARCH_SOC_ID; + ArmCallSmc (&Args); + + if (Args.Arg0 >= 0) { + Arm64SocIdSupported = 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 = EFI_SUCCESS; + + Args.Arg0 = SMCCC_ARCH_SOC_ID; + Args.Arg1 = 0; + ArmCallSmc (&Args); + SmcCallStatus = (INT32)Args.Arg0; + + if (SmcCallStatus >= 0) { + *Jep106Code = (INT32)Args.Arg0; + } else { + Status = EFI_UNSUPPORTED; + } + + Args.Arg0 = SMCCC_ARCH_SOC_ID; + Args.Arg1 = 1; + ArmCallSmc (&Args); + SmcCallStatus = (INT32)Args.Arg0; + + if (SmcCallStatus >= 0) { + *SocRevision = (INT32)Args.Arg0; + } else { + Status = 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 = ((UINT64)Jep106Code << 32) | SocRevision; + } else { + ProcessorId = 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 = ArmReadMidr (); + + if (((MainIdRegister >> 16) & 0xF) < 8) { + ProcessorFamily2 = ProcessorFamilyARM; + } else { + if (sizeof (VOID*) == 4) { + ProcessorFamily2 = ProcessorFamilyARMv7; + } else { + ProcessorFamily2 = 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 = HasSmcArm64SocId (); + + return Characteristics; +} diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.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 + +**/ + +/=# + +#langdef en-US "English" + +// +// Processor Information +// +#string STR_PROCESSOR_SOCKET_DESIGNATION #language en-US "Not Specified" +#string STR_PROCESSOR_MANUFACTURE #language en-US "Not Specified" +#string STR_PROCESSOR_VERSION #language en-US "Not Specified" +#string STR_PROCESSOR_SERIAL_NUMBER #language en-US "Not Specified" +#string STR_PROCESSOR_ASSET_TAG #language en-US "Not Specified" +#string STR_PROCESSOR_PART_NUMBER #language en-US "Not Specified" +#string STR_PROCESSOR_UNKNOWN #language en-US "Unknown" -- 2.26.2