On Wed, Oct 25, 2023 at 13:25:39 +0200, PierreGondois wrote: > From: Pierre Gondois <pierre.gond...@arm.com> > > 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.
Couple of questions: With a generic name like ArmScmiInfoLib, does is belong in ArmPkg or MdeModulePkg? Or if it's more tightly integrated with DynamicTablesPkg (not blatantly obvious from a quick skim below), should that be reflected by the library name? / Leif > Signed-off-by: Pierre Gondois <pierre.gond...@arm.com> > --- > 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/ArmScmiInfoLib.c > create mode 100644 DynamicTablesPkg/Library/ArmScmiInfoLib/ArmScmiInfoLib.inf > > diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc > b/DynamicTablesPkg/DynamicTables.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/AcpiHelperLib.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/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf > > TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf > diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec > b/DynamicTablesPkg/DynamicTablesPkg.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 > > + ## @libraryclass Defines a set of APIs to populate CmObj using SCMI. > + ArmScmiInfoLib|Include/Library/ArmScmiInfoLib.h > + > [Protocols] > # Configuration Manager Protocol GUID > gEdkiiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { > 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } } > diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc > b/DynamicTablesPkg/DynamicTablesPkg.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 > > [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/DynamicTablesPkg/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.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef ARM_SCMI_INFO_LIB_H_ > +#define ARM_SCMI_INFO_LIB_H_ > + > +#include <ConfigurationManagerObject.h> > + > +/** 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/DynamicTablesPkg/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.<BR> > + > + Arm Functional Fixed Hardware Specification: > + - https://developer.arm.com/documentation/den0048/latest/ > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include <Library/AcpiLib.h> > +#include <Library/ArmScmiInfoLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Protocol/ArmScmi.h> > +#include <Protocol/ArmScmiPerformanceProtocol.h> > + > +/** Arm FFH registers > + > + Cf. Arm Functional Fixed Hardware Specification > + s3.2 Performance management and Collaborative Processor Performance Control > +*/ > +#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 = gBS->LocateProtocol ( > + &gArmScmiPerformanceProtocolGuid, > + NULL, > + (VOID **)&ScmiPerfProtocol > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = 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 buffer > + 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 freed 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 == NULL) || > + (LevelArray == NULL) || > + (LevelArrayCount == NULL)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + // First call to get the number of levels. > + Size = 0; > + Status = ScmiPerfProtocol->DescribeLevels ( > + ScmiPerfProtocol, > + DomainId, > + &Count, > + &Size, > + NULL > + ); > + if (Status != EFI_BUFFER_TOO_SMALL) { > + // EFI_SUCCESS is not a valid option. > + if (Status == EFI_SUCCESS) { > + return EFI_INVALID_PARAMETER; > + } else { > + return Status; > + } > + } > + > + Array = AllocateZeroPool (Size); > + if (Array == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // Second call to get the descriptions of the levels. > + Status = ScmiPerfProtocol->DescribeLevels ( > + ScmiPerfProtocol, > + DomainId, > + &Count, > + &Size, > + Array > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *LevelArray = Array; > + *LevelArrayCount = 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 == NULL) || > + (CpcInfo == NULL)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ScmiPerfProtocol->DescribeFastchannel ( > + ScmiPerfProtocol, > + DomainId, > + ScmiMessageIdPerformanceLevelSet, > + &FcLevelGet > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ScmiPerfProtocol->DescribeFastchannel ( > + ScmiPerfProtocol, > + DomainId, > + ScmiMessageIdPerformanceLimitsSet, > + &FcLimitsSet > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ScmiPerfProtocol->GetDomainAttributes ( > + ScmiPerfProtocol, > + DomainId, > + &DomainAttributes > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ArmScmiInfoDescribeLevels (DomainId, &LevelArray, &LevelCount); > + 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 != sizeof (UINT32)) || > + ((FcLevelGet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) == > + SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) || > + (FcLimitsSet.ChanSize != 2 * sizeof (UINT32)) || > + ((FcLimitsSet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) == > + SCMI_PERF_FC_ATTRIB_HAS_DOORBELL)) > + { > + Status = EFI_INVALID_PARAMETER; > + goto exit_handler; > + } > + > + FcLevelGetAddr = ((UINT64)FcLevelGet.ChanAddrHigh << 32) | > + FcLevelGet.ChanAddrLow; > + FcLimitsMaxSetAddr = ((UINT64)FcLimitsSet.ChanAddrHigh << 32) | > + FcLimitsSet.ChanAddrLow; > + FcLimitsMinSetAddr = FcLimitsMaxSetAddr + 0x4; > + > + CpcInfo->Revision = > EFI_ACPI_6_4_AML_CPC_REVISION_V3; > + CpcInfo->HighestPerformanceInteger = LevelArray[LevelCount - > 1].Level; > + CpcInfo->NominalPerformanceInteger = > DomainAttributes.SustainedPerfLevel; > + CpcInfo->LowestNonlinearPerformanceInteger = LevelArray[0].Level; > + CpcInfo->LowestPerformanceInteger = LevelArray[0].Level; > + > + CpcInfo->DesiredPerformanceRegister.AddressSpaceId = > EFI_ACPI_6_4_SYSTEM_MEMORY; > + CpcInfo->DesiredPerformanceRegister.RegisterBitWidth = 32; > + CpcInfo->DesiredPerformanceRegister.RegisterBitOffset = 0; > + CpcInfo->DesiredPerformanceRegister.AccessSize = EFI_ACPI_6_4_DWORD; > + CpcInfo->DesiredPerformanceRegister.Address = FcLevelGetAddr; > + > + CpcInfo->MinimumPerformanceRegister.AddressSpaceId = > EFI_ACPI_6_4_SYSTEM_MEMORY; > + CpcInfo->MinimumPerformanceRegister.RegisterBitWidth = 32; > + CpcInfo->MinimumPerformanceRegister.RegisterBitOffset = 0; > + CpcInfo->MinimumPerformanceRegister.AccessSize = EFI_ACPI_6_4_DWORD; > + CpcInfo->MinimumPerformanceRegister.Address = FcLimitsMinSetAddr; > + > + CpcInfo->MaximumPerformanceRegister.AddressSpaceId = > EFI_ACPI_6_4_SYSTEM_MEMORY; > + CpcInfo->MaximumPerformanceRegister.RegisterBitWidth = 32; > + CpcInfo->MaximumPerformanceRegister.RegisterBitOffset = 0; > + CpcInfo->MaximumPerformanceRegister.AccessSize = EFI_ACPI_6_4_DWORD; > + CpcInfo->MaximumPerformanceRegister.Address = FcLimitsMaxSetAddr; > + > + CpcInfo->ReferencePerformanceCounterRegister.AddressSpaceId = > EFI_ACPI_6_4_FUNCTIONAL_FIXED_HARDWARE; > + CpcInfo->ReferencePerformanceCounterRegister.RegisterBitWidth = 0x40; > + CpcInfo->ReferencePerformanceCounterRegister.RegisterBitOffset = 0; > + CpcInfo->ReferencePerformanceCounterRegister.AccessSize = > ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER; > + CpcInfo->ReferencePerformanceCounterRegister.Address = 0x4; > + > + CpcInfo->DeliveredPerformanceCounterRegister.AddressSpaceId = > EFI_ACPI_6_4_FUNCTIONAL_FIXED_HARDWARE; > + CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitWidth = 0x40; > + CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitOffset = 0; > + CpcInfo->DeliveredPerformanceCounterRegister.AccessSize = > ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER; > + CpcInfo->DeliveredPerformanceCounterRegister.Address = 0x4; > + > + // SCMI should advertise performance values on a unified scale. So > frequency > + // 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 = 0x0001001B > + BASE_NAME = ArmScmiInfoLib > + FILE_GUID = 1A7CDB04-9FFC-40DA-A87C-A5ACADAF8136 > + VERSION_STRING = 1.0 > + MODULE_TYPE = DXE_DRIVER > + LIBRARY_CLASS = ArmScmiInfoLib > + CONSTRUCTOR = ArmScmiInfoLibConstructor > + > +[Sources] > + ArmScmiInfoLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + DynamicTablesPkg/DynamicTablesPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + > +[Protocols] > + gArmScmiPerformanceProtocolGuid ## CONSUMES > + > +[Depex] > + gArmScmiPerformanceProtocolGuid > -- > 2.25.1 > > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#110091): https://edk2.groups.io/g/devel/message/110091 Mute This Topic: https://groups.io/mt/102175821/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-