public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses
@ 2024-05-28 10:31 Marcin Juszkiewicz
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 1/3] SbsaQemu: scan for PCIe buses Marcin Juszkiewicz
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Marcin Juszkiewicz @ 2024-05-28 10:31 UTC (permalink / raw)
  To: devel
  Cc: Leif Lindholm, Ard Biesheuvel, Graeme Gregory, Ray Ni,
	Marcin Juszkiewicz

QEMU allows to have NUMA setup where each node has own cpus, memory and
i/o. We already handle cpus and memory. This patchset adds support for
having multiple PCI Express buses.

SbsaQemu assumed that there is only bus 0. First patch does PCIe bus
scan to find all host bridges (bus 0 one and additional 'pxb-pcie'
ones).

Second patch moves description of PCIe from DSDT to SSDT (one per each
PCIe bus). So Operating System will know about all of them.

Third patch moves generation of MCFG table to C. It is preparation to
move PCIe Pcds from being fixed to dynamic ones.

There are some booting issues with assigning resources for cards:

pci 0000:00:03.0: BAR 15: no space for [mem size 0x00200000 64bit pref]
pci 0000:00:03.0: BAR 15: failed to assign [mem size 0x00200000 64bit pref]
pci 0000:00:01.0: BAR 6: no space for [mem size 0x00040000 pref]
pci 0000:00:01.0: BAR 6: failed to assign [mem size 0x00040000 pref]
pci 0000:00:03.0: BAR 13: no space for [io  size 0x1000]
pci 0000:00:03.0: BAR 13: failed to assign [io  size 0x1000]

Boot log (Linux + lspci + ACPI tables dump):
https://people.linaro.org/~marcin.juszkiewicz/sbsa-ref/boot-linux-with-numa-multiple-pcie-buses.txt

I am wondering where I made mistakes in handling PCIe buses.

Thanks go to Leif for pointing me to use of Aml to generate SSDT tables.

Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Graeme Gregory <graeme@xora.org.uk>
Cc: Ray Ni <ray.ni@intel.com>
To: devel@edk2.groups.io

Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
---
Changes in v2:
- Dropped [WIP] status
- Link to v1: https://openfw.io/edk2-devel/20240425-review-multiple-pcie-0425-v1-0-68fdfd781f9e@linaro.org/

---
Marcin Juszkiewicz (3):
      SbsaQemu: scan for PCIe buses
      SbsaQemu: describe PCIe buses in SSDT tables
      SbsaQemu: generate MCFG table

 Platform/Qemu/SbsaQemu/SbsaQemu.dsc                 |   2 +
 Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf     |   1 -
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf     |  37 +-
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h      |  23 +
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c       | 170 +++++-
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c      | 576 ++++++++++++++++++++
 .../SbsaQemuPciHostBridgeLib.c                      | 185 ++++---
 Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl           | 302 ----------
 Silicon/Qemu/SbsaQemu/AcpiTables/Mcfg.aslc          |  43 --
 .../Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl        |  82 +++
 10 files changed, 982 insertions(+), 439 deletions(-)
---
base-commit: 4bbd0ed440322e49edffdebe15e12aa76916d1b0
change-id: 20240425-review-multiple-pcie-0425-54ce3817fd3f

