[edk2-devel] [edk2-platforms][PATCH v4 19/31] JadePkg: Add ACPI tables to support PCIe

Leif Lindholm leif at nuviainc.com
Tue Oct 26 12:54:51 UTC 2021


On Fri, Oct 22, 2021 at 13:17:57 +0700, Nhi Pham wrote:
> From: Vu Nguyen <vunguyen at 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 at os.amperecomputing.com>
> Cc: Chuong Tran <chuong at os.amperecomputing.com>
> Cc: Phong Vo <phong at os.amperecomputing.com>
> Cc: Leif Lindholm <leif at nuviainc.com>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> 
> Signed-off-by: Nhi Pham <nhi at os.amperecomputing.com>

I haven't sanity-checked anything, but:
Acked-by: Leif Lindholm <leif at nuviainc.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
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#82692): https://edk2.groups.io/g/devel/message/82692
Mute This Topic: https://groups.io/mt/86507933/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list