From: Isaku Yamahata yamahata@valinux.co.jp
add mcfg table. mcfg isn't populated at the moment. dev-q35 will use it later.
[jbaron@redhat.com: moved header from post.h -> acpi.h] Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp Signed-off-by: Jason Baron jbaron@redhat.com --- src/acpi.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/acpi.h | 17 ++++++++++++++ 2 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 6d239fa..780c0ac 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -13,6 +13,7 @@ #include "pci_regs.h" // PCI_INTERRUPT_LINE #include "ioport.h" // inl #include "paravirt.h" // qemu_cfg_irq0_override +#include "memmap.h"
/****************************************************/ /* ACPI tables init */ @@ -734,6 +735,77 @@ build_srat(void) return srat; }
+struct acpi_mcfg +{ + u32 nr; + struct acpi_table_mcfg *mcfg; + struct e820entry *e820; +}; + +static const struct pci_device_id mcfg_find_tbl[] = { + PCI_DEVICE_END, +}; + +static const struct pci_device_id mcfg_init_tbl[] = { + PCI_DEVICE_END, +}; + +static void * +build_mcfg(void) +{ + struct pci_device *dev; + int bdf; + + struct acpi_mcfg acpi_mcfg = { + .nr = 0, + .mcfg = NULL, + .e820 = NULL, + }; + dev = pci_find_init_device(mcfg_find_tbl, &acpi_mcfg); + bdf = dev->bdf; + if (bdf < 0) { + return NULL; + } + if (acpi_mcfg.nr == 0) { + return NULL; + } + + struct acpi_table_mcfg *mcfg; + int len = sizeof(*mcfg) + acpi_mcfg.nr * sizeof(mcfg->allocation[0]); + mcfg = malloc_high(len); + if (!mcfg) { + dprintf(1, "Not enough memory for mcfg table!\n"); + return NULL; + } + memset(mcfg, 0, len); + acpi_mcfg.mcfg = mcfg; + + + struct e820entry *e820; + int e820_len = acpi_mcfg.nr * sizeof(*e820); + e820 = malloc_tmphigh(e820_len); + if (!e820) { + dprintf(1, "Not enough memory for e820 table!\n"); + free(mcfg); + return NULL; + } + memset(e820, 0, e820_len); + acpi_mcfg.e820 = e820; + + pci_init_device(mcfg_init_tbl, dev, &acpi_mcfg); + + /* Linux checks if e820 covers mcfg area as reserved. + * If no, Linux thinks bios is buggy and won't use MCFG */ + int i; + for (i = 0; i < acpi_mcfg.nr; i++) { + add_e820(e820[i].start, e820[i].size, E820_RESERVED); + } + free(e820); + + 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), @@ -774,6 +846,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