[Linaro-uefi] Platforms/AMD/Styx: enable SMMUs in the ACPI IORT table

Message ID 20170413164904.2733-1-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel April 13, 2017, 4:49 p.m.
Due to the fact that AMD Seattle maps all its DRAM starting at
physical address 0x80_0000_0000, we currently only support DMA for
devices that can access 40 bits of physical address space.

This is not a problem for the onboard devices, but it would be useful
if we could support random PCIe plug-in cards, even if they are only
32-bit DMA capable.

Fortunately, there is a ARM (tm) Corelink(r) MMU-401 between the PCIe
root complex and the CPU bus, and so all we need to do is to inform
the OS about this. So add a description of it to the APCI IORT table.

While we're at it, let's describe all the other SMMUs we may be able to
make use of, i.e., 2x SATA and 2x XGBE, as well.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 Platforms/AMD/Styx/AcpiTables/AcpiTables.inf              |   1 +
 Platforms/AMD/Styx/AcpiTables/Iort.c                      | 301 ++++++++++++++++++++
 Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h                |   1 +
 Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c |   1 +
 4 files changed, 304 insertions(+)

Comments

Leif Lindholm April 13, 2017, 6:43 p.m. | #1
On Thu, Apr 13, 2017 at 05:49:04PM +0100, Ard Biesheuvel wrote:
> Due to the fact that AMD Seattle maps all its DRAM starting at
> physical address 0x80_0000_0000, we currently only support DMA for
> devices that can access 40 bits of physical address space.
> 
> This is not a problem for the onboard devices, but it would be useful
> if we could support random PCIe plug-in cards, even if they are only
> 32-bit DMA capable.
> 
> Fortunately, there is a ARM (tm) Corelink(r) MMU-401 between the PCIe
> root complex and the CPU bus, and so all we need to do is to inform
> the OS about this. So add a description of it to the APCI IORT table.
> 
> While we're at it, let's describe all the other SMMUs we may be able to
> make use of, i.e., 2x SATA and 2x XGBE, as well.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Looks sensible to me. If you get a nod from Graeme:
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

