From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.26932.1683292669050400795 for ; Fri, 05 May 2023 06:17:49 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: pierre.gondois@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0ABF31480; Fri, 5 May 2023 06:18:33 -0700 (PDT) Received: from e126645.arm.com (e126645.nice.arm.com [10.34.100.110]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6FBE53F64C; Fri, 5 May 2023 06:17:47 -0700 (PDT) From: "PierreGondois" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Leif Lindholm , Sami Mujawar , Michael D Kinney , Liming Gao , Zhiguang Liu Subject: [PATCH v1 10/11] DynamicTablesPkg: Add ArmScmiInfoLib Date: Fri, 5 May 2023 15:17:20 +0200 Message-Id: <20230505131721.1310590-11-pierre.gondois@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230505131721.1310590-1-pierre.gondois@arm.com> References: <20230505131721.1310590-1-pierre.gondois@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Pierre Gondois The SCP holds some power information that could be advertised through the _CPC object. The communication with the SCP is done through SCMI protocols (c.f. ArmScmiDxe). Use the SCMI protocols to query information and feed it to the DynamicTablesPkg. Signed-off-by: Pierre Gondois --- DynamicTablesPkg/DynamicTables.dsc.inc | 1 + DynamicTablesPkg/DynamicTablesPkg.dec | 3 + DynamicTablesPkg/DynamicTablesPkg.dsc | 1 + .../Include/Library/ArmScmiInfoLib.h | 33 ++ .../Library/ArmScmiInfoLib/ArmScmiInfoLib.c | 294 ++++++++++++++++++ .../Library/ArmScmiInfoLib/ArmScmiInfoLib.inf | 31 ++ 6 files changed, 363 insertions(+) create mode 100644 DynamicTablesPkg/Include/Library/ArmScmiInfoLib.h create mode 100644 DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLi= b.c create mode 100644 DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLi= b.inf diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dy= namicTables.dsc.inc index 9d4312c4e87d..be40ebc4b472 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -15,6 +15,7 @@ [BuildOptions] [LibraryClasses.common] AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelper= Lib.inf AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + ArmScmiInfoLib|DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.= inf SsdtPcieSupportLib|DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/= SsdtPcieSupportLib.inf SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortF= ixupLib/SsdtSerialPortFixupLib.inf TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHel= perLib.inf diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/Dyn= amicTablesPkg.dec index cfbcbb9569f1..26498e5fec53 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -42,6 +42,9 @@ [LibraryClasses] ## @libraryclass Defines a set of SMBIOS string helper methods. SmbiosStringTableLib|Include/Library/SmbiosStringTableLib.h =20 + ## @libraryclass Defines a set of APIs to populate CmObj using SCMI. + ArmScmiInfoLib|Include/Library/ArmScmiInfoLib.h + [Protocols] # Configuration Manager Protocol GUID gEdkiiConfigurationManagerProtocolGuid =3D { 0xd85a4835, 0x5a82, 0x489= 4, { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } } diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/Dyn= amicTablesPkg.dsc index bd5084a9008f..6ea86c9efdb0 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -39,6 +39,7 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64] PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf =20 [Components.common] + DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.= inf diff --git a/DynamicTablesPkg/Include/Library/ArmScmiInfoLib.h b/DynamicT= ablesPkg/Include/Library/ArmScmiInfoLib.h new file mode 100644 index 000000000000..8d3fb31df13c --- /dev/null +++ b/DynamicTablesPkg/Include/Library/ArmScmiInfoLib.h @@ -0,0 +1,33 @@ +/** @file + Arm SCMI Info Library. + + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef ARM_SCMI_INFO_LIB_H_ +#define ARM_SCMI_INFO_LIB_H_ + +#include + +/** Populate a AML_CPC_INFO object based on SCMI information. + + @param[in] DomainId Identifier for the performance domain. + @param[out] CpcInfo If success, this structure was populated from + information queried to the SCP. + + @retval EFI_SUCCESS Success. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_TIMEOUT Time out. + @retval EFI_UNSUPPORTED Unsupported. +**/ +EFI_STATUS +EFIAPI +ArmScmiInfoGetFastChannel ( + IN UINT32 DomainId, + OUT AML_CPC_INFO *CpcInfo + ); + +#endif // ARM_SCMI_INFO_LIB_H_ diff --git a/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c b/D= ynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c new file mode 100644 index 000000000000..c23bff63bb6f --- /dev/null +++ b/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.c @@ -0,0 +1,294 @@ +/** @file + Arm SCMI Info Library. + + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.
+ + Arm Functional Fixed Hardware Specification: + - https://developer.arm.com/documentation/den0048/latest/ + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + +/** Arm FFH registers + + Cf. Arm Functional Fixed Hardware Specification + s3.2 Performance management and Collaborative Processor Performance Co= ntrol +*/ +#define ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER 0x0 +#define ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER 0x1 + +/// Arm SCMI performance protocol. +STATIC SCMI_PERFORMANCE_PROTOCOL *ScmiPerfProtocol; + +/** Arm SCMI Info Library constructor. + + @param ImageHandle Image of the loaded driver. + @param SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS Success. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Not Found + @retval EFI_TIMEOUT Timeout. + @retval EFI_UNSUPPORTED Unsupported. +**/ +EFI_STATUS +EFIAPI +ArmScmiInfoLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 Version; + + Status =3D gBS->LocateProtocol ( + &gArmScmiPerformanceProtocolGuid, + NULL, + (VOID **)&ScmiPerfProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D ScmiPerfProtocol->GetVersion (ScmiPerfProtocol, &Version); + if (EFI_ERROR (Status)) { + return Status; + } + + // FastChannels were added in SCMI v2.0 spec. + if (Version < PERFORMANCE_PROTOCOL_VERSION_V2) { + DEBUG ((DEBUG_ERROR, "ArmScmiInfoLib requires SCMI version > 2.0\n")= ); + return EFI_UNSUPPORTED; + } + + return Status; +} + +/** Get the OPPs/performance states of a power domain. + + This function is a wrapper around the SCMI PERFORMANCE_DESCRIBE_LEVELS + command. The list of discrete performance states is returned in a buff= er + that must be freed by the caller. + + @param[in] DomainId Identifier for the performance domain. + @param[out] LevelArray If success, pointer to the list of list of + performance state. This memory must be fre= ed by + the caller. + @param[out] LevelArrayCount If success, contains the number of states = in + LevelArray. + + @retval EFI_SUCCESS Success. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_TIMEOUT Time out. + @retval EFI_UNSUPPORTED Unsupported. +**/ +STATIC +EFI_STATUS +EFIAPI +ArmScmiInfoDescribeLevels ( + IN UINT32 DomainId, + OUT SCMI_PERFORMANCE_LEVEL **LevelArray, + OUT UINT32 *LevelArrayCount + ) +{ + EFI_STATUS Status; + SCMI_PERFORMANCE_LEVEL *Array; + UINT32 Count; + UINT32 Size; + + if ((ScmiPerfProtocol =3D=3D NULL) || + (LevelArray =3D=3D NULL) || + (LevelArrayCount =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + // First call to get the number of levels. + Size =3D 0; + Status =3D ScmiPerfProtocol->DescribeLevels ( + ScmiPerfProtocol, + DomainId, + &Count, + &Size, + NULL + ); + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + // EFI_SUCCESS is not a valid option. + if (Status =3D=3D EFI_SUCCESS) { + return EFI_INVALID_PARAMETER; + } else { + return Status; + } + } + + Array =3D AllocateZeroPool (Size); + if (Array =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Second call to get the descriptions of the levels. + Status =3D ScmiPerfProtocol->DescribeLevels ( + ScmiPerfProtocol, + DomainId, + &Count, + &Size, + Array + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *LevelArray =3D Array; + *LevelArrayCount =3D Count; + + return Status; +} + +/** Populate a AML_CPC_INFO object based on SCMI information. + + @param[in] DomainId Identifier for the performance domain. + @param[out] CpcInfo If success, this structure was populated from + information queried to the SCP. + + @retval EFI_SUCCESS Success. + @retval EFI_DEVICE_ERROR Device error. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_TIMEOUT Time out. + @retval EFI_UNSUPPORTED Unsupported. +**/ +EFI_STATUS +EFIAPI +ArmScmiInfoGetFastChannel ( + IN UINT32 DomainId, + OUT AML_CPC_INFO *CpcInfo + ) +{ + EFI_STATUS Status; + SCMI_PERFORMANCE_FASTCHANNEL FcLevelGet; + SCMI_PERFORMANCE_FASTCHANNEL FcLimitsSet; + SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES DomainAttributes; + + SCMI_PERFORMANCE_LEVEL *LevelArray; + UINT32 LevelCount; + + UINT64 FcLevelGetAddr; + UINT64 FcLimitsMaxSetAddr; + UINT64 FcLimitsMinSetAddr; + + if ((ScmiPerfProtocol =3D=3D NULL) || + (CpcInfo =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + Status =3D ScmiPerfProtocol->DescribeFastchannel ( + ScmiPerfProtocol, + DomainId, + ScmiMessageIdPerformanceLevelSet, + &FcLevelGet + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D ScmiPerfProtocol->DescribeFastchannel ( + ScmiPerfProtocol, + DomainId, + ScmiMessageIdPerformanceLimitsSet, + &FcLimitsSet + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D ScmiPerfProtocol->GetDomainAttributes ( + ScmiPerfProtocol, + DomainId, + &DomainAttributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D ArmScmiInfoDescribeLevels (DomainId, &LevelArray, &LevelCou= nt); + if (EFI_ERROR (Status)) { + return Status; + } + + /* Do some safety checks. + Only support FastChannels (and not doorbells) as this is + the only mechanism supported by SCP. + FcLimits[Get|Set] require 2 UINT32 values (max, then min) and + FcLimits[Get|Set] require 1 UINT32 value (level). + */ + if ((FcLevelGet.ChanSize !=3D sizeof (UINT32)) || + ((FcLevelGet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) =3D=3D + SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) || + (FcLimitsSet.ChanSize !=3D 2 * sizeof (UINT32)) || + ((FcLimitsSet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) =3D=3D + SCMI_PERF_FC_ATTRIB_HAS_DOORBELL)) + { + Status =3D EFI_INVALID_PARAMETER; + goto exit_handler; + } + + FcLevelGetAddr =3D ((UINT64)FcLevelGet.ChanAddrHigh << 32) | + FcLevelGet.ChanAddrLow; + FcLimitsMaxSetAddr =3D ((UINT64)FcLimitsSet.ChanAddrHigh << 32) | + FcLimitsSet.ChanAddrLow; + FcLimitsMinSetAddr =3D FcLimitsMaxSetAddr + 0x4; + + CpcInfo->Revision =3D EFI_ACPI_6_4_AML_CPC_RE= VISION_V3; + CpcInfo->HighestPerformanceInteger =3D LevelArray[LevelCount -= 1].Level; + CpcInfo->NominalPerformanceInteger =3D DomainAttributes.Sustai= nedPerfLevel; + CpcInfo->LowestNonlinearPerformanceInteger =3D LevelArray[0].Level; + CpcInfo->LowestPerformanceInteger =3D LevelArray[0].Level; + + CpcInfo->DesiredPerformanceRegister.AddressSpaceId =3D EFI_ACPI_6_4= _SYSTEM_MEMORY; + CpcInfo->DesiredPerformanceRegister.RegisterBitWidth =3D 32; + CpcInfo->DesiredPerformanceRegister.RegisterBitOffset =3D 0; + CpcInfo->DesiredPerformanceRegister.AccessSize =3D EFI_ACPI_6_4= _DWORD; + CpcInfo->DesiredPerformanceRegister.Address =3D FcLevelGetAd= dr; + + CpcInfo->MinimumPerformanceRegister.AddressSpaceId =3D EFI_ACPI_6_4= _SYSTEM_MEMORY; + CpcInfo->MinimumPerformanceRegister.RegisterBitWidth =3D 32; + CpcInfo->MinimumPerformanceRegister.RegisterBitOffset =3D 0; + CpcInfo->MinimumPerformanceRegister.AccessSize =3D EFI_ACPI_6_4= _DWORD; + CpcInfo->MinimumPerformanceRegister.Address =3D FcLimitsMinS= etAddr; + + CpcInfo->MaximumPerformanceRegister.AddressSpaceId =3D EFI_ACPI_6_4= _SYSTEM_MEMORY; + CpcInfo->MaximumPerformanceRegister.RegisterBitWidth =3D 32; + CpcInfo->MaximumPerformanceRegister.RegisterBitOffset =3D 0; + CpcInfo->MaximumPerformanceRegister.AccessSize =3D EFI_ACPI_6_4= _DWORD; + CpcInfo->MaximumPerformanceRegister.Address =3D FcLimitsMaxS= etAddr; + + CpcInfo->ReferencePerformanceCounterRegister.AddressSpaceId =3D EFI= _ACPI_6_4_FUNCTIONAL_FIXED_HARDWARE; + CpcInfo->ReferencePerformanceCounterRegister.RegisterBitWidth =3D 0x4= 0; + CpcInfo->ReferencePerformanceCounterRegister.RegisterBitOffset =3D 0; + CpcInfo->ReferencePerformanceCounterRegister.AccessSize =3D ARM= _FFH_REFERENCE_PERF_COUNTER_REGISTER; + CpcInfo->ReferencePerformanceCounterRegister.Address =3D 0x4= ; + + CpcInfo->DeliveredPerformanceCounterRegister.AddressSpaceId =3D EFI= _ACPI_6_4_FUNCTIONAL_FIXED_HARDWARE; + CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitWidth =3D 0x4= 0; + CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitOffset =3D 0; + CpcInfo->DeliveredPerformanceCounterRegister.AccessSize =3D ARM= _FFH_DELIVERED_PERF_COUNTER_REGISTER; + CpcInfo->DeliveredPerformanceCounterRegister.Address =3D 0x4= ; + + // SCMI should advertise performance values on a unified scale. So fre= quency + // values are not available. LowestFrequencyInteger and + // NominalFrequencyInteger are populated in the ConfigurationManager. + +exit_handler: + FreePool (LevelArray); + return Status; +} diff --git a/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf b= /DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf new file mode 100644 index 000000000000..aad3f0fa7b83 --- /dev/null +++ b/DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf @@ -0,0 +1,31 @@ +## @file +# Arm SCMI Info Library. +# +# Copyright (c) 2022 - 2023, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D ArmScmiInfoLib + FILE_GUID =3D 1A7CDB04-9FFC-40DA-A87C-A5ACADAF8136 + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D ArmScmiInfoLib + CONSTRUCTOR =3D ArmScmiInfoLibConstructor + +[Sources] + ArmScmiInfoLib.c + +[Packages] + ArmPkg/ArmPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[Protocols] + gArmScmiPerformanceProtocolGuid ## CONSUMES + +[Depex] + gArmScmiPerformanceProtocolGuid --=20 2.25.1