public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nhi Pham" <nhi@os.amperecomputing.com>
To: devel@edk2.groups.io
Cc: patches@amperecomputing.com, nhi@os.amperecomputing.com,
	vunguyen@os.amperecomputing.com,
	Thang Nguyen <thang@os.amperecomputing.com>,
	Chuong Tran <chuong@os.amperecomputing.com>,
	Phong Vo <phong@os.amperecomputing.com>,
	Leif Lindholm <leif@nuviainc.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: [edk2-platforms][PATCH v4 19/31] JadePkg: Add ACPI tables to support PCIe
Date: Fri, 22 Oct 2021 13:17:57 +0700	[thread overview]
Message-ID: <20211022061809.31087-20-nhi@os.amperecomputing.com> (raw)
In-Reply-To: <20211022061809.31087-1-nhi@os.amperecomputing.com>

From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Add IORT and MCFG tables to let the OS discover the PCIe resources. This
driver also fixup the DSDT table to adapt with the difference between 1P
and 2P system.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
---
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf |   4 +
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h      |  12 +
 Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h               |  60 ++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c          |  90 +++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiIort.c          | 349 ++++++++++++++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMcfg.c          | 151 +++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c   |  10 +
 7 files changed, 676 insertions(+)

diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
index 72e78fb4e31e..415f795d2a54 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -18,7 +18,9 @@ [Sources.common]
   AcpiApei.c
   AcpiApei.h
   AcpiDsdt.c
+  AcpiIort.c
   AcpiMadt.c
+  AcpiMcfg.c
   AcpiNfit.c
   AcpiPcct.c
   AcpiPlatform.h
@@ -43,6 +45,7 @@ [LibraryClasses]
   BaseLib
   DebugLib
   FlashLib
+  HobLib
   MailboxInterfaceLib
   SystemFirmwareInterfaceLib
   TimerLib
@@ -66,6 +69,7 @@ [Guids]
   gEfiAcpiTableGuid
   gEfiEventReadyToBootGuid
   gPlatformInfoHobGuid
+  gRootComplexInfoHobGuid
 
 [Protocols]
   gEfiAcpiTableProtocolGuid                     ## ALWAYS_CONSUMED
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
index b5035067a47b..170aeff24d59 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
@@ -71,4 +71,16 @@ AcpiInstallSratTable (
   VOID
   );
 