> ---
>  Platforms/AMD/Styx/AcpiTables/AcpiTables.inf              |   1 +
>  Platforms/AMD/Styx/AcpiTables/Iort.c                      | 301 ++++++++++++++++++++
>  Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h                |   1 +
>  Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c |   1 +
>  4 files changed, 304 insertions(+)
> 
> diff --git a/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf b/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf
> index 12e0444009ef..3615d7fc0279 100644
> --- a/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf
> +++ b/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf
> @@ -37,6 +37,7 @@
>    Mcfg.c
>    Csrt.c
>    Dsdt.c
> +  Iort.c
>  
>  [Packages]
>    ArmPkg/ArmPkg.dec
> diff --git a/Platforms/AMD/Styx/AcpiTables/Iort.c b/Platforms/AMD/Styx/AcpiTables/Iort.c
> new file mode 100644
> index 000000000000..408149d59db9
> --- /dev/null
> +++ b/Platforms/AMD/Styx/AcpiTables/Iort.c
> @@ -0,0 +1,301 @@
> +/** @file
> +
> +  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <AmdStyxAcpiLib.h>
> +#include <IndustryStandard/IoRemappingTable.h>
> +
> +#define FIELD_OFFSET(type, name)            __builtin_offsetof(type, name)
> +
> +#define STYX_PCIE_SMMU_BASE                 0xE0A00000
> +#define STYX_PCIE_SMMU_SIZE                 0x10000
> +#define STYX_PCIE_SMMU_INTERRUPT            0x16d
> +
> +#define STYX_ETH0_SMMU_BASE                 0xE0600000
> +#define STYX_ETH0_SMMU_SIZE                 0x10000
> +#define STYX_ETH0_SMMU_INTERRUPT            0x170
> +
> +#define STYX_ETH1_SMMU_BASE                 0xE0800000
> +#define STYX_ETH1_SMMU_SIZE                 0x10000
> +#define STYX_ETH1_SMMU_INTERRUPT            0x16f
> +
> +#define STYX_SATA0_SMMU_BASE                0xE0200000
> +#define STYX_SATA0_SMMU_SIZE                0x10000
> +#define STYX_SATA0_SMMU_INTERRUPT           0x16c
> +
> +#define STYX_SATA1_SMMU_BASE                0xE0C00000
> +#define STYX_SATA1_SMMU_SIZE                0x10000
> +#define STYX_SATA1_SMMU_INTERRUPT           0x16b
> +
> +#pragma pack(1)
> +typedef struct {
> +  EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE       Node;
> +  EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT        Context[1];
> +} STYX_SMMU_NODE;
> +
> +typedef struct {
> +  EFI_ACPI_6_0_IO_REMAPPING_RC_NODE         Node;
> +  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE        RcIdMapping[1];
> +} STYX_RC_NODE;
> +
> +typedef struct {
> +  EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE Node;
> +  CONST CHAR8                               Name[11];
> +  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE        RcIdMapping[16];
> +} STYX_NC_NODE;
> +
> +typedef struct {
> +  EFI_ACPI_6_0_IO_REMAPPING_TABLE           Iort;
> +  STYX_SMMU_NODE                            PciSmmuNode;
> +  STYX_RC_NODE                              PciRcNode;
> +
> +#if DO_XGBE
> +  STYX_SMMU_NODE                            Eth0SmmuNode;
> +  STYX_NC_NODE                              Eth0NamedNode;
> +  STYX_SMMU_NODE                            Eth1SmmuNode;
> +  STYX_NC_NODE                              Eth1NamedNode;
> +#endif
> +
> +  STYX_SMMU_NODE                            Sata0SmmuNode;
> +  STYX_NC_NODE                              Sata0NamedNode;
> +  STYX_SMMU_NODE                            Sata1SmmuNode;
> +  STYX_NC_NODE                              Sata1NamedNode;
> +} STYX_IO_REMAPPING_STRUCTURE;
> +
> +#define __STYX_SMMU_NODE(Base, Size, Irq)                   \
> +  {                                                         \
> +    {                                                       \
> +      EFI_ACPI_IORT_TYPE_SMMUv1v2,                          \
> +      sizeof(STYX_SMMU_NODE),                               \
> +      0x0,                                                  \
> +      0x0,                                                  \
> +      0x0,                                                  \
> +      0x0,                                                  \
> +    },                                                      \
> +    Base,                                                   \
> +    Size,                                                   \
> +    EFI_ACPI_IORT_SMMUv1v2_MODEL_v1,                        \
> +    EFI_ACPI_IORT_SMMUv1v2_FLAG_COH_WALK,                   \
> +    FIELD_OFFSET(EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE,       \
> +                 SMMU_NSgIrpt),                             \
> +    0x1,                                                    \
> +    sizeof(EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE),            \
> +    0x0,                                                    \
> +    0x0,                                                    \
> +    Irq,                                                    \
> +    EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_LEVEL,                  \
> +    0x0,                                                    \
> +    0x0,                                                    \
> +  }, {                                                      \
> +    {                                                       \
> +      Irq,                                                  \
> +      EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_LEVEL,                \
> +    },                                                      \
> +  }
> +
> +#define __STYX_ID_MAPPING(In, Num, Out, Flags, Ref)         \
> +  {                                                         \
> +    In,                                                     \
> +    Num,                                                    \
> +    Out,                                                    \
> +    FIELD_OFFSET(STYX_IO_REMAPPING_STRUCTURE, Ref),         \
> +    Flags                                                   \
> +  }
> +
> +#define __STYX_NAMED_COMPONENT_NODE(Name)                   \
> +    {                                                       \
> +      {                                                     \
> +        EFI_ACPI_IORT_TYPE_NAMED_COMP,                      \
> +        sizeof(STYX_NC_NODE),                               \
> +        0x0,                                                \
> +        0x0,                                                \
> +        0x10,                                               \
> +        FIELD_OFFSET(STYX_NC_NODE, RcIdMapping),            \
> +      },                                                    \
> +      0x0,                                                  \
> +      EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,                    \
> +      0x0,                                                  \
> +      0x0,                                                  \
> +      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM |                  \
> +      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS,                  \
> +      40,                                                   \
> +    },                                                      \
> +    Name
> +
> +STATIC STYX_IO_REMAPPING_STRUCTURE AcpiIort = {
> +  {
> +    AMD_ACPI_HEADER(EFI_ACPI_6_0_IO_REMAPPING_TABLE_SIGNATURE,
> +                    STYX_IO_REMAPPING_STRUCTURE,
> +                    EFI_ACPI_IO_REMAPPING_TABLE_REVISION),
> +#if DO_XGBE
> +    10,                                             // NumNodes
> +#else
> +    6,                                              // NumNodes
> +#endif
> +    sizeof(EFI_ACPI_6_0_IO_REMAPPING_TABLE),        // NodeOffset
> +    0                                               // Reserved
> +  }, {
> +    // PciSmmuNode
> +    __STYX_SMMU_NODE(STYX_PCIE_SMMU_BASE,
> +                     STYX_PCIE_SMMU_SIZE,
> +                     STYX_PCIE_SMMU_INTERRUPT)
> +  }, {
> +    // PciRcNode
> +    {
> +      {
> +        EFI_ACPI_IORT_TYPE_ROOT_COMPLEX,                    // Type
> +        sizeof(STYX_RC_NODE),                               // Length
> +        0x0,                                                // Revision
> +        0x0,                                                // Reserved
> +        0x1,                                                // NumIdMappings
> +        FIELD_OFFSET(STYX_RC_NODE, RcIdMapping),            // IdReference
> +      },
> +      EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,                    // CacheCoherent
> +      0x0,                                                  // AllocationHints
> +      0x0,                                                  // Reserved
> +      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM |
> +      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS,                  // MemoryAccessFlags
> +      EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED,           // AtsAttribute
> +      0x0,                                                  // PciSegmentNumber
> +    }, {
> +      __STYX_ID_MAPPING(0x0, 0xffff, 0x0, 0x0, PciSmmuNode),
> +    }
> +#if DO_XGBE
> +  }, {
> +    // Eth0SmmuNode
> +    __STYX_SMMU_NODE(STYX_ETH0_SMMU_BASE,
> +                     STYX_ETH0_SMMU_SIZE,
> +                     STYX_ETH0_SMMU_INTERRUPT)
> +  }, {
> +    // Eth0NamedNode
> +    __STYX_NAMED_COMPONENT_NODE("\\_SB_.ETH0"),
> +    {
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
> +    }
> +  }, {
> +    // Eth1SmmuNode
> +    __STYX_SMMU_NODE(STYX_ETH1_SMMU_BASE,
> +                     STYX_ETH1_SMMU_SIZE,
> +                     STYX_ETH1_SMMU_INTERRUPT)
> +  }, {
> +    // Eth1NamedNode
> +    __STYX_NAMED_COMPONENT_NODE("\\_SB_.ETH1"),
> +    {
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
> +    }
> +#endif
> +  }, {
> +    // Sata0SmmuNode
> +    __STYX_SMMU_NODE(STYX_SATA0_SMMU_BASE,
> +                     STYX_SATA0_SMMU_SIZE,
> +                     STYX_SATA0_SMMU_INTERRUPT)
> +  }, {
> +    // Sata0NamedNode
> +    __STYX_NAMED_COMPONENT_NODE("\\_SB_.AHC0"),
> +    {
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
> +    }
> +  }, {
> +    // Sata1SmmuNode
> +    __STYX_SMMU_NODE(STYX_SATA1_SMMU_BASE,
> +                     STYX_SATA1_SMMU_SIZE,
> +                     STYX_SATA1_SMMU_INTERRUPT)
> +  }, {
> +    // Sata1NamedNode
> +    __STYX_NAMED_COMPONENT_NODE("\\_SB_.AHC1"),
> +    {
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
> +    }
> +  }
> +};
> +
> +#pragma pack()
> +
> +#define STYX_SOC_VERSION_MASK    0xFFF
> +#define STYX_SOC_VERSION_A0      0x000
> +#define STYX_SOC_VERSION_B0      0x010
> +#define STYX_SOC_VERSION_B1      0x011
> +
> +EFI_ACPI_DESCRIPTION_HEADER *
> +IortHeader (
> +  VOID
> +  )
> +{
> +  if (FixedPcdGet8 (PcdSata1PortCount) == 0 ||
> +      (PcdGet32 (PcdSocCpuId) & STYX_SOC_VERSION_MASK) < STYX_SOC_VERSION_B1) {
> +
> +    // ignore the last two nodes if Sata1 is not enabled
> +    AcpiIort.Iort.NumNodes -= 2;
> +  }
> +  return (EFI_ACPI_DESCRIPTION_HEADER *) &AcpiIort.Iort.Header;
> +}
> diff --git a/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h b/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h
> index 698a5d3f90f8..9438b8b0c27e 100644
> --- a/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h
> +++ b/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h
> @@ -27,6 +27,7 @@ EFI_ACPI_DESCRIPTION_HEADER *McfgHeader (void);
>  EFI_ACPI_DESCRIPTION_HEADER *Dbg2Header (void);
>  EFI_ACPI_DESCRIPTION_HEADER *SpcrHeader (void);
>  EFI_ACPI_DESCRIPTION_HEADER *CsrtHeader (void);
> +EFI_ACPI_DESCRIPTION_HEADER *IortHeader (void);
>  
>  #define EFI_ACPI_AMD_OEM_ID_ARRAY        {'A','M','D','I','N','C'}
>  #define EFI_ACPI_AMD_OEM_TABLE_ID        SIGNATURE_64('S','E','A','T','T','L','E',' ')
> diff --git a/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c b/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
> index 1bad597a8eaa..8efb5ccfd8b7 100644
> --- a/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
> +++ b/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
> @@ -65,6 +65,7 @@ AcpiPlatformEntryPoint (
>    AcpiTableList[TableIndex++] = SpcrHeader();
>    AcpiTableList[TableIndex++] = McfgHeader();
>    AcpiTableList[TableIndex++] = CsrtHeader();
> +  AcpiTableList[TableIndex++] = IortHeader();
>    AcpiTableList[TableIndex++] = NULL;
>  
>    DEBUG((DEBUG_INFO, "%a(): ACPI Table installer\n", __FUNCTION__));
> -- 
> 2.9.3
>
Ard Biesheuvel April 14, 2017, 12:23 p.m. | #2
On 13 April 2017 at 19:43, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Thu, Apr 13, 2017 at 05:49:04PM +0100, Ard Biesheuvel wrote:
>> Due to the fact that AMD Seattle maps all its DRAM starting at
>> physical address 0x80_0000_0000, we currently only support DMA for
>> devices that can access 40 bits of physical address space.
>>
>> This is not a problem for the onboard devices, but it would be useful
>> if we could support random PCIe plug-in cards, even if they are only
>> 32-bit DMA capable.
>>
>> Fortunately, there is a ARM (tm) Corelink(r) MMU-401 between the PCIe
>> root complex and the CPU bus, and so all we need to do is to inform
>> the OS about this. So add a description of it to the APCI IORT table.
>>
>> While we're at it, let's describe all the other SMMUs we may be able to
>> make use of, i.e., 2x SATA and 2x XGBE, as well.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> Looks sensible to me. If you get a nod from Graeme:
> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
>

Thanks. But as it turns out, i will need to respin it since the SMMU
config of the B1 silicon deviates from B0. I tested it on Cello while
under the assumption that it is B1 silicon, but it turns out to be B0,
and on my B1 overdrive, only the PCIe SMMU works (which is arguably
the most important one anyway)

At the same time, there is no reason for DT to deviate from ACPI in
this respect, so I will spin a v2 that addresses both these points.
Graeme Gregory April 14, 2017, 4:52 p.m. | #3
On Fri, Apr 14, 2017 at 01:23:25PM +0100, Ard Biesheuvel wrote:
> On 13 April 2017 at 19:43, Leif Lindholm <leif.lindholm@linaro.org> wrote:

> > On Thu, Apr 13, 2017 at 05:49:04PM +0100, Ard Biesheuvel wrote:

> >> Due to the fact that AMD Seattle maps all its DRAM starting at

> >> physical address 0x80_0000_0000, we currently only support DMA for

> >> devices that can access 40 bits of physical address space.

> >>

> >> This is not a problem for the onboard devices, but it would be useful

> >> if we could support random PCIe plug-in cards, even if they are only

> >> 32-bit DMA capable.

> >>

> >> Fortunately, there is a ARM (tm) Corelink(r) MMU-401 between the PCIe

> >> root complex and the CPU bus, and so all we need to do is to inform

> >> the OS about this. So add a description of it to the APCI IORT table.

> >>

> >> While we're at it, let's describe all the other SMMUs we may be able to

> >> make use of, i.e., 2x SATA and 2x XGBE, as well.

> >>

> >> Contributed-under: TianoCore Contribution Agreement 1.0

> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> >

> > Looks sensible to me. If you get a nod from Graeme:

> > Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

> >

> 

> Thanks. But as it turns out, i will need to respin it since the SMMU

> config of the B1 silicon deviates from B0. I tested it on Cello while

> under the assumption that it is B1 silicon, but it turns out to be B0,

> and on my B1 overdrive, only the PCIe SMMU works (which is arguably

> the most important one anyway)

> 

That might explain why when I asked AMD to add this they were not
interested. But yes would be good to get the SMMU's turned on if they
work.

Graeme

Patch hide | download patch | download mbox

diff --git a/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf b/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf
index 12e0444009ef..3615d7fc0279 100644
--- a/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf
+++ b/Platforms/AMD/Styx/AcpiTables/AcpiTables.inf
@@ -37,6 +37,7 @@ 
   Mcfg.c
   Csrt.c
   Dsdt.c
+  Iort.c
 
 [Packages]
   ArmPkg/ArmPkg.dec
diff --git a/Platforms/AMD/Styx/AcpiTables/Iort.c b/Platforms/AMD/Styx/AcpiTables/Iort.c
new file mode 100644
index 000000000000..408149d59db9
--- /dev/null
+++ b/Platforms/AMD/Styx/AcpiTables/Iort.c
@@ -0,0 +1,301 @@ 
+/** @file
+
+  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <AmdStyxAcpiLib.h>
+#include <IndustryStandard/IoRemappingTable.h>
+
+#define FIELD_OFFSET(type, name)            __builtin_offsetof(type, name)
+
+#define STYX_PCIE_SMMU_BASE                 0xE0A00000
+#define STYX_PCIE_SMMU_SIZE                 0x10000
+#define STYX_PCIE_SMMU_INTERRUPT            0x16d
+
+#define STYX_ETH0_SMMU_BASE                 0xE0600000
+#define STYX_ETH0_SMMU_SIZE                 0x10000
+#define STYX_ETH0_SMMU_INTERRUPT            0x170
+
+#define STYX_ETH1_SMMU_BASE                 0xE0800000
+#define STYX_ETH1_SMMU_SIZE                 0x10000
+#define STYX_ETH1_SMMU_INTERRUPT            0x16f
+
+#define STYX_SATA0_SMMU_BASE                0xE0200000
+#define STYX_SATA0_SMMU_SIZE                0x10000
+#define STYX_SATA0_SMMU_INTERRUPT           0x16c
+
+#define STYX_SATA1_SMMU_BASE                0xE0C00000
+#define STYX_SATA1_SMMU_SIZE                0x10000
+#define STYX_SATA1_SMMU_INTERRUPT           0x16b
+
+#pragma pack(1)
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE       Node;
+  EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT        Context[1];
+} STYX_SMMU_NODE;
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_RC_NODE         Node;
+  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE        RcIdMapping[1];
+} STYX_RC_NODE;
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE Node;
+  CONST CHAR8                               Name[11];
+  EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE        RcIdMapping[16];
+} STYX_NC_NODE;
+
+typedef struct {
+  EFI_ACPI_6_0_IO_REMAPPING_TABLE           Iort;
+  STYX_SMMU_NODE                            PciSmmuNode;
+  STYX_RC_NODE                              PciRcNode;
+
+#if DO_XGBE
+  STYX_SMMU_NODE                            Eth0SmmuNode;
+  STYX_NC_NODE                              Eth0NamedNode;
+  STYX_SMMU_NODE                            Eth1SmmuNode;
+  STYX_NC_NODE                              Eth1NamedNode;
+#endif
+
+  STYX_SMMU_NODE                            Sata0SmmuNode;
+  STYX_NC_NODE                              Sata0NamedNode;
+  STYX_SMMU_NODE                            Sata1SmmuNode;
+  STYX_NC_NODE                              Sata1NamedNode;
+} STYX_IO_REMAPPING_STRUCTURE;
+
+#define __STYX_SMMU_NODE(Base, Size, Irq)                   \
+  {                                                         \
+    {                                                       \
+      EFI_ACPI_IORT_TYPE_SMMUv1v2,                          \
+      sizeof(STYX_SMMU_NODE),                               \
+      0x0,                                                  \
+      0x0,                                                  \
+      0x0,                                                  \
+      0x0,                                                  \
+    },                                                      \
+    Base,                                                   \
+    Size,                                                   \
+    EFI_ACPI_IORT_SMMUv1v2_MODEL_v1,                        \
+    EFI_ACPI_IORT_SMMUv1v2_FLAG_COH_WALK,                   \
+    FIELD_OFFSET(EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE,       \
+                 SMMU_NSgIrpt),                             \
+    0x1,                                                    \
+    sizeof(EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE),            \
+    0x0,                                                    \
+    0x0,                                                    \
+    Irq,                                                    \
+    EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_LEVEL,                  \
+    0x0,                                                    \
+    0x0,                                                    \
+  }, {                                                      \
+    {                                                       \
+      Irq,                                                  \
+      EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_LEVEL,                \
+    },                                                      \
+  }
+
+#define __STYX_ID_MAPPING(In, Num, Out, Flags, Ref)         \
+  {                                                         \
+    In,                                                     \
+    Num,                                                    \
+    Out,                                                    \
+    FIELD_OFFSET(STYX_IO_REMAPPING_STRUCTURE, Ref),         \
+    Flags                                                   \
+  }
+
+#define __STYX_NAMED_COMPONENT_NODE(Name)                   \
+    {                                                       \
+      {                                                     \
+        EFI_ACPI_IORT_TYPE_NAMED_COMP,                      \
+        sizeof(STYX_NC_NODE),                               \
+        0x0,                                                \
+        0x0,                                                \
+        0x10,                                               \
+        FIELD_OFFSET(STYX_NC_NODE, RcIdMapping),            \
+      },                                                    \
+      0x0,                                                  \
+      EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,                    \
+      0x0,                                                  \
+      0x0,                                                  \
+      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM |                  \
+      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS,                  \
+      40,                                                   \
+    },                                                      \
+    Name
+
+STATIC STYX_IO_REMAPPING_STRUCTURE AcpiIort = {
+  {
+    AMD_ACPI_HEADER(EFI_ACPI_6_0_IO_REMAPPING_TABLE_SIGNATURE,
+                    STYX_IO_REMAPPING_STRUCTURE,
+                    EFI_ACPI_IO_REMAPPING_TABLE_REVISION),
+#if DO_XGBE
+    10,                                             // NumNodes
+#else
+    6,                                              // NumNodes
+#endif
+    sizeof(EFI_ACPI_6_0_IO_REMAPPING_TABLE),        // NodeOffset
+    0                                               // Reserved
+  }, {
+    // PciSmmuNode
+    __STYX_SMMU_NODE(STYX_PCIE_SMMU_BASE,
+                     STYX_PCIE_SMMU_SIZE,
+                     STYX_PCIE_SMMU_INTERRUPT)
+  }, {
+    // PciRcNode
+    {
+      {
+        EFI_ACPI_IORT_TYPE_ROOT_COMPLEX,                    // Type
+        sizeof(STYX_RC_NODE),                               // Length
+        0x0,                                                // Revision
+        0x0,                                                // Reserved
+        0x1,                                                // NumIdMappings
+        FIELD_OFFSET(STYX_RC_NODE, RcIdMapping),            // IdReference
+      },
+      EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,                    // CacheCoherent
+      0x0,                                                  // AllocationHints
+      0x0,                                                  // Reserved
+      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM |
+      EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS,                  // MemoryAccessFlags
+      EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED,           // AtsAttribute
+      0x0,                                                  // PciSegmentNumber
+    }, {
+      __STYX_ID_MAPPING(0x0, 0xffff, 0x0, 0x0, PciSmmuNode),
+    }
+#if DO_XGBE
+  }, {
+    // Eth0SmmuNode
+    __STYX_SMMU_NODE(STYX_ETH0_SMMU_BASE,
+                     STYX_ETH0_SMMU_SIZE,
+                     STYX_ETH0_SMMU_INTERRUPT)
+  }, {
+    // Eth0NamedNode
+    __STYX_NAMED_COMPONENT_NODE("\\_SB_.ETH0"),
+    {
+      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth0SmmuNode),
+    }
+  }, {
+    // Eth1SmmuNode
+    __STYX_SMMU_NODE(STYX_ETH1_SMMU_BASE,
+                     STYX_ETH1_SMMU_SIZE,
+                     STYX_ETH1_SMMU_INTERRUPT)
+  }, {
+    // Eth1NamedNode
+    __STYX_NAMED_COMPONENT_NODE("\\_SB_.ETH1"),
+    {
+      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Eth1SmmuNode),
+    }
+#endif
+  }, {
+    // Sata0SmmuNode
+    __STYX_SMMU_NODE(STYX_SATA0_SMMU_BASE,
+                     STYX_SATA0_SMMU_SIZE,
+                     STYX_SATA0_SMMU_INTERRUPT)
+  }, {
+    // Sata0NamedNode
+    __STYX_NAMED_COMPONENT_NODE("\\_SB_.AHC0"),
+    {
+      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata0SmmuNode),
+    }
+  }, {
+    // Sata1SmmuNode
+    __STYX_SMMU_NODE(STYX_SATA1_SMMU_BASE,
+                     STYX_SATA1_SMMU_SIZE,
+                     STYX_SATA1_SMMU_INTERRUPT)
+  }, {
+    // Sata1NamedNode
+    __STYX_NAMED_COMPONENT_NODE("\\_SB_.AHC1"),
+    {
+      __STYX_ID_MAPPING(0x0, 0x0, 0x00, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x01, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x02, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x03, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x04, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x05, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x06, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x07, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x10, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x11, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x12, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x13, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x14, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x15, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x16, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+      __STYX_ID_MAPPING(0x0, 0x0, 0x17, EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE, Sata1SmmuNode),
+    }
+  }
+};
+
+#pragma pack()
+
+#define STYX_SOC_VERSION_MASK    0xFFF
+#define STYX_SOC_VERSION_A0      0x000
+#define STYX_SOC_VERSION_B0      0x010
+#define STYX_SOC_VERSION_B1      0x011
+
+EFI_ACPI_DESCRIPTION_HEADER *
+IortHeader (
+  VOID
+  )
+{
+  if (FixedPcdGet8 (PcdSata1PortCount) == 0 ||
+      (PcdGet32 (PcdSocCpuId) & STYX_SOC_VERSION_MASK) < STYX_SOC_VERSION_B1) {
+
+    // ignore the last two nodes if Sata1 is not enabled
+    AcpiIort.Iort.NumNodes -= 2;
+  }
+  return (EFI_ACPI_DESCRIPTION_HEADER *) &AcpiIort.Iort.Header;
+}
diff --git a/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h b/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h
index 698a5d3f90f8..9438b8b0c27e 100644
--- a/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h
+++ b/Platforms/AMD/Styx/Common/AmdStyxAcpiLib.h
@@ -27,6 +27,7 @@  EFI_ACPI_DESCRIPTION_HEADER *McfgHeader (void);
 EFI_ACPI_DESCRIPTION_HEADER *Dbg2Header (void);
 EFI_ACPI_DESCRIPTION_HEADER *SpcrHeader (void);
 EFI_ACPI_DESCRIPTION_HEADER *CsrtHeader (void);
+EFI_ACPI_DESCRIPTION_HEADER *IortHeader (void);
 
 #define EFI_ACPI_AMD_OEM_ID_ARRAY        {'A','M','D','I','N','C'}
 #define EFI_ACPI_AMD_OEM_TABLE_ID        SIGNATURE_64('S','E','A','T','T','L','E',' ')
diff --git a/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c b/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
index 1bad597a8eaa..8efb5ccfd8b7 100644
--- a/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
+++ b/Platforms/AMD/Styx/Drivers/AcpiPlatformDxe/AcpiPlatform.c
@@ -65,6 +65,7 @@  AcpiPlatformEntryPoint (
   AcpiTableList[TableIndex++] = SpcrHeader();
   AcpiTableList[TableIndex++] = McfgHeader();
   AcpiTableList[TableIndex++] = CsrtHeader();
+  AcpiTableList[TableIndex++] = IortHeader();
   AcpiTableList[TableIndex++] = NULL;
 
   DEBUG((DEBUG_INFO, "%a(): ACPI Table installer\n", __FUNCTION__));