Files
system76-edk2/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c
Minh Nguyen 11b5093ce4 ArmPkg: Correct return value of "SMCCC_ARCH_SOC_ID" Function ID call
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>
2022-09-23 14:39:10 +00:00

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;
}