Load memory window setup for pci from host. This makes it possible for host to make sure setup matches hardware exactly: especially important for when ACPI tables are loaded from host. This will also make it easier to add more chipsets down the road.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- src/pciinit.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index ef5e33b..cc12040 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -15,6 +15,7 @@ #include "paravirt.h" // RamSize #include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR #include "list.h" // struct hlist_node +#include "byteorder.h" // le64_to_cpu
#define PCI_DEVICE_MEM_MIN 0x1000 #define PCI_BRIDGE_IO_MIN 0x1000 @@ -844,15 +845,45 @@ static void pci_bios_map_devices(struct pci_bus *busses, struct pci_mem *mem) } }
+static +int pci_mem_get(struct pci_mem *mem) +{ + int ret; + struct romfile_s *file = romfile_find("etc/pci-info"); + if (!file) + return -1; + + ret = file->copy(file, mem, sizeof(*mem)); + if (ret < (int)sizeof(*mem)) { + dprintf(1, "failed to read %d bytes from etc/pci-info: result %d\n", + (int)sizeof *mem, ret); + return -1; + } + + mem->start32 = le64_to_cpu(mem->start32); + mem->end32 = le64_to_cpu(mem->end32); + mem->start64 = le64_to_cpu(mem->start64); + mem->end64 = le64_to_cpu(mem->end64); + + dprintf(3, "loaded pci setup from etc/pci-info: %llx-%llx %llx-%llx\n", + (long long)mem->start32, + (long long)mem->end32, + (long long)mem->start64, + (long long)mem->end64 + ); + + return 0; +} +
/**************************************************************** * Main setup code ****************************************************************/ - void pci_setup(void) { struct pci_mem mem; + int pcimem_is_set;
if (!CONFIG_QEMU) return; @@ -868,7 +899,13 @@ pci_setup(void) dprintf(1, "=== PCI device probing ===\n"); pci_probe_devices();
- pci_bios_init_mem_addr(&mem); + if (pci_mem_get(&mem) < 0) { + pci_bios_init_mem_addr(&mem); + pcimem_is_set = 0; + } else { + pcimem_is_set = 1; + } + pci_bios_init_platform();
dprintf(1, "=== PCI new allocation pass #1 ===\n"); @@ -882,11 +919,20 @@ pci_setup(void) return;
dprintf(1, "=== PCI new allocation pass #2 ===\n"); + if (pcimem_is_set) { + pcimem_start = mem.start32; + pcimem_end = mem.end32; + pcimem64_start = mem.start64; + pcimem64_end = mem.end64; + } pci_bios_map_devices(busses, &mem); - pcimem_start = mem.start32; - pcimem_end = mem.end32; - pcimem64_start = mem.start64; - pcimem64_end = mem.end64; + /* If memory window is not yet set, set it to result of bus scan */ + if (!pcimem_is_set) { + pcimem_start = mem.start32; + pcimem_end = mem.end32; + pcimem64_start = mem.start64; + pcimem64_end = mem.end64; + }
pci_bios_init_devices();