Best regards,
-- 
Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119300): https://edk2.groups.io/g/devel/message/119300
Mute This Topic: https://groups.io/mt/106345969/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [edk2-devel] [PATCH edk2-platforms v2 1/3] SbsaQemu: scan for PCIe buses
  2024-05-28 10:31 [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Marcin Juszkiewicz
@ 2024-05-28 10:31 ` Marcin Juszkiewicz
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 2/3] SbsaQemu: describe PCIe buses in SSDT tables Marcin Juszkiewicz
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Marcin Juszkiewicz @ 2024-05-28 10:31 UTC (permalink / raw)
  To: devel
  Cc: Leif Lindholm, Ard Biesheuvel, Graeme Gregory, Ray Ni,
	Marcin Juszkiewicz

SbsaQemu assumes that there is only one PCI Express bus. But there can
be multiple PCIe buses as NUMA systems can get 'pxb-pcie' HostBridge
devices added.

Let scan for all PCIe buses and report them back so EDK2 will be able to
find all expansions.

Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
---
 .../SbsaQemuPciHostBridgeLib.c                      | 185 ++++++++++++--------
 1 file changed, 109 insertions(+), 76 deletions(-)

diff --git a/Silicon/Qemu/SbsaQemu/Library/SbsaQemuPciHostBridgeLib/SbsaQemuPciHostBridgeLib.c b/Silicon/Qemu/SbsaQemu/Library/SbsaQemuPciHostBridgeLib/SbsaQemuPciHostBridgeLib.c
index 9739c7500def..1c4ed1c74e52 100644
--- a/Silicon/Qemu/SbsaQemu/Library/SbsaQemuPciHostBridgeLib/SbsaQemuPciHostBridgeLib.c
+++ b/Silicon/Qemu/SbsaQemu/Library/SbsaQemuPciHostBridgeLib/SbsaQemuPciHostBridgeLib.c
@@ -6,10 +6,14 @@
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
+#include <limits.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/DevicePathLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/PciHostBridgeLib.h>
+#include <Library/PciLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 
 #include <PiDxe.h>
@@ -52,76 +56,49 @@ CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
   L"Mem", L"I/O", L"Bus"
 };
 
-STATIC PCI_ROOT_BRIDGE mRootBridge = {
-  /* UINT32 Segment; Segment number */
-  0,
-
-  /* UINT64 Supports; Supported attributes */
-  EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
-  EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16,
-
-  /* UINT64 Attributes; Initial attributes */
-  EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
-  EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16,
-
-  /* BOOLEAN DmaAbove4G; DMA above 4GB memory */
-  TRUE,
-
-  /* BOOLEAN NoExtendedConfigSpace; When FALSE, the root bridge supports
-     Extended (4096-byte) Configuration Space.  When TRUE, the root bridge
-     supports 256-byte Configuration Space only. */
-  FALSE,
-
-  /* BOOLEAN ResourceAssigned; Resource assignment status of the root bridge.
-     Set to TRUE if Bus/IO/MMIO resources for root bridge have been assigned */
-  FALSE,
-
-  /* UINT64 AllocationAttributes; Allocation attributes. */
-  EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
-  EFI_PCI_HOST_BRIDGE_MEM64_DECODE, /* as Mmio64Size > 0 */
-
-  {
-     /* PCI_ROOT_BRIDGE_APERTURE Bus; Bus aperture which can be used by the
-      * root bridge. */
-     FixedPcdGet32 (PcdPciBusMin),
-     FixedPcdGet32 (PcdPciBusMax)
-  },
-
-  /* PCI_ROOT_BRIDGE_APERTURE Io; IO aperture which can be used by the root
-     bridge */
-  {
-     FixedPcdGet64 (PcdPciIoBase),
-     FixedPcdGet64 (PcdPciIoBase) + FixedPcdGet64 (PcdPciIoSize) - 1
-  },
-
-  /* PCI_ROOT_BRIDGE_APERTURE Mem; MMIO aperture below 4GB which can be used by
-     the root bridge
-     (gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation as 0x0) */
-  {
-    FixedPcdGet32 (PcdPciMmio32Base),
-    FixedPcdGet32 (PcdPciMmio32Base) + FixedPcdGet32 (PcdPciMmio32Size) - 1,
-  },
-
-  /* PCI_ROOT_BRIDGE_APERTURE MemAbove4G; MMIO aperture above 4GB which can be
-     used by the root bridge.
-     (gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation as 0x0) */
-  {
-    FixedPcdGet64 (PcdPciMmio64Base),
-    FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size) - 1
-  },
-
-  /* PCI_ROOT_BRIDGE_APERTURE PMem; Prefetchable MMIO aperture below 4GB which
-     can be used by the root bridge.
-     In our case, there are no separate ranges for prefetchable and
-     non-prefetchable BARs */
-  { MAX_UINT64, 0 },
-
-  /* PCI_ROOT_BRIDGE_APERTURE PMemAbove4G; Prefetchable MMIO aperture above 4GB
-     which can be used by the root bridge. */
-  { MAX_UINT64, 0 },
-  /* EFI_DEVICE_PATH_PROTOCOL *DevicePath; Device path. */
-  (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath,
-};
+EFI_STATUS
+EFIAPI
+PciHostBridgeUtilityInitRootBridge (
+  IN UINTN             RootBusNumber,
+  OUT PCI_ROOT_BRIDGE  *RootBus
+  )
+{
+  EFI_PCI_ROOT_BRIDGE_DEVICE_PATH  *DevicePath;
+  UINTN                            MaxSubBusNumber = 255;
+
+  DevicePath = AllocateCopyPool (
+                 sizeof mEfiPciRootBridgeDevicePath,
+                 &mEfiPciRootBridgeDevicePath
+                 );
+  if (DevicePath == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: %r\n", __func__, EFI_OUT_OF_RESOURCES));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DevicePath->AcpiDevicePath.UID = RootBusNumber;
+
+  RootBus->Segment               = 0;
+  RootBus->Supports              = 0;
+  RootBus->Attributes            = 0;
+  RootBus->DmaAbove4G            = TRUE;
+  RootBus->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | EFI_PCI_HOST_BRIDGE_MEM64_DECODE, /* as Mmio64Size > 0 */
+  RootBus->Bus.Base              = RootBusNumber;
+  RootBus->Bus.Limit             = MaxSubBusNumber;
+  RootBus->Io.Base               = PcdGet64 (PcdPciIoBase);
+  RootBus->Io.Limit              = PcdGet64 (PcdPciIoBase) + PcdGet64 (PcdPciIoSize) - 1;
+  RootBus->Mem.Base              = PcdGet32 (PcdPciMmio32Base);
+  RootBus->Mem.Limit             = PcdGet32 (PcdPciMmio32Base) + PcdGet32 (PcdPciMmio32Size) - 1;
+  RootBus->MemAbove4G.Base       = PcdGet64 (PcdPciMmio64Base);
+  RootBus->MemAbove4G.Limit      = PcdGet64 (PcdPciMmio64Base) + PcdGet64 (PcdPciMmio64Size) - 1;
+  RootBus->PMem.Base             = MAX_UINT64;
+  RootBus->PMem.Limit            = 0;
+  RootBus->PMemAbove4G.Base      = MAX_UINT64;
+  RootBus->PMemAbove4G.Limit     = 0;
+  RootBus->NoExtendedConfigSpace = FALSE;
+  RootBus->DevicePath            = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
+
+  return EFI_SUCCESS;
+}
 
 /**
   Return all the root bridge instances in an array.
@@ -135,11 +112,67 @@ STATIC PCI_ROOT_BRIDGE mRootBridge = {
 PCI_ROOT_BRIDGE *
 EFIAPI
 PciHostBridgeGetRootBridges (
-  UINTN *Count
+  UINTN  *Count
   )
 {
-  *Count = 1;
-  return &mRootBridge;
+  PCI_ROOT_BRIDGE  *Bridges;
+  int              BusId, BusMin = 0, BusMax = 255, Index = 0;
+  int              AvailableBusses[255] = { INT_MAX }; // INT_MAX as "there is no bus"
+
+  *Count = 0;
+
+  //
+  // Scan all root buses. If function 0 of any device on a bus returns a
+  // VendorId register value different from all-bits-one, then that bus is
+  // alive.
+  //
+  for (BusId = BusMin; BusId <= BusMax; ++BusId) {
+    UINTN  Device;
+
+    for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
+      if (PciRead16 (
+            PCI_LIB_ADDRESS (
+              BusId,
+              Device,
+              0,
+              PCI_VENDOR_ID_OFFSET
+              )
+            ) != MAX_UINT16)
+      {
+        break;
+      }
+    }
+
+    if (Device <= PCI_MAX_DEVICE) {
+      DEBUG ((DEBUG_ERROR, "%a: found bus: 0x%02x\n", __func__, BusId));
+      AvailableBusses[Index++] = BusId;
+      *Count                  += 1;
+    }
+  }
+
+  //
+  // Allocate the "main" root bridge, and any extra root bridges.
+  //
+  Bridges = AllocateZeroPool (*Count * sizeof *Bridges);
+  if (Bridges == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: %r\n", __func__, EFI_OUT_OF_RESOURCES));
+    return NULL;
+  }
+
+  for (Index = 0; Index < *Count; Index++) {
+    if (AvailableBusses[Index] == INT_MAX) {
+      break;
+    }
+
+    PciHostBridgeUtilityInitRootBridge (AvailableBusses[Index], &Bridges[Index]);
+
+    // limit previous RootBridge bus range
+    if (Index > 0) {
+      Bridges[Index - 1].Bus.Limit = AvailableBusses[Index] - 1;
+    }
+  }
+
+  return Bridges;
 }
 
 /**
@@ -152,11 +185,11 @@ PciHostBridgeGetRootBridges (
 VOID
 EFIAPI
 PciHostBridgeFreeRootBridges (
-  PCI_ROOT_BRIDGE *Bridges,
-  UINTN           Count
+  PCI_ROOT_BRIDGE  *Bridges,
+  UINTN            Count
   )
 {
-  ASSERT (Count == 1);
+  FreePool (Bridges);
 }
 
 /**

-- 
2.45.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119301): https://edk2.groups.io/g/devel/message/119301
Mute This Topic: https://groups.io/mt/106345970/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [edk2-devel] [PATCH edk2-platforms v2 2/3] SbsaQemu: describe PCIe buses in SSDT tables
  2024-05-28 10:31 [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Marcin Juszkiewicz
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 1/3] SbsaQemu: scan for PCIe buses Marcin Juszkiewicz
@ 2024-05-28 10:31 ` Marcin Juszkiewicz
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 3/3] SbsaQemu: generate MCFG table Marcin Juszkiewicz
  2024-05-28 14:31 ` [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Ard Biesheuvel
  3 siblings, 0 replies; 7+ messages in thread
From: Marcin Juszkiewicz @ 2024-05-28 10:31 UTC (permalink / raw)
  To: devel
  Cc: Leif Lindholm, Ard Biesheuvel, Graeme Gregory, Ray Ni,
	Marcin Juszkiewicz

We can have more than one PCI Express bus. So instead of having static
description in DSDT we create SSDT table for each existing PCIe bus.

Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
---
 Platform/Qemu/SbsaQemu/SbsaQemu.dsc                 |   2 +
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf     |  37 +-
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h      |  23 +
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c       |  87 ++-
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c      | 576 ++++++++++++++++++++
 Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl           | 302 ----------
 .../Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl        |  82 +++
 7 files changed, 790 insertions(+), 319 deletions(-)

diff --git a/Platform/Qemu/SbsaQemu/SbsaQemu.dsc b/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
index e246db8b0a23..b012eaa34147 100644
--- a/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
+++ b/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
@@ -173,6 +173,8 @@ [LibraryClasses.common]
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
 
   AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf
+  AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf
+  AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
 
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
   ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
index 727c8e82d16e..6de1073e6ac2 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
@@ -18,18 +18,25 @@ [Defines]
 
 [Sources]
   SbsaQemuAcpiDxe.c
+  SbsaQemuAcpiDxe.h
+  SbsaQemuAcpiPcie.c
+  SbsaQemuAcpiPcie.h
+  SsdtTemplate.asl
 
 [Packages]
   ArmPkg/ArmPkg.dec
   ArmPlatformPkg/ArmPlatformPkg.dec
   ArmVirtPkg/ArmVirtPkg.dec
+  DynamicTablesPkg/DynamicTablesPkg.dec
   EmbeddedPkg/EmbeddedPkg.dec
   MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
   Silicon/Qemu/SbsaQemu/SbsaQemu.dec
 
 [LibraryClasses]
+  AcpiHelperLib
   AcpiLib
+  AmlLib
   ArmLib
   BaseMemoryLib
   BaseLib
@@ -37,6 +44,7 @@ [LibraryClasses]
   DxeServicesLib
   HardwareInfoLib
   PcdLib
+  PciLib
   PrintLib
   UefiDriverEntryPoint
   UefiLib
@@ -54,14 +62,39 @@ [Pcd]
   gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdSmmuBase
 
 [Depex]
-  gEfiAcpiTableProtocolGuid                       ## CONSUMES
+  # We want all PCIe buses to be scanned first
+  gEfiPciIoProtocolGuid             ## CONSUMES
 
 [Guids]
   gEdkiiPlatformHasAcpiGuid
 
 [Protocols]
   gEfiAcpiSdtProtocolGuid
-  gEfiAcpiTableProtocolGuid                       ## CONSUMES
+  gEfiAcpiTableProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdPciBusMin
+  gArmTokenSpaceGuid.PcdPciBusMax
+  gArmTokenSpaceGuid.PcdPciIoBase
+  gArmTokenSpaceGuid.PcdPciIoSize
+  gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciIoLimit
+
+  gArmTokenSpaceGuid.PcdPciMmio32Base
+  gArmTokenSpaceGuid.PcdPciMmio32Size
+  gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciMmio32Limit
+
+  gArmTokenSpaceGuid.PcdPciMmio64Base
+  gArmTokenSpaceGuid.PcdPciMmio64Size
+  gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciMmio64Limit
+
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciExpressBarSize
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciExpressBarLimit
 
 [FixedPcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h
new file mode 100644
index 000000000000..56cc6f1381da
--- /dev/null
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h
@@ -0,0 +1,23 @@
+/** @file
+*  This file is an ACPI driver for the Qemu SBSA platform.
+*
+*  Copyright (c) 2024, Linaro Ltd. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef SBSAQEMU_ACPI_PCIE_H
+#define SBSAQEMU_ACPI_PCIE_H
+
+#pragma pack(1)
+
+/* AML bytecode generated from SsdtTemplate.asl */
+extern CHAR8  ssdttemplate_aml_code[];
+
+EFI_STATUS
+AddPcieHostBridges (
+  AML_OBJECT_NODE_HANDLE  ScopeNode
+  );
+
+#endif
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
index 30239e7dca0d..f3d5dc9e9ba7 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
@@ -6,28 +6,27 @@
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
 *
 **/
-#include <IndustryStandard/Acpi.h>
-#include <IndustryStandard/AcpiAml.h>
 #include <IndustryStandard/IoRemappingTable.h>
 #include <IndustryStandard/SbsaQemuAcpi.h>
 #include <IndustryStandard/SbsaQemuPlatformVersion.h>
+
 #include <Library/AcpiLib.h>
+#include <Library/AmlLib/AmlLib.h>
 #include <Library/ArmLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PcdLib.h>
-#include <Library/PrintLib.h>
 #include <Library/HardwareInfoLib.h>
+#include <Library/PrintLib.h>
 #include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiLib.h>
+
 #include <Protocol/AcpiTable.h>
+#include <Protocol/PciRootBridgeIo.h>
+
 #include "SbsaQemuAcpiDxe.h"
+#include "SbsaQemuAcpiPcie.h"
 
 #pragma pack(1)
 
-
 static UINTN GicItsBase;
 
 #pragma pack ()
@@ -36,7 +35,7 @@ static UINTN GicItsBase;
  * A Function to Compute the ACPI Table Checksum
  */
 VOID
-AcpiPlatformChecksum (
+AcpiTableChecksum (
   IN UINT8      *Buffer,
   IN UINTN      Size
   )
@@ -189,7 +188,7 @@ AddIortTable (
   CopyMem (New, &Rc, sizeof (SBSA_EFI_ACPI_6_0_IO_REMAPPING_RC_NODE));
   New += sizeof (SBSA_EFI_ACPI_6_0_IO_REMAPPING_RC_NODE);
 
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -314,7 +313,7 @@ AddMadtTable (
     New += sizeof (EFI_ACPI_6_5_GIC_ITS_STRUCTURE);
   }
 
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -467,7 +466,7 @@ AddSsdtTable (
   }
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -572,7 +571,7 @@ AddPpttTable (
   }
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -667,7 +666,7 @@ AddGtdtTable (
   New += sizeof (EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -752,7 +751,7 @@ AddSratTable (
   }
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -832,6 +831,58 @@ DisableXhciOnOlderPlatVer (
   return Status;
 }
 
+/** Adds the SSDT ACPI table with PCIe nodes.
+
+  @param AcpiTable        The ACPI Table.
+
+  @return EFI_SUCCESS on success, or an error code.
+
+**/
+STATIC
+EFI_STATUS
+AddSsdtPcieTable (
+  IN  EFI_ACPI_TABLE_PROTOCOL  *AcpiTable
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        TableHandle;
+  EFI_ACPI_DESCRIPTION_HEADER  *Table;
+  AML_ROOT_NODE_HANDLE         RootNode;
+  AML_OBJECT_NODE_HANDLE       ScopeNode;
+
+  Status = AmlCodeGenDefinitionBlock ("SSDT", "LINARO", "SBSAQEMU", 0x1, &RootNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT: AmlCodeGenDefinitionBlock failed."
+      " Status = %r\n",
+      Status
+      ));
+  }
+
+  AmlCodeGenScope ("_SB_", RootNode, &ScopeNode);
+
+  AddPcieHostBridges(ScopeNode);
+
+  // Serialize the tree.
+  Status = AmlSerializeDefinitionBlock (
+             RootNode,
+             &Table
+             );
+
+  Status = AcpiTable->InstallAcpiTable (
+                        AcpiTable,
+                        Table,
+                        Table->Length,
+                        &TableHandle
+                        );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to install SSDT table\n"));
+  }
+
+  return EFI_SUCCESS;
+}
+
 
 EFI_STATUS
 EFIAPI
@@ -895,5 +946,11 @@ InitializeSbsaQemuAcpiDxe (
     DEBUG ((DEBUG_ERROR, "Failed to handle XHCI enablement\n"));
   }
 
+  Status = AddSsdtPcieTable (AcpiTable);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to add SSDT table\n"));
+  }
+
+
   return EFI_SUCCESS;
 }
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c
new file mode 100644
index 000000000000..f5595b8a1baa
--- /dev/null
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c
@@ -0,0 +1,576 @@
+/** @file
+*  This file is an ACPI driver for the Qemu SBSA platform.
+*
+*  Copyright (c) 2024, Linaro Ltd. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/AcpiHelperLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/PciRootBridgeIo.h>
+
+#include "SbsaQemuAcpiPcie.h"
+
+#pragma pack(1)
+
+/** Adds the _OSC method to the PCIe node.
+
+  @param PciNode  PCIe device node.
+
+  @return EFI_SUCCESS on success, or an error code.
+
+**/
+STATIC
+EFI_STATUS
+AddOscMethod (
+  IN  OUT   AML_OBJECT_NODE_HANDLE  PciNode
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_ACPI_DESCRIPTION_HEADER  *SsdtPcieOscTemplate;
+  AML_ROOT_NODE_HANDLE         OscTemplateRoot;
+  AML_OBJECT_NODE_HANDLE       OscNode;
+  AML_OBJECT_NODE_HANDLE       ClonedOscNode;
+
+  ASSERT (PciNode != NULL);
+
+  /* Parse the Ssdt Pci Osc Template. */
+  SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)
+                        ssdttemplate_aml_code;
+
+  Status = AmlParseDefinitionBlock (
+             SsdtPcieOscTemplate,
+             &OscTemplateRoot
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
+      " Status = %r\n",
+      Status
+      ));
+    return Status;
+  }
+
+  Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "AmlFindNode: %r\n", Status));
+    return Status;
+  }
+
+  Status = AmlCloneTree (OscNode, &ClonedOscNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "AmlCloneTree: %r\n", Status));
+    return Status;
+  }
+
+  Status = AmlAttachNode (PciNode, ClonedOscNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "AmlAttachNode: %r\n", Status));
+    // Free the cloned node.
+    AmlDeleteTree (ClonedOscNode);
+    return Status;
+  }
+
+  return Status;
+}
+
+/** Creates a PCI Interrupt Link Device.
+
+  @param PciDeviceHandle  PCIe device node.
+  @param Uid              UID of the Link Device.
+  @param LinkName         Name of the Device.
+  @param Irq              IRQ number.
+
+**/
+STATIC
+VOID
+GenPciLinkDevice (
+  AML_OBJECT_NODE_HANDLE  PciDeviceHandle,
+  UINT32                  Uid,
+  CONST CHAR8             *LinkName,
+  UINT32                  Irq
+  )
+{
+  EFI_STATUS              Status;
+  UINT32                  EisaId;
+  AML_OBJECT_NODE_HANDLE  GsiNode;
+
+  AmlCodeGenDevice (LinkName, PciDeviceHandle, &GsiNode);
+
+  Status = AmlGetEisaIdFromString ("PNP0C0F", &EisaId);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return;
+  }
+
+  AmlCodeGenNameInteger ("_HID", EisaId, GsiNode, NULL);
+  AmlCodeGenNameInteger ("_UID", Uid, GsiNode, NULL);
+
+  AML_OBJECT_NODE_HANDLE  Prs;
+
+  AmlCodeGenNameResourceTemplate ("_PRS", GsiNode, &Prs);
+  AmlCodeGenRdInterrupt (FALSE, FALSE, FALSE, FALSE, &Irq, 1, Prs, NULL);
+  AmlCodeGenMethodRetNameString ("_CRS", "_PRS", 0, TRUE, 0, GsiNode, NULL);
+  AmlCodeGenMethodRetNameString ("_SRS", NULL, 1, FALSE, 0, GsiNode, NULL);
+  AmlCodeGenMethodRetNameString ("_DIS", NULL, 0, FALSE, 0, GsiNode, NULL);
+}
+
+/** Creates a _PRT package.
+
+  @param PciDeviceHandle  PCIe device node.
+
+**/
+STATIC
+VOID
+GenPrtEntries (
+  AML_OBJECT_NODE_HANDLE  PciDeviceHandle
+  )
+{
+  AML_OBJECT_NODE_HANDLE  PrtNode;
+
+  AmlCodeGenNamePackage ("_PRT", PciDeviceHandle, &PrtNode);
+
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI3", 0, PrtNode);
+
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI1", 1, PrtNode);
+
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI2", 3, PrtNode);
+}
+
+EFI_STATUS
+PciGetProtocolAndResource (
+  IN  EFI_HANDLE                         Handle,
+  OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    **IoDev,
+  OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Get inferface from protocol
+  //
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **)IoDev
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Call Configuration() to get address space descriptors
+  //
+  Status = (*IoDev)->Configuration (*IoDev, (VOID **)Descriptors);
+  if (Status == EFI_UNSUPPORTED) {
+    *Descriptors = NULL;
+    return EFI_SUCCESS;
+  } else {
+    return Status;
+  }
+}
+
+EFI_STATUS
+AddPcieHostBridges (
+  AML_OBJECT_NODE_HANDLE  ScopeNode
+  )
+{
+  UINTN       HandleBufSize;
+  EFI_HANDLE  *HandleBuf;
+  UINTN       HandleCount;
+  EFI_STATUS  Status;
+  UINTN       Index;
+
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *IoDev;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptors;
+
+  AML_OBJECT_NODE_HANDLE  PciNode;
+  AML_OBJECT_NODE_HANDLE  ResNode;
+  AML_OBJECT_NODE_HANDLE  RbufRt;
+  AML_OBJECT_NODE_HANDLE  ResRt;
+  UINT64                  PcieDeviceStatus;
+  UINT32                  EisaId;
+  CHAR8                   DeviceName[5];
+
+  HandleBufSize = sizeof (EFI_HANDLE);
+  HandleBuf     = (EFI_HANDLE *)AllocateZeroPool (HandleBufSize);
+  if (HandleBuf == NULL) {
+    DEBUG ((DEBUG_ERROR, "Failed to allocate memory\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = gBS->LocateHandle (
+                  ByProtocol,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  NULL,
+                  &HandleBufSize,
+                  HandleBuf
+                  );
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    HandleBuf = ReallocatePool (sizeof (EFI_HANDLE), HandleBufSize, HandleBuf);
+    if (HandleBuf == NULL) {
+      DEBUG ((DEBUG_ERROR, "Failed to allocate memory\n"));
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    Status = gBS->LocateHandle (
+                    ByProtocol,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    NULL,
+                    &HandleBufSize,
+                    HandleBuf
+                    );
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to locate PciRootBridge\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  HandleCount = HandleBufSize / sizeof (EFI_HANDLE);
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    AsciiSPrint (DeviceName, sizeof (DeviceName), "PCI%x", Index);
+    AmlCodeGenDevice (DeviceName, ScopeNode, &PciNode);
+    Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
+    Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
+    AmlCodeGenNameInteger ("_SEG", 0, PciNode, NULL);
+    AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
+    AmlCodeGenNameString ("_UID", DeviceName, PciNode, NULL);
+
+    GenPciLinkDevice (PciNode, 0, "GSI0", 0x23);
+    GenPciLinkDevice (PciNode, 0, "GSI1", 0x24);
+    GenPciLinkDevice (PciNode, 0, "GSI2", 0x25);
+    GenPciLinkDevice (PciNode, 0, "GSI3", 0x26);
+
+    GenPrtEntries (PciNode);
+    AmlCodeGenNameResourceTemplate ("RBUF", PciNode, &RbufRt);
+    AmlCodeGenMethodRetInteger ("_CBA", PcdGet64 (PcdPciExpressBaseAddress), 0, FALSE, 0, PciNode, NULL);
+
+    Status = PciGetProtocolAndResource (
+               HandleBuf[Index],
+               &IoDev,
+               &Descriptors
+               );
+
+    while ((*Descriptors).Desc != ACPI_END_TAG_DESCRIPTOR) {
+      if (((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
+          ((*Descriptors).AddrSpaceGranularity == 0x20))
+      {
+        AmlCodeGenRdDWordMemory (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          1,
+          TRUE,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          0,
+          TRUE,
+          RbufRt,
+          NULL
+          );
+      }
+
+      if (((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
+          ((*Descriptors).AddrSpaceGranularity == 0x40))
+      {
+        AmlCodeGenRdQWordMemory (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          TRUE,
+          TRUE,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          0,
+          TRUE,
+          RbufRt,
+          NULL
+          );
+      }
+
+      if ((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+        AmlCodeGenRdDWordIo (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          3,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          FALSE,
+          TRUE,
+          RbufRt,
+          NULL
+          );
+      }
+
+      if ((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+        AmlCodeGenNameInteger ("_BBN", (*Descriptors).AddrRangeMin, PciNode, NULL);
+        AmlCodeGenRdWordBusNumber (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          RbufRt,
+          NULL
+          );
+      }
+
+      (Descriptors)++;
+    }
+
+    DEBUG ((DEBUG_INFO, "\n"));
+
+    AmlCodeGenMethodRetNameString ("_CRS", "RBUF", 0, TRUE, 0, PciNode, NULL);
+    PcieDeviceStatus = 0xF; // STATUS_PRESENT | STATUS_ENABLED | STATUS_SHOWN_IN_UI | STATUS_FUNCTIONING;
+    AmlCodeGenMethodRetInteger ("_STA", PcieDeviceStatus, 0, TRUE, 0, PciNode, NULL);
+
+    AmlCodeGenNameInteger ("SUPP", 0, PciNode, NULL);
+    AmlCodeGenNameInteger ("CTRL", 0, PciNode, NULL);
+
+    AddOscMethod (PciNode);
+
+    if (Index == 0) {
+      // first node
+      AmlCodeGenDevice ("RES0", PciNode, &ResNode);
+      Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId);
+      if (EFI_ERROR (Status)) {
+        ASSERT (0);
+        return Status;
+      }
+
+      AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);
+
+      AmlCodeGenNameResourceTemplate ("_CRS", ResNode, &ResRt);
+      AmlCodeGenRdQWordMemory (
+        FALSE,
+        TRUE,
+        TRUE,
+        TRUE,
+        FALSE,
+        TRUE,
+        0,
+        PcdGet64 (PcdPciExpressBaseAddress), // Range Minimum
+        PcdGet64 (PcdPciExpressBarLimit),    // Range Maximum
+        0x0000000000000000,                       // Translation Offset
+        PcdGet64 (PcdPciExpressBarSize),     // Length
+        //   Bridge->Mem.Base,
+        //   Bridge->Mem.Limit,
+        //   FixedPcdGet32 (PcdPciMmio32Translation),
+        //   Bridge->Mem.Limit - Bridge->Mem.Base + 1,
+        0,
+        NULL /* ResourceSource */,
+        0 /* MemoryRangeType */,
+        TRUE /* IsTypeStatic */,
+        ResRt,
+        NULL
+        );
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl b/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl
index c134fb66e860..1c8d4fe4f647 100644
--- a/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl
+++ b/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl
@@ -181,307 +181,5 @@ DefinitionBlock ("DsdtTable.aml", "DSDT",
             } // USB0_RHUB_HUB1
         } // USB0_RHUB
     } // USB0
-
-    Device (PCI0)
-    {
-      Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
-      Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
-      Name (_SEG, Zero) // PCI Segment Group number
-      Name (_BBN, Zero) // PCI Base Bus Number
-      Name (_UID, "PCI0")
-      Name (_CCA, One)    // Initially mark the PCI coherent (for JunoR1)
-
-      Method (_STA) {
-        Return (0xF)
-      }
-
-      Method (_CBA, 0, NotSerialized) {
-          return (FixedPcdGet32 (PcdPciExpressBaseAddress))
-      }
-
-      LINK_DEVICE(0, GSI0, 0x23)
-      LINK_DEVICE(1, GSI1, 0x24)
-      LINK_DEVICE(2, GSI2, 0x25)
-      LINK_DEVICE(3, GSI3, 0x26)
-
-      Name (_PRT, Package ()  // _PRT: PCI Routing Table
-      {
-        PRT_ENTRY(0x0000FFFF, 0, GSI0),
-        PRT_ENTRY(0x0000FFFF, 0, GSI1),
-        PRT_ENTRY(0x0000FFFF, 0, GSI2),
-        PRT_ENTRY(0x0000FFFF, 0, GSI3),
-
-        PRT_ENTRY(0x0001FFFF, 0, GSI1),
-        PRT_ENTRY(0x0001FFFF, 1, GSI2),
-        PRT_ENTRY(0x0001FFFF, 2, GSI3),
-        PRT_ENTRY(0x0001FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0002FFFF, 0, GSI2),
-        PRT_ENTRY(0x0002FFFF, 1, GSI3),
-        PRT_ENTRY(0x0002FFFF, 2, GSI0),
-        PRT_ENTRY(0x0002FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0003FFFF, 0, GSI3),
-        PRT_ENTRY(0x0003FFFF, 1, GSI0),
-        PRT_ENTRY(0x0003FFFF, 2, GSI1),
-        PRT_ENTRY(0x0003FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0004FFFF, 0, GSI0),
-        PRT_ENTRY(0x0004FFFF, 1, GSI1),
-        PRT_ENTRY(0x0004FFFF, 2, GSI2),
-        PRT_ENTRY(0x0004FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0005FFFF, 0, GSI1),
-        PRT_ENTRY(0x0005FFFF, 1, GSI2),
-        PRT_ENTRY(0x0005FFFF, 2, GSI3),
-        PRT_ENTRY(0x0005FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0006FFFF, 0, GSI2),
-        PRT_ENTRY(0x0006FFFF, 1, GSI3),
-        PRT_ENTRY(0x0006FFFF, 2, GSI0),
-        PRT_ENTRY(0x0006FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0007FFFF, 0, GSI3),
-        PRT_ENTRY(0x0007FFFF, 1, GSI0),
-        PRT_ENTRY(0x0007FFFF, 2, GSI1),
-        PRT_ENTRY(0x0007FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0008FFFF, 0, GSI0),
-        PRT_ENTRY(0x0008FFFF, 1, GSI1),
-        PRT_ENTRY(0x0008FFFF, 2, GSI2),
-        PRT_ENTRY(0x0008FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0009FFFF, 0, GSI1),
-        PRT_ENTRY(0x0009FFFF, 1, GSI2),
-        PRT_ENTRY(0x0009FFFF, 2, GSI3),
-        PRT_ENTRY(0x0009FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x000AFFFF, 0, GSI2),
-        PRT_ENTRY(0x000AFFFF, 1, GSI3),
-        PRT_ENTRY(0x000AFFFF, 2, GSI0),
-        PRT_ENTRY(0x000AFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x000BFFFF, 0, GSI3),
-        PRT_ENTRY(0x000BFFFF, 1, GSI0),
-        PRT_ENTRY(0x000BFFFF, 2, GSI1),
-        PRT_ENTRY(0x000BFFFF, 3, GSI2),
-
-        PRT_ENTRY(0x000CFFFF, 0, GSI0),
-        PRT_ENTRY(0x000CFFFF, 1, GSI1),
-        PRT_ENTRY(0x000CFFFF, 2, GSI2),
-        PRT_ENTRY(0x000CFFFF, 3, GSI3),
-
-        PRT_ENTRY(0x000DFFFF, 0, GSI1),
-        PRT_ENTRY(0x000DFFFF, 1, GSI2),
-        PRT_ENTRY(0x000DFFFF, 2, GSI3),
-        PRT_ENTRY(0x000DFFFF, 3, GSI0),
-
-        PRT_ENTRY(0x000EFFFF, 0, GSI2),
-        PRT_ENTRY(0x000EFFFF, 1, GSI3),
-        PRT_ENTRY(0x000EFFFF, 2, GSI0),
-        PRT_ENTRY(0x000EFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x000FFFFF, 0, GSI3),
-        PRT_ENTRY(0x000FFFFF, 1, GSI0),
-        PRT_ENTRY(0x000FFFFF, 2, GSI1),
-        PRT_ENTRY(0x000FFFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0010FFFF, 0, GSI0),
-        PRT_ENTRY(0x0010FFFF, 1, GSI1),
-        PRT_ENTRY(0x0010FFFF, 2, GSI2),
-        PRT_ENTRY(0x0010FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0011FFFF, 0, GSI1),
-        PRT_ENTRY(0x0011FFFF, 1, GSI2),
-        PRT_ENTRY(0x0011FFFF, 2, GSI3),
-        PRT_ENTRY(0x0011FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0012FFFF, 0, GSI2),
-        PRT_ENTRY(0x0012FFFF, 1, GSI3),
-        PRT_ENTRY(0x0012FFFF, 2, GSI0),
-        PRT_ENTRY(0x0012FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0013FFFF, 0, GSI3),
-        PRT_ENTRY(0x0013FFFF, 1, GSI0),
-        PRT_ENTRY(0x0013FFFF, 2, GSI1),
-        PRT_ENTRY(0x0013FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0014FFFF, 0, GSI0),
-        PRT_ENTRY(0x0014FFFF, 1, GSI1),
-        PRT_ENTRY(0x0014FFFF, 2, GSI2),
-        PRT_ENTRY(0x0014FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0015FFFF, 0, GSI1),
-        PRT_ENTRY(0x0015FFFF, 1, GSI2),
-        PRT_ENTRY(0x0015FFFF, 2, GSI3),
-        PRT_ENTRY(0x0015FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0016FFFF, 0, GSI2),
-        PRT_ENTRY(0x0016FFFF, 1, GSI3),
-        PRT_ENTRY(0x0016FFFF, 2, GSI0),
-        PRT_ENTRY(0x0016FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0017FFFF, 0, GSI3),
-        PRT_ENTRY(0x0017FFFF, 1, GSI0),
-        PRT_ENTRY(0x0017FFFF, 2, GSI1),
-        PRT_ENTRY(0x0017FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0018FFFF, 0, GSI0),
-        PRT_ENTRY(0x0018FFFF, 1, GSI1),
-        PRT_ENTRY(0x0018FFFF, 2, GSI2),
-        PRT_ENTRY(0x0018FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0019FFFF, 0, GSI1),
-        PRT_ENTRY(0x0019FFFF, 1, GSI2),
-        PRT_ENTRY(0x0019FFFF, 2, GSI3),
-        PRT_ENTRY(0x0019FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x001AFFFF, 0, GSI2),
-        PRT_ENTRY(0x001AFFFF, 1, GSI3),
-        PRT_ENTRY(0x001AFFFF, 2, GSI0),
-        PRT_ENTRY(0x001AFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x001BFFFF, 0, GSI3),
-        PRT_ENTRY(0x001BFFFF, 1, GSI0),
-        PRT_ENTRY(0x001BFFFF, 2, GSI1),
-        PRT_ENTRY(0x001BFFFF, 3, GSI2),
-
-        PRT_ENTRY(0x001CFFFF, 0, GSI0),
-        PRT_ENTRY(0x001CFFFF, 1, GSI1),
-        PRT_ENTRY(0x001CFFFF, 2, GSI2),
-        PRT_ENTRY(0x001CFFFF, 3, GSI3),
-
-        PRT_ENTRY(0x001DFFFF, 0, GSI1),
-        PRT_ENTRY(0x001DFFFF, 1, GSI2),
-        PRT_ENTRY(0x001DFFFF, 2, GSI3),
-        PRT_ENTRY(0x001DFFFF, 3, GSI0),
-
-        PRT_ENTRY(0x001EFFFF, 0, GSI2),
-        PRT_ENTRY(0x001EFFFF, 1, GSI3),
-        PRT_ENTRY(0x001EFFFF, 2, GSI0),
-        PRT_ENTRY(0x001EFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x001FFFFF, 0, GSI3),
-        PRT_ENTRY(0x001FFFFF, 1, GSI0),
-        PRT_ENTRY(0x001FFFFF, 2, GSI1),
-        PRT_ENTRY(0x001FFFFF, 3, GSI2),
-      })
-
-      // Root complex resources
-      Name (_CRS, ResourceTemplate () {
-        WordBusNumber ( // Bus numbers assigned to this root
-        ResourceProducer,
-        MinFixed, MaxFixed, PosDecode,
-        0,   // AddressGranularity
-        FixedPcdGet32 (PcdPciBusMin),   // AddressMinimum - Minimum Bus Number
-        FixedPcdGet32 (PcdPciBusMax),   // AddressMaximum - Maximum Bus Number
-        0,   // AddressTranslation - Set to 0
-        256  // RangeLength - Number of Busses
-        )
-
-        DWordMemory ( // 32-bit BAR Windows
-          ResourceProducer, PosDecode,
-          MinFixed, MaxFixed,
-          Cacheable, ReadWrite,
-          0x00000000,                              // Granularity
-          FixedPcdGet32 (PcdPciMmio32Base),        // Min Base Address
-          FixedPcdGet32 (PcdPciMmio32Limit),       // Max Base Address
-          FixedPcdGet32 (PcdPciMmio32Translation), // Translate
-          FixedPcdGet32 (PcdPciMmio32Size)         // Length
-          )
-
-        QWordMemory ( // 64-bit BAR Windows
-          ResourceProducer, PosDecode,
-          MinFixed, MaxFixed,
-          Cacheable, ReadWrite,
-          0x00000000,                              // Granularity
-          FixedPcdGet64 (PcdPciMmio64Base),        // Min Base Address
-          FixedPcdGet64 (PcdPciMmio64Limit),       // Max Base Address
-          FixedPcdGet64 (PcdPciMmio64Translation), // Translate
-          FixedPcdGet64 (PcdPciMmio64Size)         // Length
-          )
-
-        DWordIo ( // IO window
-          ResourceProducer,
-          MinFixed,
-          MaxFixed,
-          PosDecode,
-          EntireRange,
-          0x00000000,                              // Granularity
-          FixedPcdGet32 (PcdPciIoBase),            // Min Base Address
-          FixedPcdGet32 (PcdPciIoLimit),           // Max Base Address
-          FixedPcdGet32 (PcdPciIoTranslation),     // Translate
-          FixedPcdGet32 (PcdPciIoSize),            // Length
-          ,,,TypeTranslation
-          )
-      }) // Name(_CRS)
-
-      Device (RES0)
-      {
-        Name (_HID, "PNP0C02" /* PNP Motherboard Resources */)  // _HID: Hardware ID
-        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
-        {
-           QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
-           0x0000000000000000,                       // Granularity
-           FixedPcdGet64 (PcdPciExpressBaseAddress), // Range Minimum
-           FixedPcdGet64 (PcdPciExpressBarLimit),    // Range Maximum
-           0x0000000000000000,                       // Translation Offset
-           FixedPcdGet64 (PcdPciExpressBarSize),     // Length
-           ,, , AddressRangeMemory, TypeStatic)
-        })
-        Method (_STA) {
-          Return (0xF)
-        }
-      }
-
-      // OS Control Handoff
-      Name (SUPP, Zero) // PCI _OSC Support Field value
-      Name (CTRL, Zero) // PCI _OSC Control Field value
-
-      /*
-       * See [1] 6.2.10, [2] 4.5
-       */
-      Method (_OSC,4) {
-        // Check for proper UUID
-        If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) {
-          // Create DWord-adressable fields from the Capabilities Buffer
-          CreateDWordField (Arg3,0,CDW1)
-          CreateDWordField (Arg3,4,CDW2)
-          CreateDWordField (Arg3,8,CDW3)
-
-          // Save Capabilities DWord2 & 3
-          Store (CDW2,SUPP)
-          Store (CDW3,CTRL)
-
-          // Only allow native hot plug control if OS supports:
-          // * ASPM
-          // * Clock PM
-          // * MSI/MSI-X
-          If ((SUPP & 0x16) != 0x16) {
-            CTRL &= 0x1E // Mask bit 0 (and undefined bits)
-          }
-
-          // Always allow native PME, AER (no dependencies)
-
-          // Never allow SHPC (no SHPC controller in this system)
-          CTRL &= 0x1D
-
-          If (Arg1 != One) {         // Unknown revision
-            CDW1 |= 0x08
-          }
-
-          If (CDW3 != CTRL) {        // Capabilities bits were masked
-            CDW1 |= 0x10
-          }
-
-          // Update DWORD3 in the buffer
-          Store (CTRL,CDW3)
-          Return (Arg3)
-        } Else {
-          CDW1 |= 4 // Unrecognized UUID
-          Return (Arg3)
-        }
-      } // End _OSC
-    }
   } // Scope (_SB)
 }
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl
new file mode 100644
index 000000000000..2fcdb607d173
--- /dev/null
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl
@@ -0,0 +1,82 @@
+/** @file
+*  Differentiated System Description Table Fields (DSDT).
+*
+*  Copyright (c) 2024, Linaro Ltd. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <IndustryStandard/Acpi63.h>
+#include <IndustryStandard/SbsaQemuAcpi.h>
+
+#define LINK_DEVICE(Uid, LinkName, Irq)                                        \
+        Device (LinkName) {                                                    \
+            Name (_HID, EISAID("PNP0C0F"))                                     \
+            Name (_UID, Uid)                                                   \
+            Name (_PRS, ResourceTemplate() {                                   \
+                Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { Irq } \
+            })                                                                 \
+            Method (_CRS, 0) { Return (_PRS) }                                 \
+            Method (_SRS, 1) { }                                               \
+            Method (_DIS) { }                                                  \
+        }
+
+#define PRT_ENTRY(Address, Pin, Link)                                          \
+        Package (4) {                                                          \
+            Address, Pin, Link, Zero                                           \
+          }
+
+DefinitionBlock ("Dsdt.aml", "DSDT",
+                 EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION,
+                 "LINARO", "SBSAQEMU", FixedPcdGet32 (PcdAcpiDefaultOemRevision)) {
+      /*
+       * See [1] 6.2.10, [2] 4.5
+       */
+      Name (SUPP, Zero) // PCI _OSC Support Field value
+      Name (CTRL, Zero) // PCI _OSC Control Field value
+      Method (_OSC, 4, Serialized) {
+        //
+        // OS Control Handoff
+        //
+
+        // Check for proper UUID
+        If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) {
+          // Create DWord-adressable fields from the Capabilities Buffer
+          CreateDWordField (Arg3,0,CDW1)
+          CreateDWordField (Arg3,4,CDW2)
+          CreateDWordField (Arg3,8,CDW3)
+
+          // Save Capabilities DWord2 & 3
+          Store (CDW2,SUPP)
+          Store (CDW3,CTRL)
+
+          // Only allow native hot plug control if OS supports:
+          // * ASPM
+          // * Clock PM
+          // * MSI/MSI-X
+          If ((SUPP & 0x16) != 0x16) {
+            CTRL |= 0x1E // Mask bit 0 (and undefined bits)
+          }
+
+          // Always allow native PME, AER (no dependencies)
+
+          // Never allow SHPC (no SHPC controller in this system)
+          CTRL &= 0x1D
+
+          If (Arg1 != One) {        // Unknown revision
+            CDW1 |= 0x08
+          }
+
+          If (CDW3 != CTRL) {        // Capabilities bits were masked
+            CDW1 |= 0x10
+          }
+
+          // Update DWORD3 in the buffer
+          Store (CTRL,CDW3)
+          Return (Arg3)
+        } Else {
+          CDW1 |= 4 // Unrecognized UUID
+          Return (Arg3)
+        }
+      } // End _OSC
+}

-- 
2.45.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119302): https://edk2.groups.io/g/devel/message/119302
Mute This Topic: https://groups.io/mt/106345971/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [edk2-devel] [PATCH edk2-platforms v2 3/3] SbsaQemu: generate MCFG table
  2024-05-28 10:31 [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Marcin Juszkiewicz
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 1/3] SbsaQemu: scan for PCIe buses Marcin Juszkiewicz
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 2/3] SbsaQemu: describe PCIe buses in SSDT tables Marcin Juszkiewicz
@ 2024-05-28 10:31 ` Marcin Juszkiewicz
  2024-05-28 14:31 ` [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Ard Biesheuvel
  3 siblings, 0 replies; 7+ messages in thread
From: Marcin Juszkiewicz @ 2024-05-28 10:31 UTC (permalink / raw)
  To: devel
  Cc: Leif Lindholm, Ard Biesheuvel, Graeme Gregory, Ray Ni,
	Marcin Juszkiewicz

We want to have dynaminc PCI Express variables. Which forces us to
generate MCFG from C code.

Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
---
 Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf      |  1 -
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c        | 83 ++++++++++++++++++++
 Silicon/Qemu/SbsaQemu/AcpiTables/Mcfg.aslc           | 43 ----------
 3 files changed, 83 insertions(+), 44 deletions(-)

diff --git a/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf b/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf
index 8d4905362edc..37abf2f4c512 100644
--- a/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf
+++ b/Silicon/Qemu/SbsaQemu/AcpiTables/AcpiTables.inf
@@ -19,7 +19,6 @@ [Sources]
   Dbg2.aslc
   Dsdt.asl
   Fadt.aslc
-  Mcfg.aslc
   Spcr.aslc
 
 [Packages]
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
index f3d5dc9e9ba7..6c7913eead81 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
@@ -7,6 +7,7 @@
 *
 **/
 #include <IndustryStandard/IoRemappingTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
 #include <IndustryStandard/SbsaQemuAcpi.h>
 #include <IndustryStandard/SbsaQemuPlatformVersion.h>
 
@@ -883,6 +884,83 @@ AddSsdtPcieTable (
   return EFI_SUCCESS;
 }
 
+/** Adds the MCFG ACPI table.
+
+  @param AcpiTable        The ACPI Table.
+  @param PcieCfgData      PCIe configuration data.
+  @param NumPcieSegments  Number of PCIe segments.
+
+  @return EFI_SUCCESS on success, or an error code.
+
+**/
+STATIC
+EFI_STATUS
+AddMcfgTable (
+  IN EFI_ACPI_TABLE_PROTOCOL  *AcpiTable
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 TableHandle;
+  UINT32                TableSize;
+  EFI_PHYSICAL_ADDRESS  PageAddress;
+  UINT8                 *New;
+
+  EFI_ACPI_DESCRIPTION_HEADER  Header =
+    SBSAQEMU_ACPI_HEADER (
+      EFI_ACPI_6_3_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+      EFI_ACPI_DESCRIPTION_HEADER,
+      EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
+      );
+
+  TableSize = sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER) +
+              sizeof (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE);
+
+  Status = gBS->AllocatePages (
+                  AllocateAnyPages,
+                  EfiACPIReclaimMemory,
+                  EFI_SIZE_TO_PAGES (TableSize),
+                  &PageAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to allocate pages for MCFG table\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  New = (UINT8 *)(UINTN)PageAddress;
+  ZeroMem (New, TableSize);
+
+  // Add the  ACPI Description table header
+  CopyMem (New, &Header, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+  ((EFI_ACPI_DESCRIPTION_HEADER *)New)->Length = TableSize;
+  New                                         += sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER);
+
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE  *CfgPtr;
+
+  CfgPtr = (VOID *)New;
+
+  CfgPtr->BaseAddress           = PcdGet64 (PcdPciExpressBaseAddress);
+  CfgPtr->PciSegmentGroupNumber = 0;
+  CfgPtr->StartBusNumber        = PcdGet32 (PcdPciBusMin);
+  CfgPtr->EndBusNumber          = PcdGet32 (PcdPciBusMax);
+
+  New += sizeof (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE);
+
+  // Perform Checksum
+  AcpiTableChecksum ((UINT8 *)PageAddress, TableSize);
+
+  Status = AcpiTable->InstallAcpiTable (
+                        AcpiTable,
+                        (EFI_ACPI_COMMON_HEADER *)PageAddress,
+                        TableSize,
+                        &TableHandle
+                        );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to install MCFG table\n"));
+  }
+
+  return Status;
+}
+
 
 EFI_STATUS
 EFIAPI
@@ -951,6 +1029,11 @@ InitializeSbsaQemuAcpiDxe (
     DEBUG ((DEBUG_ERROR, "Failed to add SSDT table\n"));
   }
 
+  Status = AddMcfgTable (AcpiTable);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to add MCFG table\n"));
+  }
+
 
   return EFI_SUCCESS;
 }
diff --git a/Silicon/Qemu/SbsaQemu/AcpiTables/Mcfg.aslc b/Silicon/Qemu/SbsaQemu/AcpiTables/Mcfg.aslc
deleted file mode 100644
index 289f4ad4ea3a..000000000000
--- a/Silicon/Qemu/SbsaQemu/AcpiTables/Mcfg.aslc
+++ /dev/null
@@ -1,43 +0,0 @@
-/** @file
-*  ACPI Memory mapped configuration space base address Description Table (MCFG).
-*
-*  Copyright (c) 2020, Linaro Limited. All rights reserved.
-*
-*  SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include <IndustryStandard/Acpi.h>
-#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
-#include <IndustryStandard/SbsaQemuAcpi.h>
-
-#pragma pack(push, 1)
-
-typedef struct {
-  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
-  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure[1];
-} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;
-
-EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg = {
-  {
-    SBSAQEMU_ACPI_HEADER (
-      EFI_ACPI_6_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
-      EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE,
-      EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
-    EFI_ACPI_RESERVED_QWORD
-  },
-  {
-    {
-      FixedPcdGet32 (PcdPciExpressBaseAddress),
-      0,
-      FixedPcdGet32 (PcdPciBusMin),
-      FixedPcdGet32 (PcdPciBusMax),
-      EFI_ACPI_RESERVED_DWORD
-    }
-  }
-};
-
-#pragma pack(pop)
-
-// Reference the table being generated to prevent the optimizer
-// from removing the data structure from the executable
-VOID* CONST ReferenceAcpiTable = &Mcfg;

-- 
2.45.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119303): https://edk2.groups.io/g/devel/message/119303
Mute This Topic: https://groups.io/mt/106345972/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses
  2024-05-28 10:31 [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Marcin Juszkiewicz
                   ` (2 preceding siblings ...)
  2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 3/3] SbsaQemu: generate MCFG table Marcin Juszkiewicz
