Get remote memory node details(number of memory nodes, remote memory
range address) by using CxlProtocol interfaces.
Prepare SRAT table with both Local memory, remote memory blocks,
along with other necessary details.
Prepare HMAT table with required proximity, latency info.
In Single-Chip scenario, one of the primary use case, of having
extended remote memory area and SRAT,HMAT table, is to avail the
extended remote memory region as CXL.Memory.
Signed-off-by: Sayanta Pattanayak <sayanta.pattanayak@...>
---
Platform/ARM/SgiPkg/SgiPlatform.dsc.inc =
| 7 +
Platform/ARM/SgiPkg/SgiPlatform.fdf =
| 9 +-
Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerator.inf=
| 73 +++++
Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerator.h =
| 36 +++
Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerator.c =
| 72 +++++
Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/HmatTableGenerator.c =
| 120 ++++++++
Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/SratTableGenerator.c =
| 290 ++++++++++++++++++++
7 files changed, 606 insertions(+), 1 deletion(-)
diff --git a/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc b/Platform/ARM/SgiPk=
g/SgiPlatform.dsc.inc
index 2f5dadfaef..4113d8ad90 100644
--- a/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc
+++ b/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc
@@ -308,6 +308,13 @@
#
Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.inf
=20
+ #
+ # SRAT/HMAT Table generator
+ #
+!if $(EDK2_ENABLE_REMOTE_CXL_MEM) =3D=3D TRUE
+ Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerator.i=
nf
+!endif
+
#
# FAT filesystem + GPT/MBR partitioning
#
diff --git a/Platform/ARM/SgiPkg/SgiPlatform.fdf b/Platform/ARM/SgiPkg/Sg=
iPlatform.fdf
index 4018480b42..9c5bfd30ef 100644
--- a/Platform/ARM/SgiPkg/SgiPlatform.fdf
+++ b/Platform/ARM/SgiPkg/SgiPlatform.fdf
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2021, ARM Limited. All rights reserved.
+# Copyright (c) 2018 - 2022, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -194,6 +194,13 @@ READ_LOCK_STATUS =3D TRUE
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
=20
+ #
+ # SRAT/HMAT Table generator
+ #
+!if $(EDK2_ENABLE_REMOTE_CXL_MEM) =3D=3D TRUE
+ INF Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerat=
or.inf
+!endif
+
#
# Networking stack
#
diff --git a/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableG=
enerator.inf b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTabl=
eGenerator.inf
new file mode 100644
index 0000000000..2be6d5a2aa
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerato=
r.inf
@@ -0,0 +1,73 @@
+## @file
+# ACPI table generator sources.
+#
+# SRAT, HMAT table generator sources prepare respective ACPI tables, th=
at
+# help OSPM to identify device domains, memory attributes etc.
+#
+# Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION =3D 0x0001001A
+ BASE_NAME =3D AcpiTableGeneratorLib
+ FILE_GUID =3D fd0e015b-bbbf-474c-8b68-9ea1b555f91=
3
+ MODULE_TYPE =3D DXE_DRIVER
+ VERSION_STRING =3D 1.0
+ ENTRY_POINT =3D AcpiTableGeneratorEntryPoint
+
+[Sources.common]
+ AcpiTableGenerator.c
+ HmatTableGenerator.c
+ SratTableGenerator.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Platform/ARM/SgiPkg/SgiPlatform.dec
+ Platform/ARM/Drivers/CxlDxe/CxlDxe.dec
+
+
+[LibraryClasses]
+ ArmPlatformLib
+ BaseLib
+ DebugLib
+ HobLib
+ IoLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+ gCxlPlatformProtocolGuid ## CONSUMES
+
+[Guids]
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
+ AND gCxlPlatformProtocolGuid
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdClusterCount
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+ gArmSgiTokenSpaceGuid.PcdDramBlock2Base
+ gArmSgiTokenSpaceGuid.PcdDramBlock2Size
+ gArmSgiTokenSpaceGuid.PcdGicSize
+
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+ gArmTokenSpaceGuid.PcdMmBufferBase
+ gArmTokenSpaceGuid.PcdMmBufferSize
+
+ gArmSgiTokenSpaceGuid.PcdChipCount
+
+ gArmSgiTokenSpaceGuid.PcdNumLocalMemBlock
+
+ gArmSgiTokenSpaceGuid.PcdRemoteMemoryBase
diff --git a/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableG=
enerator.h b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableG=
enerator.h
new file mode 100644
index 0000000000..597c0f7a1e
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerato=
r.h
@@ -0,0 +1,36 @@
+/** @file
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __ACPI_TABLE_GENERATOR_H__
+#define __ACPI_TABLE_GENERATOR_H__
+
+#include <Library/AcpiLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Cxl.h>
+#include <SgiAcpiHeader.h>
+#include <SgiPlatform.h>
+
+#define LOWER_BYTES_MASK 0xFFFFF000
+#define LOWER_BYTES_SHIFT 32
+
+EFI_STATUS EFIAPI SratTableGenerator (
+ EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol
+ );
+
+EFI_STATUS EFIAPI HmatTableGenerator (
+ EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol
+ );
+
+#endif // __ACPI_TABLE_GENERATOR_H__
diff --git a/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableG=
enerator.c b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableG=
enerator.c
new file mode 100644
index 0000000000..c0958c8a5a
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/AcpiTableGenerato=
r.c
@@ -0,0 +1,72 @@
+/** @file
+ ACPI Table Generator Entrypoint. It invokes functions to
+ generate SRAT, HMAT tables.
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiTableGenerator.h"
+
+STATIC EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol =3D NULL;
+
+/**
+ Initialize function for the driver.
+
+ Locate ACPI Table protocol and installs SRAT, HMAT tables.
+
+ @param[in] ImageHandle Handle to image.
+ @param[in] SystemTable Pointer to System table.
+
+ @retval EFI_SUCCESS On successful installation of SRAT, HMAT ACPI ta=
bles.
+ @retval Other Failure in installing ACPI tables.
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiTableGeneratorEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status =3D gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID **)&mAcpiTableProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to locate ACPI table protocol, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+
+ Status =3D SratTableGenerator (mAcpiTableProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to create SRAT table: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+
+ Status =3D HmatTableGenerator (mAcpiTableProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to create HMAT table: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+
+ return Status;
+}
diff --git a/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/HmatTableG=
enerator.c b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/HmatTableG=
enerator.c
new file mode 100644
index 0000000000..91c8a18d13
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/HmatTableGenerato=
r.c
@@ -0,0 +1,120 @@
+/** @file
+ Heterogeneous Memory Attribute Table (HMAT) Table Generator.
+
+ The (HMAT) describes the memory attributes, such as bandwidth and late=
ncy
+ details, related to Memory Proximity Domains. The software is expected
+ to use this information as a hint for optimization, or when the system=
has
+ heterogeneous memory.
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference:
+ - ACPI 6.4, Chapter 5.2.27 Heterogeneous Memory Attribute Table (H=
MAT)
+**/
+
+#include "AcpiTableGenerator.h"
+
+#define CHIP_CNT 2
+#define INITATOR_PROXIMITY_DOMAIN_CNT 2
+#define TARGET_PROXIMITY_DOMAIN_CNT 2
+
+/* HMAT Table */
+typedef struct InitiatorTargetProximityMatrix {
+ UINT32 InitatorProximityDomain[INITATOR_PROXIMITY_DOMAIN_CNT];
+ UINT32 TargetProximityDomain[TARGET_PROXIMITY_DOMAIN_CNT];
+ UINT16 MatrixEntry[INITATOR_PROXIMITY_DOMAIN_CNT * TARGET_PROXIMITY_D=
OMAIN_CNT];
+} INITIATOR_TARGET_PROXIMITY_MATRIX;
+
+typedef struct {
+ EFI_ACPI_6_4_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_HEADER Header;
+ EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES
+ Proximity[CHIP_CNT];
+ EFI_ACPI_6_4_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO
+ LatencyInfo;
+ INITIATOR_TARGET_PROXIMITY_MATRIX Matrix;
+} EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE;
+
+EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE Hmat =3D {
+ // Header
+ {
+ ARM_ACPI_HEADER (
+ EFI_ACPI_6_4_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE,
+ EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE,
+ EFI_ACPI_6_4_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_REVISION
+ ),
+ {
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE
+ },
+ },
+
+ // Memory Proximity Domain
+ {
+ EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES_INIT =
(
+ 1, 0x0, 0x0),
+ EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES_INIT =
(
+ 1, 0x0, 0x1),
+ },
+
+ // Latency Info
+ EFI_ACPI_6_4_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO=
_INIT (
+ 0, 0, 0, INITATOR_PROXIMITY_DOMAIN_CNT, TARGET_PROXIMITY_DOMAIN_CNT,=
100),
+ {
+ {0, 1},
+ {0, 1},
+ {
+ //
+ // The latencies mentioned in this table are hypothetical values a=
nd
+ // represents typical latency between two chips. These values are
+ // applicable only for RD-N1-Edge dual-chip fixed virtual platform=
and
+ // should not be reused for other platforms.
+ //
+ 10, 20,
+ 20, 10,
+ }
+ }
+};
+
+/**
+ Installs the HMAT table.
+
+ @param[in] mAcpiTableProtocol Handle to AcpiTableProtocol.
+
+ @retval EFI_SUCCESS On successful installation of HMAT table.
+ @retval Other Failure in installing HMAT table.
+**/
+EFI_STATUS
+EFIAPI
+HmatTableGenerator (
+ IN EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol
+ )
+{
+ EFI_STATUS Status;
+ UINTN AcpiTableHandle;
+
+ Status =3D mAcpiTableProtocol->InstallAcpiTable (
+ mAcpiTableProtocol,
+ &Hmat,
+ sizeof (Hmat),
+ &AcpiTableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: HMAT table installation failed, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "Installed HMAT table \n"
+ ));
+ }
+
+ return Status;
+}
+
diff --git a/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/SratTableG=
enerator.c b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/SratTableG=
enerator.c
new file mode 100644
index 0000000000..84d191252d
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Library/AcpiTableGeneratorLib/SratTableGenerato=
r.c
@@ -0,0 +1,290 @@
+/** @file
+ SRAT Table Generator.
+
+ SRAT table provides information that allows OSPM to associate devices =
such as
+ processors with system locality / proximity domains and clock domains.
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference:
+ - ACPI 6.4, Chapter 5.2.16 System Resource Affinity Table (SRAT)
+ **/
+
+#include <Library/HobLib.h>
+#include "AcpiTableGenerator.h"
+
+STATIC EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE *RemoteMemory;
+
+EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER SratHeader =3D {
+ ARM_ACPI_HEADER (
+ EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE,
+ EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER,
+ EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION
+ ),
+ 0x00000001,
+ EFI_ACPI_RESERVED_QWORD
+};
+
+EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE Gicc[8] =3D {
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000000, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000001, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000002, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000003, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000004, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000005, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000006, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000007, 0x00000001, 0x00000000),
+#if ((CORE_COUNT * CLUSTER_COUNT) > 8)
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000008, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x00000009, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x0000000A, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x0000000B, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x0000000C, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x0000000D, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x0000000E, 0x00000001, 0x00000000),
+ EFI_ACPI_6_4_GICC_AFFINITY_STRUCTURE_INIT (
+ 0x0, 0x0000000F, 0x00000001, 0x00000000),
+#endif
+};
+
+EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE LocalMemory[3] =3D {
+ // Memory at 32-bit address space
+ EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE_INIT (
+ 0x0, FixedPcdGet64 (PcdSystemMemoryBase),
+ FixedPcdGet64 (PcdSystemMemorySize), 0x00000001),
+ // Memory at 64-bit address space
+ EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE_INIT (
+ 0x0, FixedPcdGet64 (PcdDramBlock2Base),
+ FixedPcdGet64 (PcdDramBlock2Size), 0x00000001),
+ // MmBuffer region
+ EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE_INIT (
+ 0x0, FixedPcdGet64 (PcdMmBufferBase),
+ FixedPcdGet64 (PcdMmBufferSize), 0x00000001),
+};
+
+/**
+ Fetch the details of Remote Memory Node, using CXL protocol interfaces=
.
+
+ By using CXL platform protocol interfaces, fetch number CXL remote mem=
ory
+ nodes and their corresponding configurations(Base address, length).
+
+ @param[out] RemoteMemCount Number of Remote CXL memory nodes.
+
+ @retval RemoteMem Remote memory configuraiton on successful fet=
ching
+ of remote memory configuration.
+ @retval Zero Returns Zero on failure.
+**/
+STATIC
+REMOTE_MEMORY_CONFIG *
+FetchRemoteCxlMem (OUT UINT32 *RemoteMemCount)
+{
+ EFI_STATUS Status;
+ CXL_PLATFORM_PROTOCOL *CxlProtocol;
+ REMOTE_MEMORY_CONFIG *RemoteMem;
+ UINT32 RemoteMemNumber;
+
+ Status =3D gBS->LocateProtocol (
+ &gCxlPlatformProtocolGuid,
+ NULL,
+ (VOID **)&CxlProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to locate CXL Protocol, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return 0;
+ }
+
+ RemoteMemNumber =3D CxlProtocol->CxlGetRemoteMemCount();
+ if (RemoteMemNumber) {
+ RemoteMem =3D (REMOTE_MEMORY_CONFIG *) AllocateZeroPool (
+ sizeof (REMOTE_MEMORY_CONFIG)=
*
+ RemoteMemNumber
+ );
+ if (RemoteMem =3D=3D NULL) {
+ DEBUG ((DEBUG_WARN, "No memory for Remote Memory affinity structur=
e:\n"));
+ return 0;
+ }
+ }
+
+ Status =3D CxlProtocol->CxlGetRemoteMem(RemoteMem, &RemoteMemNumber);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get CXL Remote memory details: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ FreePool(RemoteMem);
+ return 0;
+ }
+
+ *RemoteMemCount =3D RemoteMemNumber;
+
+ return RemoteMem;
+}
+
+/**
+ Fetch the details of all Remote Memory Node, using CXL protocol interf=
aces.
+ Prepare SRAT table structure by combining LocalMemoryNode and
+ RemoteMemoryNode information. Thereafter installs the SRAT table.
+
+ @param[in] mAcpiTableProtocol Handle to AcpiTableProtocol.
+
+ @retval EFI_SUCCESS On successful installation of SRAT table.
+ @retval Other Failure in installing SRAT table.
+**/
+EFI_STATUS
+EFIAPI
+SratTableGenerator (
+ IN EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol
+ )
+{
+ EFI_STATUS Status;
+ UINTN AcpiTableHandle;
+ UINTN MemoryNodeCount;
+ UINTN TableSize;
+ UINT8 Idx;
+ VOID *Srat, *SratDataNext;
+ REMOTE_MEMORY_CONFIG *RemoteMem;
+ UINT32 RemoteMemCount;
+ UINT64 HostPhysicalBase;
+ UINT64 MemDevicePhysicalBase;
+
+
+ RemoteMem =3D FetchRemoteCxlMem(&RemoteMemCount);
+
+ if (RemoteMemCount) {
+ RemoteMemory =3D
+ AllocateZeroPool (sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE) =
*
+ RemoteMemCount
+ );
+ if (RemoteMemory =3D=3D NULL) {
+ DEBUG ((DEBUG_WARN, "No memory for Remote Memory affinity structur=
e:\n"));
+ RemoteMemCount =3D 0;
+ } else {
+ HostPhysicalBase =3D FixedPcdGet64 (PcdRemoteMemoryBase);
+
+ for (Idx =3D 0; Idx < RemoteMemCount; Idx++) {
+ RemoteMemory[Idx].Type =3D 1;
+ RemoteMemory[Idx].Length =3D
+ sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE);
+ RemoteMemory[Idx].ProximityDomain =3D 1;
+ RemoteMemory[Idx].Reserved1 =3D EFI_ACPI_RESERVED_WORD;
+
+ MemDevicePhysicalBase =3D HostPhysicalBase + RemoteMem[Idx].DpaA=
ddress;
+ RemoteMemory[Idx].AddressBaseLow =3D
+ MemDevicePhysicalBase & LOWER_BYTES_MASK;
+ RemoteMemory[Idx].AddressBaseHigh =3D
+ MemDevicePhysicalBase >> LOWER_BYTES_SHIFT;
+
+ RemoteMemory[Idx].LengthLow =3D
+ RemoteMem[Idx].DpaLength & LOWER_BYTES_MASK;
+ RemoteMemory[Idx].LengthHigh =3D
+ RemoteMem[Idx].DpaLength >> LOWER_BYTES_SHIFT;
+
+ RemoteMemory[Idx].Reserved2 =3D EFI_ACPI_RESERVED_WORD;
+ RemoteMemory[Idx].Flags =3D 0x1;
+ RemoteMemory[Idx].Reserved3 =3D EFI_ACPI_RESERVED_WORD;
+
+ HostPhysicalBase +=3D
+ RemoteMemory[Idx].LengthLow +
+ RemoteMemory[Idx].LengthHigh;
+ }
+ }
+
+ FreePool(RemoteMem);
+ }
+
+ MemoryNodeCount =3D FixedPcdGet32 (PcdNumLocalMemBlock);
+
+ MemoryNodeCount +=3D RemoteMemCount;
+ TableSize =3D sizeof (Gicc) +
+ sizeof (SratHeader) +
+ (MemoryNodeCount *
+ sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE));
+
+ Srat =3D AllocatePool (TableSize);
+
+ if (Srat =3D=3D NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to allocate memory for SRAT table\n",
+ __FUNCTION__
+ ));
+
+ FreePool(RemoteMemory);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (
+ Srat,
+ &SratHeader,
+ sizeof (SratHeader)
+ );
+
+ SratDataNext =3D Srat + sizeof (SratHeader);
+ CopyMem (
+ SratDataNext,
+ Gicc,
+ sizeof (Gicc)
+ );
+
+ SratDataNext =3D SratDataNext + sizeof (Gicc);
+ CopyMem (
+ SratDataNext,
+ LocalMemory,
+ sizeof (LocalMemory)
+ );
+
+ SratDataNext =3D ((char *)SratDataNext + sizeof (LocalMemory));
+ if (RemoteMemCount) {
+ CopyMem (
+ SratDataNext,
+ RemoteMemory,
+ sizeof (EFI_ACPI_6_4_MEMORY_AFFINITY_STRUCTURE) *
+ RemoteMemCount
+ );
+ }
+
+ ((EFI_ACPI_DESCRIPTION_HEADER *)Srat)->Length =3D TableSize;
+
+ Status =3D mAcpiTableProtocol->InstallAcpiTable (
+ mAcpiTableProtocol,
+ (EFI_ACPI_6_4_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *)Srat,
+ TableSize,
+ &AcpiTableHandle
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: SRAT table installation failed, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ } else {
+ DEBUG ((DEBUG_INFO, "Installed SRAT table \n"));
+ }
+
+ return Status;
+}
--=20
2.17.1