+EFI_STATUS
+EFIAPI
+AcpiInstallMcfg (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+AcpiInstallIort (
+  VOID
+  );
+
 #endif /* ACPI_PLATFORM_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h b/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h
index 132c0d6d6cac..d45688f88401 100644
--- a/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h
@@ -279,4 +279,64 @@
 //
 #define AC01_PCIE_MMIO32_SIZE_1P_LIST    0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x8000000, 0x10000000, 0x10000000, 0x10000000, 0, 0, 0, 0, 0, 0, 0, 0
 
+//
+// DSDT RCA2 PCIe MMIO32 Attribute
+//
+#define AC01_PCIE_RCA2_QMEM_LIST         0x0000000000000000, 0x0000000060000000, 0x000000006FFFFFFF, 0x0000000000000000, 0x0000000010000000
+
+//
+// DSDT RCA3 PCIe MMIO32 Attribute
+//
+#define AC01_PCIE_RCA3_QMEM_LIST         0x0000000000000000, 0x0000000070000000, 0x000000007FFFFFFF, 0x0000000000000000, 0x0000000010000000
+
+//
+// DSDT RCB0 PCIe MMIO32 Attribute
+//
+#define AC01_PCIE_RCB0_QMEM_LIST         0x0000000000000000, 0x0000000001000000, 0x000000000FFFFFFF, 0x0000000000000000, 0x000000000F000000
+
+//
+// DSDT RCB1 PCIe MMIO32 Attribute
+//
+#define AC01_PCIE_RCB1_QMEM_LIST         0x0000000000000000, 0x0000000010000000, 0x000000001FFFFFFF, 0x0000000000000000, 0x0000000010000000
+
+//
+// DSDT RCB2 PCIe MMIO32 Attribute
+//
+#define AC01_PCIE_RCB2_QMEM_LIST         0x0000000000000000, 0x0000000020000000, 0x000000002FFFFFFF, 0x0000000000000000, 0x0000000010000000
+
+//
+// DSDT RCB3 PCIe MMIO32 Attribute
+//
+#define AC01_PCIE_RCB3_QMEM_LIST         0x0000000000000000, 0x0000000030000000, 0x000000003FFFFFFF, 0x0000000000000000, 0x0000000010000000
+
+//
+// TBU PMU IRQ array
+//
+#define AC01_SMMU_TBU_PMU_IRQS_LIST      224, 230, 236, 242, 160, 170, 180, 190, 544, 550, 556, 562, 480, 490, 500, 510
+
+//
+// TCU PMU IRQ array
+//
+#define AC01_SMMU_TCU_PMU_IRQS_LIST      256, 257, 258, 259, 260, 261, 262, 263, 576, 577, 578, 579, 580, 581, 582, 583
+
+//
+// Max TBU PMU of Root Complex A
+//
+#define AC01_RCA_MAX_TBU_PMU             6
+
+//
+// Max TBU PMU of Root Complex B
+//
+#define AC01_RCB_MAX_TBU_PMU             10
+
+//
+// TBU Base offset of Root Complex A
+//
+#define AC01_RCA_TBU_PMU_OFFSET_LIST     0x40000, 0x60000, 0xA0000, 0xE0000, 0x100000, 0x140000
+
+//
+// TBU Base offset of Root Complex B
+//
+#define AC01_RCB_TBU_PMU_OFFSET_LIST     0x40000, 0x60000, 0xA0000, 0xE0000, 0x120000, 0x160000, 0x180000, 0x1C0000, 0x200000, 0x240000
+
 #endif /* PLATFORM_AC01_H_ */
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
index 82bfbb90f07f..885ad8fc3511 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
@@ -6,6 +6,7 @@
 
 **/
 
+#include <Guid/RootComplexInfoHob.h>
 #include <Protocol/PciRootBridgeIo.h>
 #include <Library/NVParamLib.h>
 #include <NVParamDef.h>
@@ -40,6 +41,24 @@ typedef struct {
   OP_REGION_DWORD_DATA  RegionBase;
   OP_REGION_DWORD_DATA  RegionLen;
 } AML_OP_REGION;
+
+typedef struct {
+  UINT64 AddressGranularity;
+  UINT64 AddressMin;
+  UINT64 AddressMax;
+  UINT64 AddressTranslation;
+  UINT64 RangeLength;
+} QWORD_MEMORY;
+
+STATIC QWORD_MEMORY mQMemList[] = {
+  { AC01_PCIE_RCA2_QMEM_LIST },
+  { AC01_PCIE_RCA3_QMEM_LIST },
+  { AC01_PCIE_RCB0_QMEM_LIST },
+  { AC01_PCIE_RCB1_QMEM_LIST },
+  { AC01_PCIE_RCB2_QMEM_LIST },
+  { AC01_PCIE_RCB3_QMEM_LIST }
+};
+
 #pragma pack()
 
 EFI_STATUS
@@ -543,6 +562,76 @@ AcpiPatchPcieAerFwFirst (
   return Status;
 }
 
+VOID
+AcpiPatchPcieMmio32 (
+  EFI_ACPI_SDT_PROTOCOL   *AcpiSdtProtocol,
+  EFI_ACPI_HANDLE         TableHandle
+  )
+{
+  AC01_ROOT_COMPLEX                  *RootComplexList;
+  CHAR8                              *NextDescriptor, *Buffer;
+  CHAR8                              NodePath[256];
+  EFI_ACPI_DATA_TYPE                 DataType;
+  EFI_ACPI_HANDLE                    ObjectHandle;
+  EFI_STATUS                         Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptor;
+  UINTN                              DataSize;
+  UINTN                              Idx;
+  VOID                               *Hob;
+
+  Hob = GetFirstGuidHob (&gRootComplexInfoHobGuid);
+  if (Hob == NULL) {
+    return;
+  }
+
+  RootComplexList = (AC01_ROOT_COMPLEX *)GET_GUID_HOB_DATA (Hob);
+
+  for (Idx = 0; Idx < AC01_PCIE_MAX_ROOT_COMPLEX; Idx++) {
+    if (!RootComplexList[Idx].Active) {
+      //
+      // Patch for disabled Root Complex
+      //
+      AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.PCI%X._STA", Idx);
+      UpdateStatusMethodObject (AcpiSdtProtocol, TableHandle, NodePath, 0x0);
+      continue;
+    }
+
+    if (!IsSlaveSocketActive () && Idx <= SOCKET0_LAST_RC) {
+      //
+      // Patch MMIO32 resource in 1P system
+      //
+      AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.PCI%X.RBUF", Idx);
+      Status = AcpiSdtProtocol->FindPath (TableHandle, NodePath, &ObjectHandle);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      Status = AcpiSdtProtocol->GetOption (ObjectHandle, 2, &DataType, (VOID *)&Buffer, &DataSize);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      if (DataType != EFI_ACPI_DATA_TYPE_CHILD) {
+        AcpiSdtProtocol->Close (ObjectHandle);
+        continue;
+      }
+
+      NextDescriptor = Buffer + 5; // Point to first address space descriptor
+      while ((NextDescriptor - Buffer) < DataSize) {
+        Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)NextDescriptor;
+        if (Descriptor->Desc == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR
+            && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+          CopyMem (&Descriptor->AddrSpaceGranularity, &mQMemList[Idx - 2], sizeof (QWORD_MEMORY));
+          break;
+        }
+        NextDescriptor += (Descriptor->Len + sizeof (ACPI_LARGE_RESOURCE_HEADER));
+      }
+
+      AcpiSdtProtocol->Close (ObjectHandle);
+    }
+  }
+}
+
 EFI_STATUS
 AcpiPatchDsdtTable (
   VOID
@@ -593,6 +682,7 @@ AcpiPatchDsdtTable (
   AcpiPatchNvdimm (AcpiSdtProtocol, TableHandle);
   AcpiPatchPcieNuma (AcpiSdtProtocol, TableHandle);
   AcpiPatchPcieAerFwFirst (AcpiSdtProtocol, TableHandle);
+  AcpiPatchPcieMmio32 (AcpiSdtProtocol, TableHandle);
 
   AcpiSdtProtocol->Close (TableHandle);
   AcpiUpdateChecksum ((UINT8 *)Table, Table->Length);
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiIort.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiIort.c
new file mode 100644
index 000000000000..b8f8cfa356af
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiIort.c
@@ -0,0 +1,349 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <AcpiHeader.h>
+#include <Guid/RootComplexInfoHob.h>
+#include <IndustryStandard/Acpi30.h>
+#include <IndustryStandard/IoRemappingTable.h>
+#include <Library/AcpiLib.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Platform/Ac01.h>
+#include <Protocol/AcpiTable.h>
+
+#define __AC01_ID_MAPPING(In, Num, Out, Ref, Flags)    \
+  {                                                    \
+    In,                                                \
+    Num,                                               \
+    Out,                                               \
+    OFFSET_OF (AC01_IO_REMAPPING_STRUCTURE, Ref),      \
+    Flags                                              \
+  }
+
+#define TCU_TO_SMMU_OFFSET      0x2000
+#define PAGE1_TO_PMCG_OFFSET    0x10000
+
+STATIC AC01_ROOT_COMPLEX *mRootComplexList;
+
+STATIC UINT32 mTbuPmuIrqArray[] = { AC01_SMMU_TBU_PMU_IRQS_LIST };
+STATIC UINT32 mTcuPmuIrqArray[] = { AC01_SMMU_TCU_PMU_IRQS_LIST };
+STATIC UINT64 mRcaTbuPmuOffset[] = { AC01_RCA_TBU_PMU_OFFSET_LIST };
+STATIC UINT64 mRcbTbuPmuOffset[] = { AC01_RCB_TBU_PMU_OFFSET_LIST };
+
+#pragma pack(1)
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_NODE Node;
+  UINT64                         Base;
+  UINT32                         Flags;
+  UINT32                         Reserved;
+  UINT64                         VatosAddress;
+  UINT32                         Model;
+  UINT32                         Event;
+  UINT32                         Pri;
+  UINT32                         Gerr;
+  UINT32                         Sync;
+  UINT32                         ProximityDomain;
+  UINT32                         DeviceIdMapping;
+} EFI_ACPI_6_2_IO_REMAPPING_SMMU3_NODE;
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE Node;
+  UINT32                             ItsIdentifier;
+} AC01_ITS_NODE;
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_RC_NODE  Node;
+  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE RcIdMapping;
+} AC01_RC_NODE;
+
+typedef struct {
+  EFI_ACPI_6_2_IO_REMAPPING_SMMU3_NODE Node;
+  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE   InterruptMsiMapping;
+  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE   InterruptMsiMappingSingle;
+} AC01_SMMU_NODE;
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_TABLE Iort;
+  AC01_ITS_NODE                   ItsNode[2];
+  AC01_RC_NODE                    RcNode[2];
+  AC01_SMMU_NODE                  SmmuNode[2];
+} AC01_IO_REMAPPING_STRUCTURE;
+
+#pragma pack()
+
+EFI_ACPI_6_0_IO_REMAPPING_TABLE mIortHeader = {
+  .Header = __ACPI_HEADER (
+              EFI_ACPI_6_0_IO_REMAPPING_TABLE_SIGNATURE,
+              AC01_IO_REMAPPING_STRUCTURE,
+              EFI_ACPI_IO_REMAPPING_TABLE_REVISION
+              ),
+  .NumNodes = 0,  // To be filled
+  .NodeOffset = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE),
+  0
+};
+
+AC01_ITS_NODE mItsNodeTemplate = {
+  .Node = {
+    {
+      EFI_ACPI_IORT_TYPE_ITS_GROUP,
+      sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE) + 4,
+      0x0,
+      0x0,
+      0x0,
+      0x0,
+    },
+    .NumItsIdentifiers = 1,
+  },
+  .ItsIdentifier = 1,
+};
+
+AC01_RC_NODE mRcNodeTemplate = {
+  {
+    {
+      EFI_ACPI_IORT_TYPE_ROOT_COMPLEX,
+      sizeof (AC01_RC_NODE),
+      0x1,
+      0x0,
+      0x1,
+      OFFSET_OF (AC01_RC_NODE, RcIdMapping),
+    },
+    EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,
+    0x0,
+    0x0,
+    EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM |
+    EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS,
+    EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED,
+    .PciSegmentNumber = 0,
+    .MemoryAddressSize = 64,
+  },
+  __AC01_ID_MAPPING (0x0, 0xffff, 0x0, SmmuNode, 0),
+};
+
+AC01_SMMU_NODE mSmmuNodeTemplate = {
+  {
+    {
+      EFI_ACPI_IORT_TYPE_SMMUv3,
+      sizeof (AC01_SMMU_NODE),
+      0x2,  // Revision
+      0x0,
+      0x2,  // Mapping Count
+      OFFSET_OF (AC01_SMMU_NODE, InterruptMsiMapping),
+    },
+    .Base = 0,
+    EFI_ACPI_IORT_SMMUv3_FLAG_COHAC_OVERRIDE | EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0x0,
+    0x0,
+    0,     // Proximity domain - need fill in
+    .DeviceIdMapping = 1,
+  },
+  __AC01_ID_MAPPING (0x0, 0xffff, 0, SmmuNode, 0),
+  __AC01_ID_MAPPING (0x0, 0x1, 0, SmmuNode, 1),
+};
+
+EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE mPmcgNodeTemplate = {
+  {
+    EFI_ACPI_IORT_TYPE_PMCG,
+    sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE),
+    0x1,
+    0x0,
+    0x0,
+    0x0,
+  },
+  0,  // Page 0 Base. Need to be filled
+  0,  // GSIV. Need to be filled
+  0,  // Node reference. Need to be filled
+  0,  // Page 1 Base. Need to be filled
+};
+
+STATIC
+VOID
+ConstructIort (
+  VOID   *IortBuffer,
+  UINT32 RcCount,
+  UINT32 SmmuPmuAgentCount,
+  UINT32 HeaderCount,
+  INT32  *EnabledRCs
+  )
+{
+  AC01_ROOT_COMPLEX *RootComplex;
+  UINT32            Idx, Idx1;
+  UINT32            ItsOffset[AC01_PCIE_MAX_ROOT_COMPLEX];
+  UINT32            SmmuNodeOffset[AC01_PCIE_MAX_ROOT_COMPLEX];
+  UINT64            *TbuPmuOffset;
+  UINTN             MaxTbuPmu;
+  VOID              *IortIter, *SmmuIter, *PmcgIter;
+
+  IortIter = IortBuffer;
+  mIortHeader.Header.Length = HeaderCount;
+  mIortHeader.NumNodes = (3 * RcCount) + SmmuPmuAgentCount,
+  CopyMem (IortIter, &mIortHeader, sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE));
+
+  IortIter += sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);
+  for (Idx = 0; Idx < RcCount; Idx++) {
+    ItsOffset[Idx] = IortIter - IortBuffer;
+    mItsNodeTemplate.ItsIdentifier = EnabledRCs[Idx];
+    CopyMem (IortIter, &mItsNodeTemplate, sizeof (AC01_ITS_NODE));
+    IortIter += sizeof (AC01_ITS_NODE);
+  }
+
+  SmmuIter = IortIter + RcCount * sizeof (AC01_RC_NODE);
+  PmcgIter = SmmuIter + RcCount * sizeof (AC01_SMMU_NODE);
+  for (Idx = 0; Idx < RcCount; Idx++) {
+    SmmuNodeOffset[Idx] = SmmuIter - IortBuffer;
+    RootComplex = &mRootComplexList[EnabledRCs[Idx]];
+    mSmmuNodeTemplate.Node.Base = RootComplex->TcuBase;
+    mSmmuNodeTemplate.InterruptMsiMapping.OutputBase = EnabledRCs[Idx] << 16;
+    mSmmuNodeTemplate.InterruptMsiMapping.OutputReference = ItsOffset[Idx];
+    mSmmuNodeTemplate.InterruptMsiMappingSingle.OutputBase = EnabledRCs[Idx] << 16;
+    mSmmuNodeTemplate.InterruptMsiMappingSingle.OutputReference = ItsOffset[Idx];
+    /* All RCs on master be assigned to node 0, while remote RCs will be assigned to first remote node */
+    mSmmuNodeTemplate.Node.ProximityDomain = 0;
+    if ((RootComplex->TcuBase & SLAVE_SOCKET_BASE_ADDRESS_OFFSET) != 0) {
+      // RootComplex on remote socket
+      switch (CpuGetSubNumaMode ()) {
+      case SUBNUMA_MODE_MONOLITHIC:
+        mSmmuNodeTemplate.Node.ProximityDomain += MONOLITIC_NUM_OF_REGION;
+        break;
+      case SUBNUMA_MODE_HEMISPHERE:
+        mSmmuNodeTemplate.Node.ProximityDomain += HEMISPHERE_NUM_OF_REGION;
+        break;
+      case SUBNUMA_MODE_QUADRANT:
+        mSmmuNodeTemplate.Node.ProximityDomain += QUADRANT_NUM_OF_REGION;
+        break;
+      }
+    }
+    CopyMem (SmmuIter, &mSmmuNodeTemplate, sizeof (AC01_SMMU_NODE));
+    SmmuIter += sizeof (AC01_SMMU_NODE);
+
+    if (SmmuPmuAgentCount == 0) {
+      continue;
+    }
+
+    //
+    // Add TBU PMCG nodes
+    //
+    if (RootComplex->Type == RootComplexTypeA) {
+      MaxTbuPmu = AC01_RCA_MAX_TBU_PMU;
+      TbuPmuOffset = mRcaTbuPmuOffset;
+    } else {
+      MaxTbuPmu = AC01_RCB_MAX_TBU_PMU;
+      TbuPmuOffset = mRcbTbuPmuOffset;
+    }
+
+    for (Idx1 = 0; Idx1 < MaxTbuPmu; Idx1++) {
+      mPmcgNodeTemplate.Base = RootComplex->TcuBase + TCU_TO_SMMU_OFFSET + TbuPmuOffset[Idx1];
+      mPmcgNodeTemplate.Page1Base = mPmcgNodeTemplate.Base + PAGE1_TO_PMCG_OFFSET;
+      mPmcgNodeTemplate.NodeReference = SmmuNodeOffset[Idx];
+      mPmcgNodeTemplate.OverflowInterruptGsiv = mTbuPmuIrqArray[EnabledRCs[Idx]] + Idx1;
+      CopyMem (PmcgIter, &mPmcgNodeTemplate, sizeof (mPmcgNodeTemplate));
+      PmcgIter += sizeof (mPmcgNodeTemplate);
+    }
+
+    //
+    // Add TCU PMCG node
+    //
+    mPmcgNodeTemplate.Base = RootComplex->TcuBase + TCU_TO_SMMU_OFFSET;
+    mPmcgNodeTemplate.Page1Base = mPmcgNodeTemplate.Base + PAGE1_TO_PMCG_OFFSET;
+    mPmcgNodeTemplate.NodeReference = SmmuNodeOffset[Idx];
+    mPmcgNodeTemplate.OverflowInterruptGsiv = mTcuPmuIrqArray[EnabledRCs[Idx]];
+    CopyMem (PmcgIter, &mPmcgNodeTemplate, sizeof (mPmcgNodeTemplate));
+    PmcgIter += sizeof (mPmcgNodeTemplate);
+  }
+
+  for (Idx = 0; Idx < RcCount; Idx++) {
+    mRcNodeTemplate.Node.PciSegmentNumber = mRootComplexList[EnabledRCs[Idx]].Logical;
+    mRcNodeTemplate.RcIdMapping.OutputReference = SmmuNodeOffset[Idx];
+    CopyMem (IortIter, &mRcNodeTemplate, sizeof (AC01_RC_NODE));
+    IortIter += sizeof (AC01_RC_NODE);
+  }
+}
+
+EFI_STATUS
+EFIAPI
+AcpiInstallIort (
+  VOID
+  )
+{
+  EFI_ACPI_TABLE_PROTOCOL           *AcpiTableProtocol;
+  EFI_STATUS                        Status;
+  INT32                             EnabledRCs[AC01_PCIE_MAX_ROOT_COMPLEX];
+  UINT32                            RcCount, SmmuPmuAgentCount, TotalCount;
+  UINT8                             Idx;
+  UINTN                             TableKey;
+  VOID                              *Hob;
+  VOID                              *IortBuffer;
+
+  Hob = GetFirstGuidHob (&gRootComplexInfoHobGuid);
+  if (Hob == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  mRootComplexList = (AC01_ROOT_COMPLEX *)GET_GUID_HOB_DATA (Hob);
+
+  for (Idx = 0, RcCount = 0; Idx < AC01_PCIE_MAX_ROOT_COMPLEX; Idx++) {
+    if (mRootComplexList[Idx].Active) {
+      EnabledRCs[RcCount++] = Idx;
+    }
+  }
+  EnabledRCs[RcCount] = -1;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID **)&AcpiTableProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "IORT: Unable to locate ACPI table entry\n"));
+    return Status;
+  }
+
+  SmmuPmuAgentCount = 0;
+  for (Idx = 0; Idx < RcCount; Idx++) {
+    if (mRootComplexList[EnabledRCs[Idx]].Type == RootComplexTypeA) {
+      SmmuPmuAgentCount += AC01_RCA_MAX_TBU_PMU;
+    } else {
+      SmmuPmuAgentCount += AC01_RCB_MAX_TBU_PMU;
+    }
+    // Plus 1 TCU
+    SmmuPmuAgentCount += 1;
+  }
+
+  TotalCount = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE) +
+               RcCount * (sizeof (AC01_ITS_NODE) + sizeof (AC01_RC_NODE) + sizeof (AC01_SMMU_NODE)) +
+               SmmuPmuAgentCount * sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE);
+
+  IortBuffer = AllocateZeroPool (TotalCount);
+  if (IortBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ConstructIort (IortBuffer, RcCount, SmmuPmuAgentCount, TotalCount, EnabledRCs);
+
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                                AcpiTableProtocol,
+                                IortBuffer,
+                                TotalCount,
+                                &TableKey
+                                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "IORT: Unable to install IORT table entry\n"));
+  }
+
+  FreePool (IortBuffer);
+  return Status;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMcfg.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMcfg.c
new file mode 100644
index 000000000000..0b04246f06fa
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMcfg.c
@@ -0,0 +1,151 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <AcpiHeader.h>
+#include <Guid/RootComplexInfoHob.h>
+#include <IndustryStandard/Acpi30.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Platform/Ac01.h>
+#include <Protocol/AcpiTable.h>
+
+// Required to be 1 to match the kernel quirk for ECAM
+#define EFI_ACPI_MCFG_OEM_REVISION 1
+
+STATIC AC01_ROOT_COMPLEX *mRootComplexList;
+
+#pragma pack(1)
+
+typedef struct
+{
+  UINT64 BaseAddress;
+  UINT16 SegGroupNum;
+  UINT8  StartBusNum;
+  UINT8  EndBusNum;
+  UINT32 Reserved2;
+} EFI_MCFG_CONFIG_STRUCTURE;
+
+typedef struct
+{
+  EFI_ACPI_DESCRIPTION_HEADER Header;
+  UINT64                      Reserved1;
+} EFI_MCFG_TABLE_CONFIG;
+
+#pragma pack()
+
+EFI_MCFG_TABLE_CONFIG     mMcfgHeader = {
+  {
+    EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+    0,  // To be filled
+    1,
+    0x00,  // Checksum will be updated at runtime
+    EFI_ACPI_OEM_ID,
+    EFI_ACPI_OEM_TABLE_ID,
+    EFI_ACPI_MCFG_OEM_REVISION,
+    EFI_ACPI_CREATOR_ID,
+    EFI_ACPI_CREATOR_REVISION
+  },
+  0x0000000000000000,  // Reserved
+};
+
+EFI_MCFG_CONFIG_STRUCTURE mMcfgNodeTemplate = {
+  .BaseAddress = 0,
+  .SegGroupNum = 0,
+  .StartBusNum = 0,
+  .EndBusNum = 255,
+  .Reserved2 = 0,
+};
+
+STATIC
+VOID
+ConstructMcfg (
+  VOID   *McfgBuffer,
+  UINT32 McfgCount,
+  INT32  *EnabledRCs
+  )
+{
+  AC01_ROOT_COMPLEX         *RootComplex;
+  UINT32                    Idx;
+  VOID                      *Iter = McfgBuffer;
+
+  mMcfgHeader.Header.Length = McfgCount;
+  CopyMem (Iter, &mMcfgHeader, sizeof (EFI_MCFG_TABLE_CONFIG));
+
+  Iter += sizeof (EFI_MCFG_TABLE_CONFIG);
+  for (Idx = 0; EnabledRCs[Idx] != -1; Idx++) {
+    RootComplex = &mRootComplexList[EnabledRCs[Idx]];
+    mMcfgNodeTemplate.BaseAddress = RootComplex->MmcfgBase;
+    mMcfgNodeTemplate.SegGroupNum = RootComplex->Logical;
+    CopyMem (Iter, &mMcfgNodeTemplate, sizeof (EFI_MCFG_CONFIG_STRUCTURE));
+    Iter += sizeof (EFI_MCFG_CONFIG_STRUCTURE);
+  }
+}
+
+EFI_STATUS
+EFIAPI
+AcpiInstallMcfg (
+  VOID
+  )
+{
+  EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
+  EFI_STATUS              Status;
+  INT32                   EnabledRCs[AC01_PCIE_MAX_ROOT_COMPLEX];
+  UINT32                  RcCount, McfgCount;
+  UINT8                   Idx;
+  UINTN                   TableKey;
+  VOID                    *Hob;
+  VOID                    *McfgBuffer;
+
+  Hob = GetFirstGuidHob (&gRootComplexInfoHobGuid);
+  if (Hob == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  mRootComplexList = (AC01_ROOT_COMPLEX *)GET_GUID_HOB_DATA (Hob);
+
+  for (Idx = 0, RcCount = 0; Idx < AC01_PCIE_MAX_ROOT_COMPLEX; Idx++) {
+    if (mRootComplexList[Idx].Active) {
+      EnabledRCs[RcCount++] = Idx;
+    }
+  }
+  EnabledRCs[RcCount] = -1;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID **)&AcpiTableProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "MCFG: Unable to locate ACPI table entry\n"));
+    return Status;
+  }
+
+  McfgCount = sizeof (EFI_MCFG_TABLE_CONFIG) + sizeof (EFI_MCFG_CONFIG_STRUCTURE) * RcCount;
+  McfgBuffer = AllocateZeroPool (McfgCount);
+  if (McfgBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ConstructMcfg (McfgBuffer, McfgCount, EnabledRCs);
+
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                                AcpiTableProtocol,
+                                McfgBuffer,
+                                McfgCount,
+                                &TableKey
+                                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "MCFG: Unable to install MCFG table entry\n"));
+  }
+  FreePool (McfgBuffer);
+  return Status;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
index c4022eb056e0..117f3872a84a 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
@@ -93,6 +93,16 @@ InstallAcpiOnReadyToBoot (
     DEBUG ((DEBUG_INFO, "Installed NFIT table\n"));
   }
 
