[SeaBIOS] [RFC v3] pciinit: setup mcfg for pxb-pcie to support multiple pci domains

Zihan Yang whois.zihan.yang at gmail.com
Mon Sep 17 17:02:59 CEST 2018


To support multiple pci domains of pxb-pcie device in qemu, we need to setup
mcfg range in seabios. We use [0x80000000, 0xb0000000) to hold new domain mcfg
table for now, and we need to retrieve the desired mcfg size of each pxb-pcie
from a hidden bar because they may not need the whole 256 busses, which also
enables us to support more domains within a limited range (768MB)

Signed-off-by: Zihan Yang <whois.zihan.yang at gmail.com>
---
 src/fw/dev-q35.h |  7 +++++++
 src/fw/pciinit.c | 32 ++++++++++++++++++++++++++++++++
 src/hw/pci_ids.h |  1 +
 3 files changed, 40 insertions(+)

diff --git a/src/fw/dev-q35.h b/src/fw/dev-q35.h
index 201825d..229cd81 100644
--- a/src/fw/dev-q35.h
+++ b/src/fw/dev-q35.h
@@ -49,4 +49,11 @@
 #define ICH9_APM_ACPI_ENABLE           0x2
 #define ICH9_APM_ACPI_DISABLE          0x3
 
+#define PXB_PCIE_HOST_BRIDGE_MCFG_BAR              0x50    /* 64bit register */
+#define PXB_PCIE_HOST_BRIDGE_MCFG_SIZE             0x58    /* 32bit register */
+#define PXB_PCIE_HOST_BRIDGE_ENABLE                Q35_HOST_BRIDGE_PCIEXBAREN
+/* pxb-pcie can use [0x80000000, 0xb0000000), be careful not to overflow */
+#define PXB_PCIE_HOST_BRIDGE_MCFG_SIZE_ADDR        0x80000000
+#define PXB_PCIE_HOST_BRIDGE_MCFG_SIZE_ADDR_UPPER Q35_HOST_BRIDGE_PCIEXBAR_ADDR
+
 #endif // dev-q35.h
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index c0634bc..e0ac22c 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -51,6 +51,7 @@ u64 pcimem_end     = BUILD_PCIMEM_END;
 u64 pcimem64_start = BUILD_PCIMEM64_START;
 u64 pcimem64_end   = BUILD_PCIMEM64_END;
 u64 pci_io_low_end = 0xa000;
+u64 pxb_pcie_mcfg_base = PXB_PCIE_HOST_BRIDGE_MCFG_SIZE_ADDR;
 
 struct pci_region_entry {
     struct pci_device *dev;
@@ -507,11 +508,42 @@ static void mch_mem_addr_setup(struct pci_device *dev, void *arg)
         pci_io_low_end = acpi_pm_base;
 }
 
+static void pxb_pcie_mem_addr_setup(struct pci_device *dev, void *arg)
+{
+    u64 mcfg_base;
+    u32 mcfg_size = pci_config_readl(dev->bdf, PXB_PCIE_HOST_BRIDGE_MCFG_SIZE);
+
+    /* 0 means this pxb-pcie still resides in pci domain 0 */
+    if (mcfg_size == 0)
+        return;
+
+    if (pxb_pcie_mcfg_base + mcfg_size >
+                             PXB_PCIE_HOST_BRIDGE_MCFG_SIZE_ADDR_UPPER) {
+        dprintf(1, "PCI: Not enough space to hold new pci domains\n");
+        return;
+    }
+
+    mcfg_base = pxb_pcie_mcfg_base;
+    pxb_pcie_mcfg_base += mcfg_size;
+
+    /* First clear old mmio, taken care of by QEMU */
+    pci_config_writel(dev->bdf, PXB_PCIE_HOST_BRIDGE_MCFG_BAR, 0);
+    /* Update MCFG base */
+    pci_config_writel(dev->bdf, PXB_PCIE_HOST_BRIDGE_MCFG_BAR + 4,
+                      mcfg_base >> 32);
+    pci_config_writel(dev->bdf, PXB_PCIE_HOST_BRIDGE_MCFG_BAR,
+                      (mcfg_base & 0xffffffff) | PXB_PCIE_HOST_BRIDGE_ENABLE);
+
+    e820_add(mcfg_base, mcfg_size, E820_RESERVED);
+}
+
 static const struct pci_device_id pci_platform_tbl[] = {
     PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
                i440fx_mem_addr_setup),
     PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH,
                mch_mem_addr_setup),
+    PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_PXB_HOST,
+               pxb_pcie_mem_addr_setup),
     PCI_DEVICE_END
 };
 
diff --git a/src/hw/pci_ids.h b/src/hw/pci_ids.h
index 1096461..b495920 100644
--- a/src/hw/pci_ids.h
+++ b/src/hw/pci_ids.h
@@ -2266,6 +2266,7 @@
 #define PCI_VENDOR_ID_REDHAT		0x1b36
 #define PCI_DEVICE_ID_REDHAT_ROOT_PORT	0x000C
 #define PCI_DEVICE_ID_REDHAT_BRIDGE	0x0001
+#define PCI_DEVICE_ID_REDHAT_PXB_HOST   0x000B
 
 #define PCI_VENDOR_ID_TEKRAM		0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
-- 
2.7.4




More information about the SeaBIOS mailing list