From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) by mx.groups.io with SMTP id smtpd.web08.10702.1612365529215708358 for ; Wed, 03 Feb 2021 07:18:49 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=2K6TGDT9; spf=pass (domain: nuviainc.com, ip: 209.85.128.52, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f52.google.com with SMTP id f16so5899693wmq.5 for ; Wed, 03 Feb 2021 07:18:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=Rrjruv3zf824wv8mtURqJCDWmnrdZbb7hYdMtWm6qno=; b=2K6TGDT9KJDTPENp71t6CyGnK4yCy2WiGV2dYJeMxiiCbSKeRY6xGWBQv6yW0KOUL7 v4S1z37pKrZX9m1MTHMvk52AvZsUki/t+TkPFJ512NNbjNnpxa8GV3L3bHu4hawhN6xv pef4VTcUOA1DiyrFhn9xILSgaU75IAqUzDnWiiVFnvKejLf8oZ4IfxyiondG+ZVOvcAh QAR+Ini6hvbvGJbdqlrgznH1TlKSLvUqQae4EX0kKLiKjNm/8fma3dpoH1SrWJl80LxK iAFLNMXWTpfN7g24+/zG0xJGsZ/hHjq4thRa1U/iHrkene+sDI9GKGUCnh8QIkBw4wdo tzbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=Rrjruv3zf824wv8mtURqJCDWmnrdZbb7hYdMtWm6qno=; b=F4XVrkkY28jiXkyjp9yS2TQTolYElaBA0ySEL60ExiDbV/7WIGOVp51yw/J1gK8etB VsCl8MCwL0HCXWAkZDIqNo4JwwWUBDnLx291/5VPbV1CU15afl60jHdISHLnptsEMGmW 3iEYc1RRcKNqnU2DkkLfpJ5v8nAAAEGsuv7bzs6QIR2h4mdgwmCmiu0qQCOWElYecMhr 6VBJnSBXz/j2mtFmFpymZuDQ4B/wFqB59+Z68HCmrJwJ7wKt3AS969NW75rKz0mFv5Ao HLGgV3/whrfGhz+cwyviM0CK0aHIJ6rUkgK/1r5LxMoo7QK6uTMQA35E+ldEz5bhbJ+T U7kw== X-Gm-Message-State: AOAM53281G+pI+c9fQs+wnN+rBUUZT0oaFHgfzoY+Efney1emYprX3oW pCmwVp+GtCW+c9cRvjB7Ryo0kA== X-Google-Smtp-Source: ABdhPJyte0cbMlh5aMmVoNT/lJYVUnQeonOawJMS+cdDOD7GC+HRBfIT99hYbq3YsffIceuCdJ2Oaw== X-Received: by 2002:a05:600c:2f81:: with SMTP id t1mr3309491wmn.186.1612365526834; Wed, 03 Feb 2021 07:18:46 -0800 (PST) Return-Path: Received: from vanye (cpc1-cmbg19-2-0-cust915.5-4.cable.virginm.net. [82.27.183.148]) by smtp.gmail.com with ESMTPSA id i7sm12863450wmq.2.2021.02.03.07.18.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Feb 2021 07:18:46 -0800 (PST) Date: Wed, 3 Feb 2021 15:18:44 +0000 From: "Leif Lindholm" To: Rebecca Cran Cc: devel@edk2.groups.io, Ard Biesheuvel , nd@arm.com, Sami Mujawar , Liming Gao , Michael D Kinney , Zhiguang Liu , Samer El-Haj-Mahmoud , Philippe =?iso-8859-1?Q?Mathieu-Daud=E9?= Subject: Re: [PATCH v7 13/21] ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe Message-ID: <20210203151844.GX1664@vanye> References: <20210131232511.18340-1-rebecca@nuviainc.com> <20210131232511.18340-14-rebecca@nuviainc.com> MIME-Version: 1.0 In-Reply-To: <20210131232511.18340-14-rebecca@nuviainc.com> User-Agent: Mutt/1.10.1 (2018-07-13) Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I'm afraid I have another few comments on this - but they're pretty straightforward. If you can address those and then send out a v8 of just this patch, this set is ready to merge. On Sun, Jan 31, 2021 at 16:25:03 -0700, Rebecca Cran wrote: > 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. Could we make all of these not zero-based? Since we've detached the architectural requirements from the API, it would help remove several +1 operations from point of use (at the cost of, I think, one -1 operation). > + > + @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) { Similarly, could Associativity become 1-based, to get rid of a bunch of +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; Can we sort these according to the visible number rather than what the enum happens to translate to? > + 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 > + ); This is a bit too clever for my poor brain. Could we pass DataCacheType and SeparateCaches and do the logic conversion in the function? It feels like this is still somewhat encoding ARM architectural behaviour in the API? SMBIOS defines typedef enum { CacheTypeOther = 0x01, CacheTypeUnknown = 0x02, CacheTypeInstruction = 0x03, CacheTypeData = 0x04, CacheTypeUnified = 0x05 } CACHE_TYPE_DATA; OK, let's worry about that aspect later, but please, move the logic into the functions. > + if (Type7Record == NULL) { > + continue; > + } > + > + ConfigureCacheArchitectureInformation(CacheLevel, > + (DataCacheType == 0) && SeparateCaches, > + DataCacheType == 1, > + (DataCacheType == 0) && !SeparateCaches, > + Type7Record > + ); Same again. > + > + // Allow the platform to fill in other information such as speed, SRAM type etc. > + if (!OemGetCacheInformation (ProcessorIndex, CacheLevel, > + DataCacheType == 0, Type7Record)) { And again. > + 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; So I would suggest adding +1 here > + } else { > + Associativity = Ccsidr.BitsNonCcidx.Associativity; and here. > + } > + > + 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; ...and here. > + } else { > + Associativity = Ccsidr.BitsNonCcidx.Associativity; and here. > + } > + > + 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) > + { Bracket on end of line before. / Leif > + 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 >