From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) by mx.groups.io with SMTP id smtpd.web08.11703.1635252895032102907 for ; Tue, 26 Oct 2021 05:54:55 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=HXgjNOEH; spf=pass (domain: nuviainc.com, ip: 209.85.221.43, mailfrom: leif@nuviainc.com) Received: by mail-wr1-f43.google.com with SMTP id e4so19034428wrc.7 for ; Tue, 26 Oct 2021 05:54:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20210112.gappssmtp.com; s=20210112; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=CVowoWbMSxePEE4GaT5UDqiP0T6NbURwX8De94bbCj8=; b=HXgjNOEHBNDoBNwkoSzZfghfAifSV2IXYl+97aiep0sbL7SNusGg3xUbbFh6HJORsD /xtnJNbQxBtWr0SgTpKb86CDQ29Oo5qwgQN19yd7jOvEvjnBB+gXmXjx5A6S3dPIW9ov llm47Jg3evKq+gFfi5OV5sCI5idxF4Oz0puW25ReNWjYL0+KLz98UHJhL6NMcOq8515i swnRBxWP/r0KLabLvenndbF1L/l9F3xgDUmj7tMWYkabDHRd5ldrg6tjMqWmMPo7ezh9 YbT8xEh4h2cxwwe8/jiUBA9Sm/8eIM71MtJtmICG5gY3iHkx8++aE9v942qAgTjdwLmv CCOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=CVowoWbMSxePEE4GaT5UDqiP0T6NbURwX8De94bbCj8=; b=QvQ3mBhO/VN/MRTheqrLqOLF3hEw3DvfVaOMwJbzIhdWJhXB/H3b57ZGrag9wZu2pb 8Xf5neo70c+t2QXxd1ACoam+zB46/SUQgKoik9Iwgbos2xsBcxuf3Cy0kn4UZ96r+0xH P27hZ7uv+QlqJIbWm3i3lquMOj3DeiMeCLbIbP1pZ5DD24m8hVH3oijoJUcur9aImGaJ yWQSTxKcy/ZaejjDQNU/p4Nz/A0OkNFpq0wnlUpTqmh4nB7uLhcKbJhRDG5juQsB1/hS YUfQXNxCBPOt6yYxRbwXPnZ+T9+roaXZ//8lsVFESaAXGtplC2mV6lx4ijmKzAMVHJOt Pd8A== X-Gm-Message-State: AOAM532BHm7WXZnZITt1xQg+O/al5WNzSRDRl17BIDou7Z2jYv/yrTQP HuP1Ttj3p/rN4Dekqi2CR/VQ6g== X-Google-Smtp-Source: ABdhPJw80gVjdm1SMdyNQ7uQ8pAlpcrzfedwWWvi+X9MWMDhGGcAQTfsDg2Ey6V0orA8rLV09RQdkg== X-Received: by 2002:adf:d1e6:: with SMTP id g6mr7195893wrd.33.1635252893561; Tue, 26 Oct 2021 05:54:53 -0700 (PDT) Return-Path: Received: from leviathan (cpc92314-cmbg19-2-0-cust559.5-4.cable.virginm.net. [82.11.186.48]) by smtp.gmail.com with ESMTPSA id d3sm19786556wrb.36.2021.10.26.05.54.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Oct 2021 05:54:53 -0700 (PDT) Date: Tue, 26 Oct 2021 13:54:51 +0100 From: "Leif Lindholm" To: Nhi Pham Cc: devel@edk2.groups.io, patches@amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: Re: [edk2-platforms][PATCH v4 19/31] JadePkg: Add ACPI tables to support PCIe Message-ID: <20211026125451.ft6c2tv6m42ae5a7@leviathan> References: <20211022061809.31087-1-nhi@os.amperecomputing.com> <20211022061809.31087-20-nhi@os.amperecomputing.com> MIME-Version: 1.0 In-Reply-To: <20211022061809.31087-20-nhi@os.amperecomputing.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Oct 22, 2021 at 13:17:57 +0700, Nhi Pham wrote: > From: Vu Nguyen > > 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 > Cc: Chuong Tran > Cc: Phong Vo > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Ard Biesheuvel > Cc: Nate DeSimone > > Signed-off-by: Nhi Pham I haven't sanity-checked anything, but: Acked-by: Leif Lindholm > --- > 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 > #include > #include > #include > @@ -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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +// 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 >