@ 2024-05-28 14:31 ` Ard Biesheuvel
  2024-06-04  7:23   ` Marcin Juszkiewicz
  3 siblings, 1 reply; 7+ messages in thread
From: Ard Biesheuvel @ 2024-05-28 14:31 UTC (permalink / raw)
  To: devel, marcin.juszkiewicz; +Cc: Leif Lindholm, Graeme Gregory, Ray Ni

On Tue, 28 May 2024 at 12:31, Marcin Juszkiewicz
<marcin.juszkiewicz@linaro.org> wrote:
>
> QEMU allows to have NUMA setup where each node has own cpus, memory and
> i/o. We already handle cpus and memory. This patchset adds support for
> having multiple PCI Express buses.
>
> SbsaQemu assumed that there is only bus 0. First patch does PCIe bus
> scan to find all host bridges (bus 0 one and additional 'pxb-pcie'
> ones).
>
> Second patch moves description of PCIe from DSDT to SSDT (one per each
> PCIe bus). So Operating System will know about all of them.
>
> Third patch moves generation of MCFG table to C. It is preparation to
> move PCIe Pcds from being fixed to dynamic ones.
>
> There are some booting issues with assigning resources for cards:
>
> pci 0000:00:03.0: BAR 15: no space for [mem size 0x00200000 64bit pref]
> pci 0000:00:03.0: BAR 15: failed to assign [mem size 0x00200000 64bit pref]
> pci 0000:00:01.0: BAR 6: no space for [mem size 0x00040000 pref]
> pci 0000:00:01.0: BAR 6: failed to assign [mem size 0x00040000 pref]
> pci 0000:00:03.0: BAR 13: no space for [io  size 0x1000]
> pci 0000:00:03.0: BAR 13: failed to assign [io  size 0x1000]
>
> Boot log (Linux + lspci + ACPI tables dump):
> https://people.linaro.org/~marcin.juszkiewicz/sbsa-ref/boot-linux-with-numa-multiple-pcie-buses.txt
>
> I am wondering where I made mistakes in handling PCIe buses.
>

