From 58350c0055c65ceae6f77908910cddfff419a2f1 Mon Sep 17 00:00:00 2001 From: Jeff Brasen Date: Thu, 22 Sep 2022 14:36:45 -0600 Subject: DynamicTablesPkg: AML Code generation to add _CPC entries _CPC entries can describe CPU performance information. The object is described in ACPI 6.4 s8.4.7.1. "_CPC (Continuous Performance Control)". Add AmlCreateCpcNode() helper function to add _CPC entries to an existing CPU object. Signed-off-by: Jeff Brasen Reviewed-by: Pierre Gondois Reviewed-by: Sami Mujawar --- .../Library/Common/AmlLib/CodeGen/AmlCodeGen.c | 475 +++++++++++++++++++++ 1 file changed, 475 insertions(+) (limited to 'DynamicTablesPkg/Library') diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index 5fb39d077b..7e67482f99 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -2850,3 +2851,477 @@ error_handler: return Status; } + +/** Adds a register to the package + + @ingroup CodeGenApis + + @param [in] Register If provided, register that will be added to package. + otherwise NULL register will be added + @param [in] PackageNode Package to add value to + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlAddRegisterToPackage ( + IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE *Register OPTIONAL, + IN AML_OBJECT_NODE_HANDLE PackageNode + ) +{ + EFI_STATUS Status; + AML_DATA_NODE_HANDLE RdNode; + AML_OBJECT_NODE_HANDLE ResourceTemplateNode; + + RdNode = NULL; + + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + if (Register != NULL) { + Status = AmlCodeGenRdRegister ( + Register->AddressSpaceId, + Register->RegisterBitWidth, + Register->RegisterBitOffset, + Register->Address, + Register->AccessSize, + NULL, + &RdNode + ); + } else { + Status = AmlCodeGenRdRegister ( + EFI_ACPI_6_4_SYSTEM_MEMORY, + 0, + 0, + 0, + 0, + NULL, + &RdNode + ); + } + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + return Status; + +error_handler: + if (RdNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)RdNode); + } + + if (ResourceTemplateNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode); + } + + return Status; +} + +/** Utility function to check if generic address points to NULL + + @param [in] Address Pointer to the Generic address + + @retval TRUE Address is system memory with an Address of 0. + @retval FALSE Address does not point to NULL. +**/ +STATIC +BOOLEAN +EFIAPI +IsNullGenericAddress ( + IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE *Address + ) +{ + if ((Address == NULL) || + ((Address->AddressSpaceId == EFI_ACPI_6_4_SYSTEM_MEMORY) && + (Address->Address == 0x0))) + { + return TRUE; + } + + return FALSE; +} + +/** Adds an integer or register to the package + + @ingroup CodeGenApis + + @param [in] Register If provided, register that will be added to package + @param [in] Integer If Register is NULL, integer that will be added to the package + @param [in] PackageNode Package to add value to + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +AmlAddRegisterOrIntegerToPackage ( + IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE *Register OPTIONAL, + IN UINT32 Integer, + IN AML_OBJECT_NODE_HANDLE PackageNode + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE IntegerNode; + + IntegerNode = NULL; + + if (!IsNullGenericAddress (Register)) { + Status = AmlAddRegisterToPackage (Register, PackageNode); + } else { + Status = AmlCodeGenInteger (Integer, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + } + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + if (IntegerNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode); + } + } + + return Status; +} + +/** Create a _CPC node. + + Creates and optionally adds the following node + Name(_CPC, Package() + { + NumEntries, // Integer + Revision, // Integer + HighestPerformance, // Integer or Buffer (Resource Descriptor) + NominalPerformance, // Integer or Buffer (Resource Descriptor) + LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor) + LowestPerformance, // Integer or Buffer (Resource Descriptor) + GuaranteedPerformanceRegister, // Buffer (Resource Descriptor) + DesiredPerformanceRegister , // Buffer (Resource Descriptor) + MinimumPerformanceRegister , // Buffer (Resource Descriptor) + MaximumPerformanceRegister , // Buffer (Resource Descriptor) + PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor) + TimeWindowRegister, // Buffer (Resource Descriptor) + CounterWraparoundTime, // Integer or Buffer (Resource Descriptor) + ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor) + DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor) + PerformanceLimitedRegister, // Buffer (Resource Descriptor) + CPPCEnableRegister // Buffer (Resource Descriptor) + AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor) + AutonomousActivityWindowRegister, // Buffer (Resource Descriptor) + EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor) + ReferencePerformance // Integer or Buffer (Resource Descriptor) + LowestFrequency, // Integer or Buffer (Resource Descriptor) + NominalFrequency // Integer or Buffer (Resource Descriptor) + }) + + If resource buffer is NULL then integer will be used. + + Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control) + + @ingroup CodeGenApis + + @param [in] CpcInfo CpcInfo object + @param [in] ParentNode If provided, set ParentNode as the parent + of the node created. + @param [out] NewCpcNode If success and provided, contains the created node. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlCreateCpcNode ( + IN AML_CPC_INFO *CpcInfo, + IN AML_NODE_HANDLE ParentNode OPTIONAL, + OUT AML_OBJECT_NODE_HANDLE *NewCpcNode OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE CpcNode; + AML_OBJECT_NODE_HANDLE CpcPackage; + UINT32 NumberOfEntries; + + if ((CpcInfo == NULL) || + ((ParentNode == NULL) && (NewCpcNode == NULL))) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // Revision 3 per ACPI 6.4 specification + if (CpcInfo->Revision == 3) { + // NumEntries 23 per ACPI 6.4 specification + NumberOfEntries = 23; + } else { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if ((IsNullGenericAddress (&CpcInfo->HighestPerformanceBuffer) && + (CpcInfo->HighestPerformanceInteger == 0)) || + (IsNullGenericAddress (&CpcInfo->NominalPerformanceBuffer) && + (CpcInfo->NominalPerformanceInteger == 0)) || + (IsNullGenericAddress (&CpcInfo->LowestNonlinearPerformanceBuffer) && + (CpcInfo->LowestNonlinearPerformanceInteger == 0)) || + (IsNullGenericAddress (&CpcInfo->LowestPerformanceBuffer) && + (CpcInfo->LowestPerformanceInteger == 0)) || + IsNullGenericAddress (&CpcInfo->DesiredPerformanceRegister) || + IsNullGenericAddress (&CpcInfo->ReferencePerformanceCounterRegister) || + IsNullGenericAddress (&CpcInfo->DeliveredPerformanceCounterRegister) || + IsNullGenericAddress (&CpcInfo->PerformanceLimitedRegister)) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CpcPackage = NULL; + + Status = AmlCodeGenNamePackage ("_CPC", NULL, &CpcNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // Get the Package object node of the _CPC node, + // which is the 2nd fixed argument (i.e. index 1). + CpcPackage = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + CpcNode, + EAmlParseIndexTerm1 + ); + if ((CpcPackage == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)CpcPackage) != EAmlNodeObject) || + (!AmlNodeHasOpCode (CpcPackage, AML_PACKAGE_OP, 0))) + { + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + NULL, + NumberOfEntries, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + NULL, + CpcInfo->Revision, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->HighestPerformanceBuffer, + CpcInfo->HighestPerformanceInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->NominalPerformanceBuffer, + CpcInfo->NominalPerformanceInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->LowestNonlinearPerformanceBuffer, + CpcInfo->LowestNonlinearPerformanceInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->LowestPerformanceBuffer, + CpcInfo->LowestPerformanceInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->GuaranteedPerformanceRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->DesiredPerformanceRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->MinimumPerformanceRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->MaximumPerformanceRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->PerformanceReductionToleranceRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->TimeWindowRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->CounterWraparoundTimeBuffer, + CpcInfo->CounterWraparoundTimeInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->ReferencePerformanceCounterRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->DeliveredPerformanceCounterRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->PerformanceLimitedRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->CPPCEnableRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->AutonomousSelectionEnableBuffer, + CpcInfo->AutonomousSelectionEnableInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->AutonomousActivityWindowRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterToPackage (&CpcInfo->EnergyPerformancePreferenceRegister, CpcPackage); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->ReferencePerformanceBuffer, + CpcInfo->ReferencePerformanceInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->LowestFrequencyBuffer, + CpcInfo->LowestFrequencyInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlAddRegisterOrIntegerToPackage ( + &CpcInfo->NominalFrequencyBuffer, + CpcInfo->NominalFrequencyInteger, + CpcPackage + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = LinkNode (CpcNode, ParentNode, NewCpcNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + return Status; + +error_handler: + AmlDeleteTree ((AML_NODE_HANDLE)CpcNode); + return Status; +} -- cgit v1.2.3