Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/acpi.c | 22 ++++++++++++++++++++++ src/acpi.h | 17 +++++++++++++++++ src/pci.h | 1 + src/pciinit.c | 9 +++++++++ 4 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 72c8fe8..456f8f7 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -764,6 +764,27 @@ build_srat(void) return srat; }
+static void * +build_mcfg(void) +{ + struct acpi_table_mcfg *mcfg; + + if (!mmconfig.address) + return NULL; + + int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]); + mcfg = malloc_high(len); + if (!mcfg) { + warn_noalloc(); + return NULL; + } + memset(mcfg, 0, len); + mcfg->allocation[0] = mmconfig; + + build_header((void *)mcfg, MCFG_SIGNATURE, len, 1); + return mcfg; +} + static const struct pci_device_id acpi_find_tbl[] = { /* PIIX4 Power Management device. */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL), @@ -804,6 +825,7 @@ acpi_bios_init(void) ACPI_INIT_TABLE(build_madt()); ACPI_INIT_TABLE(build_hpet()); ACPI_INIT_TABLE(build_srat()); + ACPI_INIT_TABLE(build_mcfg());
u16 i, external_tables = qemu_cfg_acpi_additional_tables();
diff --git a/src/acpi.h b/src/acpi.h index cb21561..715d19d 100644 --- a/src/acpi.h +++ b/src/acpi.h @@ -107,4 +107,21 @@ struct bfld { u64 p1l; /* pci window 1 (above 4g) - length */ } PACKED;
+/* PCI fw r3.0 MCFG table. */ +/* Subtable */ +struct acpi_mcfg_allocation { + u64 address; /* Base address, processor-relative */ + u16 pci_segment; /* PCI segment group number */ + u8 start_bus_number; /* Starting PCI Bus number */ + u8 end_bus_number; /* Final PCI Bus number */ + u32 reserved; +} PACKED; + +#define MCFG_SIGNATURE 0x4746434d // MCFG +struct acpi_table_mcfg { + ACPI_TABLE_HEADER_DEF; + u8 reserved[8]; + struct acpi_mcfg_allocation allocation[0]; +} PACKED; + #endif // acpi.h diff --git a/src/pci.h b/src/pci.h index 104638d..04f79f2 100644 --- a/src/pci.h +++ b/src/pci.h @@ -59,6 +59,7 @@ struct pci_device { extern u64 mtrr_base; extern u64 pcimem_start, pcimem_end; extern u64 pcimem64_start, pcimem64_end; +extern struct acpi_mcfg_allocation mmconfig; extern struct pci_device *PCIDevices; extern int MaxPCIBus; int pci_probe_host(void); diff --git a/src/pciinit.c b/src/pciinit.c index 091d0e6..3bdeeca 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -13,6 +13,7 @@ #include "config.h" // CONFIG_* #include "xen.h" // usingXen #include "memmap.h" // add_e820 +#include "acpi.h" // acpi_table_mcfg #include "dev-q35.h"
#define PCI_DEVICE_MEM_MIN 0x1000 @@ -39,6 +40,8 @@ u64 pcimem_end = BUILD_PCIMEM_END; u64 pcimem64_start = BUILD_PCIMEM64_START; u64 pcimem64_end = BUILD_PCIMEM64_END;
+struct acpi_mcfg_allocation mmconfig; + struct pci_region_entry { struct pci_device *dev; int bar; @@ -687,6 +690,12 @@ void mch_mem_addr_init(struct pci_device *dev, void *arg) pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower); add_e820(addr, size, E820_RESERVED);
+ /* for build_mcfg */ + mmconfig.address = addr; + mmconfig.pci_segment = Q35_HOST_PCIE_PCI_SEGMENT; + mmconfig.start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER; + mmconfig.end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER; + /* setup pci i/o window (above mmconfig) */ pcimem_start = addr + size; mtrr_base = addr + size;