Hello, Just a reminder to provide feedback on this patch. Thanks, Swati swatisrik@nvidia.com ________________________________ From: Name Sent: Tuesday, August 16, 2022 2:18 PM To: devel@edk2.groups.io ; Sami.Mujawar@arm.com ; Alexei.Fedorov@arm.com ; michael.d.kinney@intel.com ; gaoliming@byosoft.com.cn ; zhiguang.liu@intel.com Cc: Swatisri Kantamsetti Subject: [PATCH 2/2] Dynamic Tbl Mgr: MPAM: MPAM Generator and supporting files From: Swatisri Kantamsetti ACPI header, MSC and Resource Nodes are populated in the MPAM Table Signed-off-by: Swatisri Kantamsetti --- DynamicTablesPkg/DynamicTables.dsc.inc | 2 + DynamicTablesPkg/Include/AcpiTableGenerator.h | 1 + .../Include/ArmNameSpaceObjects.h | 68 ++ .../Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf | 30 + .../Acpi/Arm/AcpiMpamLibArm/MpamGenerator.c | 649 ++++++++++++++++++ .../Acpi/Arm/AcpiMpamLibArm/MpamGenerator.h | 47 ++ 6 files changed, 797 insertions(+) create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.h diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 3d4fa0c4c4..745d5f0633 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -29,6 +29,7 @@ DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf + DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf @@ -54,6 +55,7 @@ NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf + NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h index f962dbff57..56d7375b4a 100644 --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h @@ -94,6 +94,7 @@ typedef enum StdAcpiTableId { EStdAcpiTableIdIort, ///< IORT Generator EStdAcpiTableIdPptt, ///< PPTT Generator EStdAcpiTableIdSrat, ///< SRAT Generator + EStdAcpiTableIdMpam, ///< MPAM Generator EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Generator EStdAcpiTableIdSsdtCpuTopology, ///< SSDT Cpu Topology diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h index 102e0f96be..39a14ed0b3 100644 --- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h @@ -63,6 +63,8 @@ typedef enum ArmObjectID { EArmObjPciInterruptMapInfo, ///< 39 - Pci Interrupt Map Info EArmObjRmr, ///< 40 - Reserved Memory Range Node EArmObjMemoryRangeDescriptor, ///< 41 - Memory Range Descriptor + EArmObjMscNodeInfo, ///< 40 - Msc Memory System Controller Node Info + EArmObjResNodeInfo, ///< 41 - Res Resource Node Info EArmObjMax } EARM_OBJECT_ID; @@ -1070,6 +1072,72 @@ typedef struct CmArmRmrDescriptor { UINT64 Length; } CM_ARM_MEMORY_RANGE_DESCRIPTOR; +/** A structure that describes Memory System Controller Node. + + MPAM Memory System Component Nodes are described by + this object. + + ID: EArmObjMscNodeInfo +*/ +typedef struct CmArmMscNodeInfo { + /// An unique token used to identify this object + CM_OBJECT_TOKEN Token; + + /// MPAM Base Address + UINT64 BaseAddress; + /// MMIO Size + UINT32 MmioSize; + /// Overflow Interrupt + UINT32 OverflowInterrupt; + /// Overflow Interrupt Flags + UINT32 OverflowInterruptFlags; + /// Overflow Interrupt Affinity + UINT32 OverflowInterruptAff; + /// Error Interrupt + UINT32 ErrorInterrupt; + /// Error Interrupt Flags + UINT32 ErrorInterruptFlags; + /// Error Interrupt Affinity + UINT32 ErrorInterruptAff; + /// Not Ready Signal time + UINT32 MaxNRdyUsec; + /// Linked Device HWID + UINT64 LinkedDeviceHwId; + /// Linked Device Instance ID + UINT32 LinkedDeviceInstanceHwId; + /// Number of Resource nodes + UINT32 NumResourceNodes; + /// Reference token for the list of resource nodes + //CM_OBJECT_TOKEN ResourceNodeListToken; + +} CM_ARM_MSC_NODE_INFO; + +/** A structure that describes Memory System Controller Node. + + MPAM Memory System Component Nodes are described by + this object. + + ID: EArmObjResNodeInfo +*/ +typedef struct CmArmResNodeInfo { + /// An unique token used to identify this object + CM_OBJECT_TOKEN Token; + + /// Identifier + UINT32 Identifier; + /// RIS Index + UINT8 RisIndex; + /// Locator Type + UINT8 LocatorType; + /// Locator + UINT64 Locator; + /// Num functional dependencies + UINT32 NumFuncDep; + /// Reference token for the list of resource nodes + CM_OBJECT_TOKEN FuncDepListToken; + +} CM_ARM_RESOURCE_NODE_INFO; + #pragma pack() #endif // ARM_NAMESPACE_OBJECTS_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf new file mode 100644 index 0000000000..480130dc21 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/AcpiMpamLibArm.inf @@ -0,0 +1,30 @@ +## @file +# MPAM Table Generator Inf file +# +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022, ARM Limited. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = AcpiMpamLibArm + FILE_GUID = 02d0c79f-41cd-45c9-9835-781229c619d1 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiMpamLibConstructor + DESTRUCTOR = AcpiMpamLibDestructor + +[Sources] + MpamGenerator.c + MpamGenerator.h + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.c new file mode 100644 index 0000000000..db3e8e95bc --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.c @@ -0,0 +1,649 @@ +/** @file + MPAM Table Generator + + Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + Copyright (c) 2022, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.4 Specification, January 2021 + + @par Glossary: + - Cm or CM - Configuration Manager + - Obj or OBJ - Object +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +#include "MpamGenerator.h" + +/** + ARM standard MPAM Generator + + Requirements: + The following Configuration Manager Object(s) are used by this Generator: + - EArmObjMscNodeInfo (REQUIRED) + - EArmObjResNodeInfo +*/ + +/** + This macro expands to a function that retrieves the MSC Node information + from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjMscNodeInfo, + CM_ARM_MSC_NODE_INFO + ); + +/** + This macro expands to a function that retrieves the Resource Node + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjResNodeInfo, + CM_ARM_RESOURCE_NODE_INFO + ); + +/** + Returns the size of the MPAM Memory System Controller (MSC) Node + + @param [in] Node Pointer to MSC Node Info CM object + + @retval Size of the MSC Node in bytes. +**/ +STATIC +UINT32 +GetMscNodeSize ( + IN CONST CM_ARM_MSC_NODE_INFO *Node + ) +{ + ASSERT (Node != NULL); + + // + return (UINT32)(sizeof (EFI_ACPI_6_4_MPAM_MSC_NODE) + + Node->NumResourceNodes * sizeof (EFI_ACPI_6_4_MPAM_RESOURCE_NODE)); +} + +/** Returns the total size required for the MSC and + updates the Node Indexer. + + This function calculates the size required for the node group + and also populates the Node Indexer array with offsets for the + individual nodes. + + @param [in] NodeStartOffset Offset from the start of the + MPAM where this node group starts. + @param [in] NodeList Pointer to MSC Group node list. + @param [in] NodeCount Count of the MSC Group nodes. + @param [in, out] NodeIndexer Pointer to the next Node Indexer. + + @retval Total size of the ITS Group Nodes. +**/ +STATIC +UINT64 +GetSizeofMscGroupNodes ( + IN CONST UINT32 NodeStartOffset, + IN CONST CM_ARM_MSC_NODE_INFO *NodeList, + IN UINT32 NodeCount, + IN OUT MPAM_NODE_INDEXER **CONST NodeIndexer + ) +{ + UINT64 Size; + + ASSERT (NodeList != NULL); + + Size = 0; + while (NodeCount-- != 0) { + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + DEBUG (( + DEBUG_INFO, + "MPAM: MSC Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + *NodeIndexer, + (*NodeIndexer)->Token, + (*NodeIndexer)->Object, + (*NodeIndexer)->Offset + )); + + Size += GetMscNodeSize (NodeList); + + (*NodeIndexer)++; + NodeList++; + } + + return Size; +} + +/** Update the MSC Group Node Information. + + @param [in] This Pointer to the table Generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Mpam Pointer to MPAM table structure. + @param [in] NodesStartOffset Offset for the start of the Msc Group + Nodes. + @param [in] NodeList Pointer to an array of Msc Group Node + Objects. + @param [in] NodeCount Number of Msc Group Node Objects. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. +**/ +STATIC +EFI_STATUS +AddMscNodes ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_HEADER *Mpam, + IN CONST UINT32 NodesStartOffset, + IN CONST CM_ARM_MSC_NODE_INFO *NodeList, + IN UINT32 NodeCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_4_MPAM_MSC_NODE *MscNode; + EFI_ACPI_6_4_MPAM_RESOURCE_NODE *ResourceNodeArray; + CM_ARM_RESOURCE_NODE_INFO *ResourceNodeList; + UINT64 NodeLength; + UINT32 ResourceNodeCount; + + ASSERT (Mpam != NULL); + + MscNode = (EFI_ACPI_6_4_MPAM_MSC_NODE *)((UINT8 *)Mpam + NodesStartOffset); + + // Get the Resource Node info to update the MPAM MSC node + Status = GetEArmObjResNodeInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &ResourceNodeList, + &ResourceNodeCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to add resource nodes info. Status = %r\n", + Status + )); + return Status; + } + + while (NodeCount-- != 0) { + NodeLength = GetMscNodeSize (NodeList); + + if (NodeLength > MAX_UINT16) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: MSC Node length 0x%lx > MAX_UINT16. Status = %r\n", + NodeLength, + Status + )); + return Status; + } + + // Populate the node header + MscNode->Length = (UINT16)NodeLength; + MscNode->Reserved = EFI_ACPI_RESERVED_WORD; + MscNode->Identifier = EFI_ACPI_RESERVED_DWORD; + MscNode->BaseAddress = NodeList->BaseAddress; + MscNode->MmioSize = NodeList->MmioSize; + MscNode->OverflowInterrupt = NodeList->OverflowInterrupt; + MscNode->OverflowInterruptFlags = NodeList->OverflowInterruptFlags; + MscNode->Reserved1 = EFI_ACPI_RESERVED_DWORD; + MscNode->OverflowInterruptAff = NodeList->OverflowInterruptAff; + MscNode->ErrorInterrupt = NodeList->ErrorInterrupt; + MscNode->ErrorInterruptFlags = NodeList->ErrorInterruptFlags; + MscNode->Reserved2 = EFI_ACPI_RESERVED_DWORD; + MscNode->ErrorInterruptAff = NodeList->ErrorInterruptAff; + MscNode->MaxNRdyUsec = NodeList->MaxNRdyUsec; + MscNode->LinkedDeviceHwId = NodeList->LinkedDeviceHwId; + MscNode->LinkedDeviceInstanceHwId = NodeList->LinkedDeviceInstanceHwId; + MscNode->NumResourceNodes = NodeList->NumResourceNodes; + + // ResourceNode List for each MSC + if (MscNode->NumResourceNodes > 0) { + // Resource Node array for this Msc node + ResourceNodeArray = (EFI_ACPI_6_4_MPAM_RESOURCE_NODE *)((UINT8 *)MscNode + sizeof (EFI_ACPI_6_4_MPAM_MSC_NODE)); + // Adding Resource Node content + while ( MscNode->NumResourceNodes-- != 0 ) { + ResourceNodeArray->Identifier = ResourceNodeList->Identifier; + ResourceNodeArray->RisIndex = ResourceNodeList->RisIndex; + ResourceNodeArray->Reserved1 = EFI_ACPI_RESERVED_WORD; + ResourceNodeArray->LocatorType = ResourceNodeList->LocatorType; + ResourceNodeArray->Locator = ResourceNodeList->Locator; + ResourceNodeArray->NumFuncDep = ResourceNodeList->NumFuncDep; + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to add Resource Node List. Status = %r\n", + Status + )); + return Status; + } + + ResourceNodeList++; + ResourceNodeArray++; + } + } + + // Next MSC Node + MscNode = (EFI_ACPI_6_4_MPAM_MSC_NODE *)((UINT8 *)MscNode + MscNode->Length); + NodeList++; + } // Msc Node + + return EFI_SUCCESS; +} + +/** + Construct the MPAM ACPI table. + + This function invokes the Configuration Manager protocol interface + to get the required hardware information for generating the ACPI + table. + + If this function allocates any resources then they must be freed + in the FreeXXXXTableResources function. + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table generator to be used. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [out] Table Pointer to the constructed ACPI Table. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildMpamTable ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + EFI_STATUS Status; + UINT64 TableSize; + UINT64 NodeSize; + UINT32 MpamNodeCount; + + UINT32 MscNodeCount; + UINT32 MscNodeOffset; + + EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_HEADER *Mpam; + ACPI_MPAM_GENERATOR *Generator; + CM_ARM_MSC_NODE_INFO *MscNodeList; + MPAM_NODE_INDEXER *NodeIndexer; + + ASSERT ( + (This != NULL) && + (AcpiTableInfo != NULL) && + (CfgMgrProtocol != NULL) && + (Table != NULL) && + (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && + (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) + ); + + DEBUG (( + DEBUG_ERROR, + "DEBUG PRINT: MPAM: Requested table revision = %d\n", + AcpiTableInfo->AcpiTableRevision + )); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Requested table revision = %d is not supported. " + "Supported table revisions: Minimum = %d. Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + Generator = (ACPI_MPAM_GENERATOR *)This; + *Table = NULL; + + // Get the Memory System Controller Node info and update the MPAM + // structure count with MSC Node count (Type 0) + Status = GetEArmObjMscNodeInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &MscNodeList, + &MscNodeCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to get memory system controller node info. Status = %r\n", + Status + )); + goto error_handler; + } + + MpamNodeCount = MscNodeCount; + Generator->MscNodeCount = MscNodeCount; + + // Allocate Node Indexer array + NodeIndexer = (MPAM_NODE_INDEXER *)AllocateZeroPool ( + sizeof (MPAM_NODE_INDEXER) * + MpamNodeCount + ); + if (NodeIndexer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to allocate memory for Node Indexer. Status = %r\n ", + Status + )); + goto error_handler; + } + + DEBUG ((DEBUG_INFO, "MPAM INFO: NodeIndexer = %p\n", NodeIndexer)); + Generator->MpamNodeCount = MpamNodeCount; + Generator->NodeIndexer = NodeIndexer; + + // Calculate the size of the MPAM table + TableSize = sizeof (EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_HEADER); + + // Include the size of MSC Nodes and index them + if (Generator->MscNodeCount != 0) { + MscNodeOffset = TableSize; + // Size of MSC nodes. + NodeSize = GetSizeofMscGroupNodes ( + MscNodeOffset, + MscNodeList, + Generator->MscNodeCount, + &NodeIndexer + ); + if (NodeSize > MAX_UINT32) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Invalid Size of Group Nodes. Status = %r\n", + Status + )); + goto error_handler; + } + + TableSize += NodeSize; + + DEBUG (( + DEBUG_INFO, + " MscNodeCount = %d\n" \ + " MscNodeOffset = 0x%x\n", + Generator->MscNodeCount, + MscNodeOffset + )); + } + + DEBUG (( + DEBUG_INFO, + "INFO: MPAM:\n" \ + " MpamNodeCount = %d\n" \ + " TableSize = 0x%X\n", + MpamNodeCount, + TableSize + )); + + if (TableSize > MAX_UINT32) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: MPAM Table Size 0x%lx > MAX_UINT32," \ + " Status = %r\n", + TableSize, + Status + )); + goto error_handler; + } + + // Allocate the Buffer for the MPAM table + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); + if (*Table == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to allocate memory for MPAM Table. " \ + "Size = %d. Status = %r\n", + TableSize, + Status + )); + goto error_handler; + } + + Mpam = (EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_HEADER *)*Table; + + DEBUG (( + DEBUG_INFO, + "MPAM: Mpam = 0x%p. TableSize = 0x%x\n", + Mpam, + TableSize + )); + + // Add ACPI header + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + &Mpam->Header, + AcpiTableInfo, + TableSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // Update MPAM table + Mpam->NumNodes = MscNodeCount; + Mpam->NodeOffset = sizeof (EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_HEADER); + Mpam->Reserved = EFI_ACPI_RESERVED_DWORD; + + // Add MSC Nodes to the generated table + if (Mpam->NumNodes != 0) { + Status = AddMscNodes ( + This, + CfgMgrProtocol, + Mpam, + MscNodeOffset, + MscNodeList, + MscNodeCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MPAM: Failed to add MSC Nodes. Status = %r\n", + Status + )); + goto error_handler; + } + } + + return Status; + +error_handler: + if (Generator->NodeIndexer != NULL) { + FreePool (Generator->NodeIndexer); + Generator->NodeIndexer = NULL; + } + + if (*Table != NULL) { + FreePool (*Table); + *Table = NULL; + } + + return Status; +} + +/** Free any resources allocated for constructing the MPAM + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI Table Info. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in, out] Table Pointer to the ACPI Table. + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +FreeMpamTableResources ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ACPI_MPAM_GENERATOR *Generator; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + Generator = (ACPI_MPAM_GENERATOR *)This; + + // Free any memory allocated by the generator + if (Generator->NodeIndexer != NULL) { + FreePool (Generator->NodeIndexer); + Generator->NodeIndexer = NULL; + } + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: MPAM: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + + return EFI_SUCCESS; +} + +/** The MPAM Table Generator revision. +*/ +#define MPAM_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the MPAM Table Generator. +*/ +STATIC +ACPI_MPAM_GENERATOR MpamGenerator = { + // ACPI table generator header + { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMpam), + // Generator Description + L"ACPI.STD.MPAM.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_STRUCTURE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_6_4_MEMORY_SYSTEM_RESOURCE_PARTITIONING_MONITORING_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + MPAM_GENERATOR_REVISION, + // Build Table function + BuildMpamTable, + // Free Resource function + FreeMpamTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL + }, + + // MPAM Generator private data + + // MPAM node count + 0, + // MSC node count + 0, + + // Pointer to MPAM Node Indexer + NULL +}; + +/** + Register the Generator with the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The Generator for the Table ID + is already registered. +**/ +EFI_STATUS +EFIAPI +AcpiMpamLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&MpamGenerator.Header); + DEBUG ((DEBUG_INFO, "MPAM: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiMpamLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&MpamGenerator.Header); + DEBUG ((DEBUG_INFO, "MPAM: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.h new file mode 100644 index 0000000000..1075bd8c6c --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMpamLibArm/MpamGenerator.h @@ -0,0 +1,47 @@ +/** @file + Header file for the dynamic MPAM generator + + Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + Copyright (c) 2022, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.4 Specification, January 2021 + - ARM Architecture Reference Manual ARMv8 + + @par Glossary: + - Cm or CM - Configuration Manager + - Obj or OBJ - Object +**/ + +#ifndef MPAM_GENERATOR_H_ +#define MPAM_GENERATOR_H_ + +#pragma pack(1) + +/** A structure that describes the Node indexer + used for indexing the MPAM MSC nodes. +*/ +typedef struct MpamNodeIndexer { + /// Index token for the Node + CM_OBJECT_TOKEN Token; + /// Pointer to the node + VOID *Object; + /// Node offset from the start of the MPAM table + UINT32 Offset; +} MPAM_NODE_INDEXER; + +typedef struct AcpiMpamGenerator { + /// ACPI Table generator header + ACPI_TABLE_GENERATOR Header; + /// MPAM structure count + UINT32 MpamNodeCount; + /// Count of Msc Nodes + UINT32 MscNodeCount; + /// List of indexed CM objects for MPAM generation + MPAM_NODE_INDEXER *NodeIndexer; +} ACPI_MPAM_GENERATOR; + +#pragma pack() + +#endif // MPAM_GENERATOR_H_ -- 2.17.1