+  Status = AcpiInstallIort ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed IORT table\n"));
+  }
+
+  Status = AcpiInstallMcfg ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed MCFG table\n"));
+  }
+
   Status = AcpiPopulateBert ();
   if (!EFI_ERROR (Status)) {
     DEBUG ((DEBUG_INFO, "Populate BERT record\n"));
-- 
2.17.1


  parent reply	other threads:[~2021-10-22  6:20 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-22  6:17 [edk2-platforms][PATCH v4 00/31] Add new Ampere Mt. Jade platform Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 01/31] Ampere: Initial support for Ampere Altra processor and " Nhi Pham
2021-10-26 11:14   ` Leif Lindholm
2021-11-03  9:31     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 02/31] AmpereAltraPkg: Add FlashLib library instance Nhi Pham
2021-10-26 11:25   ` Leif Lindholm
2021-11-03  9:32     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 03/31] AmpereAltraPkg: Add FailSafe and WDT support Nhi Pham
2021-10-26 12:15   ` Leif Lindholm
2021-11-03  9:35     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 04/31] AmpereAltraPkg: Add DwI2cLib library instance Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 05/31] AmpereAltraPkg: Add DwGpioLib " Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 06/31] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 07/31] AmpereAltraPkg: Add BootProgress support Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 08/31] AmpereAltraPkg: Support UEFI non-volatile variable Nhi Pham
2021-10-26 12:21   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 09/31] AmpereSiliconPkg: Add PlatformManagerUiLib library instance Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 10/31] AmpereAltraPkg, JadePkg: Add ACPI support Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 11/31] AmpereAltraPkg: Add Root Complex HOB data structures Nhi Pham
2021-10-26 12:23   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 12/31] AmpereAltraPkg: Add Ac01PcieLib library instance Nhi Pham
2021-10-26 12:45   ` Leif Lindholm
2021-11-03  9:33     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 13/31] JadePkg: Add BoardPcieLib " Nhi Pham
2021-10-26 12:46   ` Leif Lindholm
2021-11-03  9:33     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 14/31] AmpereAltraPkg: Add driver to initialize PCIe Root Complex Nhi Pham
2021-10-26 12:49   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 15/31] AmpereAltraPkg: Add PciHostBridgeLib library instance Nhi Pham
2021-10-26 12:49   ` Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 16/31] AmpereAltraPkg: Add PciSegmentLib " Nhi Pham
2021-10-26 12:53   ` Leif Lindholm
2021-11-03  9:35     ` Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 17/31] JadePkg: Enable PciHostBridgeDxe driver Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 18/31] JadePkg: Add PciPlatformDxe driver Nhi Pham
2021-10-22  6:17 ` Nhi Pham [this message]
2021-10-26 12:54   ` [edk2-platforms][PATCH v4 19/31] JadePkg: Add ACPI tables to support PCIe Leif Lindholm
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 20/31] JadePkg: Add ASpeed GOP driver Nhi Pham
2021-10-22  6:17 ` [edk2-platforms][PATCH v4 21/31] AmpereAltraPkg: Add Random Number Generator Support Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 22/31] JadePkg: Add SMBIOS tables support Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 23/31] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 24/31] AmpereAltraPkg: Add configuration screen for PCIe Nhi Pham
2021-10-26 12:56   ` Leif Lindholm
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 25/31] Ampere: Utilize the PCIe User setting Nhi Pham
2021-10-26 12:57   ` Leif Lindholm
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 26/31] AmpereAltraPkg: Add platform info screen Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 27/31] AmpereAltraPkg: Add configuration screen for Memory Nhi Pham
2021-10-26 12:58   ` Leif Lindholm
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 28/31] AmpereAltraPkg: Add configuration screen for CPU Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 29/31] AmpereAltraPkg: Add configuration screen for ACPI Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 30/31] AmpereAltraPkg: Add configuration screen for RAS Nhi Pham
2021-10-22  6:18 ` [edk2-platforms][PATCH v4 31/31] AmpereAltraPkg: Add configuration screen for Watchdog timer Nhi Pham
2021-10-26 13:03   ` Leif Lindholm
2021-11-03  9:36     ` Nhi Pham
2021-10-26 13:08 ` [edk2-platforms][PATCH v4 00/31] Add new Ampere Mt. Jade platform Leif Lindholm
2021-11-03  9:37   ` Nhi Pham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211022061809.31087-20-nhi@os.amperecomputing.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox