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.web12.6310.1624448512927829955 for ; Wed, 23 Jun 2021 04:41:53 -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 97CA931B; Wed, 23 Jun 2021 04:41:52 -0700 (PDT) Received: from e120189.arm.com (unknown [10.57.78.245]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 0FDF43F719; Wed, 23 Jun 2021 04:41:50 -0700 (PDT) From: "PierreGondois" To: devel@edk2.groups.io, Sami Mujawar , Alexei Fedorov Cc: Akanksha Jain , Alexandru Elisei Subject: [PATCH v1 11/13] DynamicTablesPkg: AML code generation to add an _LPI state Date: Wed, 23 Jun 2021 12:40:37 +0100 Message-Id: <20210623114039.24491-13-Pierre.Gondois@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210623114039.24491-1-Pierre.Gondois@arm.com> References: <20210623114039.24491-1-Pierre.Gondois@arm.com> From: Pierre Gondois Add AmlAddLpiState() to generates AML code to add an _LPI state to an _LPI object created using AmlCreateLpiNode(). AmlAddLpiState increments the count of LPI states in the LPI node by one, and adds the following package: Package() { MinResidency, WorstCaseWakeLatency, Flags, ArchFlags, ResCntFreq, EnableParentState, (GenericRegisterDescriptor != NULL) ? // Entry method. If a ResourceTemplate(GenericRegisterDescriptor) : // Register is given, Integer, // use it. Use the // Integer otherwise ResourceTemplate() { // NULL Residency Register (SystemMemory, 0, 0, 0, 0) // Counter }, ResourceTemplate() { // NULL Usage Counter Register (SystemMemory, 0, 0, 0, 0) }, "" // NULL State Name }, Signed-off-by: Pierre Gondois --- .../Include/Library/AmlLib/AmlLib.h | 71 +++ .../Common/AmlLib/CodeGen/AmlCodeGen.c | 439 ++++++++++++++++++ 2 files changed, 510 insertions(+) diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h index 40c45073d303..4932f6fd9c8b 100644 --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h @@ -716,6 +716,77 @@ AmlCreateLpiNode ( OUT AML_OBJECT_NODE_HANDLE * NewLpiNode OPTIONAL ); +/** Add an _LPI state to a LPI node created using AmlCreateLpiNode (). + + AmlAddLpiState () increments the Count of LPI states in the LPI node by one, + and adds the following package: + Package() { + MinResidency, + WorstCaseWakeLatency, + Flags, + ArchFlags, + ResCntFreq, + EnableParentState, + (GenericRegisterDescriptor != NULL) ? // Entry method. If a + ResourceTemplate(GenericRegisterDescriptor) : // Register is given, + Integer, // use it. Use the + // Integer otherwise. + ResourceTemplate() { // NULL Residency Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + ResourceTemplate() { // NULL Usage Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + "" // NULL State Name + }, + + Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States". + + @ingroup CodeGenApis + + @param [in] MinResidency Minimum Residency. + @param [in] WorstCaseWakeLatency Worst case wake-up latency. + @param [in] Flags Flags. + @param [in] ArchFlags Architectural flags. + @param [in] ResCntFreq Residency Counter Frequency. + @param [in] EnableParentState Enabled Parent State. + @param [in] GenericRegisterDescriptor Entry Method. + If not NULL, use this Register to + describe the entry method address. + @param [in] Integer Entry Method. + If GenericRegisterDescriptor is NULL, + take this value. + @param [in] ResidencyCounterRegister If not NULL, use it to populate the + residency counter register. + @param [in] UsageCounterRegister If not NULL, use it to populate the + usage counter register. + @param [in] StateName If not NULL, use it to populate the + state name. + @param [in] LpiNode Lpi node created with the function + AmlCreateLpiNode to which the new LPI + state is appended. + + @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 +AmlAddLpiState ( + IN UINT32 MinResidency, + IN UINT32 WorstCaseWakeLatency, + IN UINT32 Flags, + IN UINT32 ArchFlags, + IN UINT32 ResCntFreq, + IN UINT32 EnableParentState, + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * GenericRegisterDescriptor, OPTIONAL + IN UINT64 Integer, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * ResidencyCounterRegister, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * UsageCounterRegister, OPTIONAL + IN CHAR8 * StateName, OPTIONAL + IN AML_OBJECT_NODE_HANDLE LpiNode + ); + // DEPRECATED APIS #ifndef DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index 89350f65f5df..f0861040191f 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -1554,3 +1555,441 @@ error_handler: } return Status; } + +/** Add an _LPI state to a LPI node created using AmlCreateLpiNode. + + AmlAddLpiState increments the Count of LPI states in the LPI node by one, + and adds the following package: + Package() { + MinResidency, + WorstCaseWakeLatency, + Flags, + ArchFlags, + ResCntFreq, + EnableParentState, + (GenericRegisterDescriptor != NULL) ? // Entry method. If a + ResourceTemplate(GenericRegisterDescriptor) : // Register is given, + Integer, // use it. Use the + // Integer otherwise. + ResourceTemplate() { // NULL Residency Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + ResourceTemplate() { // NULL Usage Counter + Register (SystemMemory, 0, 0, 0, 0) + }, + "" // NULL State Name + }, + + Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States". + + @param [in] MinResidency Minimum Residency. + @param [in] WorstCaseWakeLatency Worst case wake-up latency. + @param [in] Flags Flags. + @param [in] ArchFlags Architectural flags. + @param [in] ResCntFreq Residency Counter Frequency. + @param [in] EnableParentState Enabled Parent State. + @param [in] GenericRegisterDescriptor Entry Method. + If not NULL, use this Register to + describe the entry method address. + @param [in] Integer Entry Method. + If GenericRegisterDescriptor is NULL, + take this value. + @param [in] ResidencyCounterRegister If not NULL, use it to populate the + residency counter register. + @param [in] UsageCounterRegister If not NULL, use it to populate the + usage counter register. + @param [in] StateName If not NULL, use it to populate the + state name. + @param [in] LpiNode Lpi node created with the function + AmlCreateLpiNode to which the new LPI + state is appended. + + @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 +AmlAddLpiState ( + IN UINT32 MinResidency, + IN UINT32 WorstCaseWakeLatency, + IN UINT32 Flags, + IN UINT32 ArchFlags, + IN UINT32 ResCntFreq, + IN UINT32 EnableParentState, + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * GenericRegisterDescriptor, OPTIONAL + IN UINT64 Integer, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * ResidencyCounterRegister, OPTIONAL + IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * UsageCounterRegister, OPTIONAL + IN CHAR8 * StateName, OPTIONAL + IN AML_OBJECT_NODE_HANDLE LpiNode + ) +{ + EFI_STATUS Status; + AML_DATA_NODE_HANDLE RdNode; + AML_OBJECT_NODE_HANDLE PackageNode; + AML_OBJECT_NODE_HANDLE IntegerNode; + AML_OBJECT_NODE_HANDLE StringNode; + AML_OBJECT_NODE_HANDLE NewLpiPackageNode; + AML_OBJECT_NODE_HANDLE ResourceTemplateNode; + + UINT32 Index; + AML_OBJECT_NODE_HANDLE CountNode; + UINT64 Count; + + if ((LpiNode == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)LpiNode) != EAmlNodeObject) || + (!AmlNodeHasOpCode (LpiNode, AML_NAME_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + RdNode = 0; + StringNode = NULL; + IntegerNode = NULL; + ResourceTemplateNode = NULL; + + // Get the LPI value which is represented as a PackageOp object node + // which is the 2nd fixed argument (i.e. index 1). + PackageNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + LpiNode, + EAmlParseIndexTerm1 + ); + if ((PackageNode == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) || + (!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0))) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + CountNode = NULL; + // The third variable argument is the LPI Count node. + for (Index = 0; Index < 3; Index++) { + CountNode = (AML_OBJECT_NODE_HANDLE)AmlGetNextVariableArgument ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)CountNode + ); + if (CountNode == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + } + + Status = AmlNodeGetIntegerValue (CountNode, &Count); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + Status = AmlUpdateInteger (CountNode, Count + 1); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenPackage (&NewLpiPackageNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // MinResidency + Status = AmlCodeGenInteger (MinResidency, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // WorstCaseWakeLatency + Status = AmlCodeGenInteger (WorstCaseWakeLatency, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // Flags + Status = AmlCodeGenInteger (Flags, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // ArchFlags + Status = AmlCodeGenInteger (ArchFlags, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // ResCntFreq + Status = AmlCodeGenInteger (ResCntFreq, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // EnableParentState + Status = AmlCodeGenInteger (EnableParentState, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + + // Entry Method + if (GenericRegisterDescriptor != NULL) { + // Entry Method: As a Register resource data + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlCodeGenRdRegister ( + GenericRegisterDescriptor->AddressSpaceId, + GenericRegisterDescriptor->RegisterBitWidth, + GenericRegisterDescriptor->RegisterBitOffset, + GenericRegisterDescriptor->Address, + GenericRegisterDescriptor->AccessSize, + NULL, + &RdNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + ResourceTemplateNode = NULL; + } else { + // Entry Method: As an integer + Status = AmlCodeGenInteger (Integer, &IntegerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)IntegerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + IntegerNode = NULL; + } + + // Residency Counter Register. + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + if (ResidencyCounterRegister != NULL) { + Status = AmlCodeGenRdRegister ( + ResidencyCounterRegister->AddressSpaceId, + ResidencyCounterRegister->RegisterBitWidth, + ResidencyCounterRegister->RegisterBitOffset, + ResidencyCounterRegister->Address, + ResidencyCounterRegister->AccessSize, + NULL, + &RdNode + ); + } else { + Status = AmlCodeGenRdRegister ( + EFI_ACPI_2_0_SYSTEM_MEMORY, + 0, + 0, + 0, + 0, + NULL, + &RdNode + ); + } + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + ResourceTemplateNode = NULL; + + // Usage Counter Register. + Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + if (UsageCounterRegister != NULL) { + Status = AmlCodeGenRdRegister ( + UsageCounterRegister->AddressSpaceId, + UsageCounterRegister->RegisterBitWidth, + UsageCounterRegister->RegisterBitOffset, + UsageCounterRegister->Address, + UsageCounterRegister->AccessSize, + NULL, + &RdNode + ); + } else { + Status = AmlCodeGenRdRegister ( + EFI_ACPI_2_0_SYSTEM_MEMORY, + 0, + 0, + 0, + 0, + NULL, + &RdNode + ); + } + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + Status = AmlAppendRdNode (ResourceTemplateNode, RdNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + RdNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)ResourceTemplateNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + ResourceTemplateNode = NULL; + + // State name. + if (UsageCounterRegister != NULL) { + Status = AmlCodeGenString (StateName, &StringNode); + } else { + Status = AmlCodeGenString ("", &StringNode); + } + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewLpiPackageNode, + (AML_NODE_HANDLE)StringNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + StringNode = NULL; + + // Add the new LPI state to the LpiNode. + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)NewLpiPackageNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto error_handler; + } + + return Status; + +error_handler: + if (RdNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)RdNode); + } + if (NewLpiPackageNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)NewLpiPackageNode); + } + if (StringNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)StringNode); + } + if (IntegerNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode); + } + if (ResourceTemplateNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode); + } + + return Status; +} -- 2.17.1