add mcfg table. mcfg isn't populated at the moment. dev-q35 will use it later.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/acpi.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/acpi.h | 17 ++++++++++++++++ src/post.h | 14 +++++++++++++ 3 files changed, 93 insertions(+), 0 deletions(-) create mode 100644 src/post.h
diff --git a/src/acpi.c b/src/acpi.c index e91f8e0..d61ae16 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -13,6 +13,7 @@ #include "pci_regs.h" // PCI_INTERRUPT_LINE #include "paravirt.h" #include "dev-i440fx.h" // piix4_fadt_init +#include "post.h"
/****************************************************/ /* ACPI tables init */ @@ -522,6 +523,66 @@ build_srat(void) return srat; }
+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 acpi_mcfg acpi_mcfg = { + .nr = 0, + .mcfg = NULL, + .e820 = NULL, + }; + int bdf = pci_find_init_device(mcfg_find_tbl, &acpi_mcfg); + 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, bdf, &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), @@ -568,6 +629,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 e01315a..798fb19 100644 --- a/src/acpi.h +++ b/src/acpi.h @@ -98,4 +98,21 @@ struct fadt_descriptor_rev1 #endif } 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/post.h b/src/post.h new file mode 100644 index 0000000..04e506d --- /dev/null +++ b/src/post.h @@ -0,0 +1,14 @@ +#ifndef __POST_H +#define __POST_H + +#include "memmap.h" // struct e820entry +#include "acpi.h" // struct acpi_table_mcfg + +struct acpi_mcfg +{ + u32 nr; + struct acpi_table_mcfg *mcfg; + struct e820entry *e820; +}; + +#endif /* __POST_H */