According to "SMC Calling Convention" specification, section 7.4, return value of Arm Architecture Calls is stored at first argument of SMC aguments (ARM_SMC_ARGS). This value can be negative values indicating error or positive values (including zero) indicating success. Positive value would contain information of respective Function ID (Section 7.3.4 and 7.4.4). For that reason, "SMCCC_VERSION" and "SMCCC_ARCH_FEATURES" Function ID calls read return value from "SmcCallStatus" variable (Args.Arg0 - first argument of SMC call). But "SMCCC_ARCH_SOC_ID" Function ID call is reading return value from "SmcParam" variable (Args.Arg1 - second argument of SMC call) so it leads to unexpected results of "Jep106Code" and "SocRevision". This patch is to correct it. Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com> Reviewed-by: Rebecca Cran <rebecca@quicinc.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Acked-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
243 lines
5.2 KiB
C
243 lines
5.2 KiB
C
/** @file
|
|
Functions for processor information common to ARM and AARCH64.
|
|
|
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
|
Copyright (c) 2021 - 2022, Ampere Computing LLC. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
#include <IndustryStandard/ArmCache.h>
|
|
#include <IndustryStandard/ArmStdSmc.h>
|
|
#include <IndustryStandard/SmBios.h>
|
|
#include <Library/ArmLib.h>
|
|
#include <Library/ArmSmcLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
|
|
#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, 1) == 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.).
|
|
|
|
@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 - 1);
|
|
|
|
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
|
|
)
|
|
{
|
|
INT32 SmcCallStatus;
|
|
BOOLEAN Arm64SocIdSupported;
|
|
UINTN SmcParam;
|
|
|
|
Arm64SocIdSupported = FALSE;
|
|
|
|
SmcCallStatus = ArmCallSmc0 (SMCCC_VERSION, NULL, NULL, NULL);
|
|
|
|
if ((SmcCallStatus < 0) || ((SmcCallStatus >> 16) >= 1)) {
|
|
SmcParam = SMCCC_ARCH_SOC_ID;
|
|
SmcCallStatus = ArmCallSmc1 (SMCCC_ARCH_FEATURES, &SmcParam, NULL, NULL);
|
|
if (SmcCallStatus >= 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
|
|
)
|
|
{
|
|
INT32 SmcCallStatus;
|
|
EFI_STATUS Status;
|
|
UINTN SmcParam;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
SmcParam = 0;
|
|
SmcCallStatus = ArmCallSmc1 (SMCCC_ARCH_SOC_ID, &SmcParam, NULL, NULL);
|
|
|
|
if (SmcCallStatus >= 0) {
|
|
*Jep106Code = SmcCallStatus;
|
|
} else {
|
|
Status = EFI_UNSUPPORTED;
|
|
}
|
|
|
|
SmcParam = 1;
|
|
SmcCallStatus = ArmCallSmc1 (SMCCC_ARCH_SOC_ID, &SmcParam, NULL, NULL);
|
|
|
|
if (SmcCallStatus >= 0) {
|
|
*SocRevision = SmcCallStatus;
|
|
} 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)SocRevision << 32) | Jep106Code;
|
|
} 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;
|
|
}
|