I would expect each host bridge to have its own separate resource
windows for config space, buses and MMIO regions.

So each host bridge gets a different segment number, and each segment
is associated with a different ECAM region. That also means the bus
range can start at 0x0 for each segment, as they are completely
disjoint.

This is a more accurate representation of the physical topology, given
that each host bridge has its own link to the CPU side interconnect,
and so things like peer-to-peer DMA between endpoints does not
generally work unless the endpoints share a segment, especially in the
presence of SMMUs.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119308): https://edk2.groups.io/g/devel/message/119308
Mute This Topic: https://groups.io/mt/106345969/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses
  2024-05-28 14:31 ` [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Ard Biesheuvel
@ 2024-06-04  7:23   ` Marcin Juszkiewicz
  2024-06-04 12:06     ` Gerd Hoffmann
  0 siblings, 1 reply; 7+ messages in thread
From: Marcin Juszkiewicz @ 2024-06-04  7:23 UTC (permalink / raw)
  To: Ard Biesheuvel, devel; +Cc: Leif Lindholm, Graeme Gregory, Ray Ni

W dniu 28.05.2024 o 16:31, Ard Biesheuvel pisze:
> I would expect each host bridge to have its own separate resource
> windows for config space, buses and MMIO regions.
> 
> So each host bridge gets a different segment number, and each segment
> is associated with a different ECAM region. That also means the bus
> range can start at 0x0 for each segment, as they are completely
> disjoint.
> 
> This is a more accurate representation of the physical topology, given
> that each host bridge has its own link to the CPU side interconnect,
> and so things like peer-to-peer DMA between endpoints does not
> generally work unless the endpoints share a segment, especially in the
> presence of SMMUs.

OK. I have to admit that I never checked how physical NUMA system 
handles PCI Express. The code in patches was done by comparing with 
other QEMU targets.

To make PCIe in a way you describe we probably need to go to QEMU devel 
ML and discuss how it can be done there. Or I did not got deep enough 
into PCIe world to notice how to make it happen with current implementation.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119442): https://edk2.groups.io/g/devel/message/119442
Mute This Topic: https://groups.io/mt/106345969/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses
  2024-06-04  7:23   ` Marcin Juszkiewicz
