public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Marcin Juszkiewicz" <marcin.juszkiewicz@linaro.org>
To: devel@edk2.groups.io
Cc: Leif Lindholm <quic_llindhol@quicinc.com>,
	 Ard Biesheuvel <ardb+tianocore@kernel.org>,
	 Graeme Gregory <graeme@xora.org.uk>, Ray Ni <ray.ni@intel.com>,
	 Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
Subject: [edk2-devel] [PATCH edk2-platforms v2 1/3] SbsaQemu: scan for PCIe buses
Date: Tue, 28 May 2024 12:31:38 +0200	[thread overview]
Message-ID: <20240528-review-multiple-pcie-0425-v2-1-e2ec9f098a78@linaro.org> (raw)
In-Reply-To: <20240528-review-multiple-pcie-0425-v2-0-e2ec9f098a78@linaro.org>

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]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2024-05-28 10:31 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20240528-review-multiple-pcie-0425-v2-1-e2ec9f098a78@linaro.org \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

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

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