[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