@ 2024-06-04 12:06     ` Gerd Hoffmann
  0 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2024-06-04 12:06 UTC (permalink / raw)
  To: devel, marcin.juszkiewicz
  Cc: Ard Biesheuvel, Leif Lindholm, Graeme Gregory, Ray Ni

On Tue, Jun 04, 2024 at 09:23:30AM GMT, Marcin Juszkiewicz wrote:
> W dniu 28.05.2024 o 16:31, Ard Biesheuvel pisze:
> > I would expect each host bridge to have its own separate resource
> > windows for config space, buses and MMIO regions.

That isn't how qemu pxb-pcie host bridge works on x86 though.  It does
*not* create a separate pci domain and resources such as bus numbers are
shared.

> OK. I have to admit that I never checked how physical NUMA system handles
> PCI Express. The code in patches was done by comparing with other QEMU
> targets.

It's probably not that easy.  On x86 initialization works like this:

 (1) the firmware sets up bridge windows and pci bars.
 (2) qemu generates acpi tables with matching _CRS ranges.
 (3) the firmware downloads and installs the acpi tables.

On arm qemu does the resource allocation for the root bridge windows and
communicates them to the firmware via FDT, so stealing ideas from x86
probably isn't going to work very well.

I think one option would be to have the firmware split the ranges it
got and distribute them across the root bridges, program the root
windows accordingly, generate acpi tables accordingly.

Going for a separate pci domain with separate ecam and separate bus
namespace and separate mmio ressources should be possible too, but that
most likely will need a bunch of changes on the qemu side.

HTH & take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#119445): https://edk2.groups.io/g/devel/message/119445
Mute This Topic: https://groups.io/mt/106345969/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-06-04 12:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-28 10:31 [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Marcin Juszkiewicz
2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 1/3] SbsaQemu: scan for PCIe buses Marcin Juszkiewicz
2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 2/3] SbsaQemu: describe PCIe buses in SSDT tables Marcin Juszkiewicz
2024-05-28 10:31 ` [edk2-devel] [PATCH edk2-platforms v2 3/3] SbsaQemu: generate MCFG table Marcin Juszkiewicz
2024-05-28 14:31 ` [edk2-devel] [PATCH edk2-platforms v2 0/3] SbsaQemu: support multiple PCI Express buses Ard Biesheuvel
2024-06-04  7:23   ` Marcin Juszkiewicz
2024-06-04 12:06     ` Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox