Try to get the pci window information from the qemu firmware config interface and use them if available, otherwise fall back to the compile time defaults.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/paravirt.c | 8 ++++++++ src/paravirt.h | 2 ++ src/pciinit.c | 29 ++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/src/paravirt.c b/src/paravirt.c index 9cf77de..61ed086 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -305,6 +305,14 @@ u16 qemu_cfg_get_max_cpus(void) return cnt; }
+void qemu_cfg_get_pci_windows(u64 *pcimem) +{ + if (!qemu_cfg_present) + return; + + qemu_cfg_read_entry(pcimem, QEMU_CFG_PCI_WINDOWS, 64); +} + static QemuCfgFile LastFile;
static u32 diff --git a/src/paravirt.h b/src/paravirt.h index f39e226..6dc8ede 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -35,6 +35,7 @@ static inline int kvm_para_available(void) #define QEMU_CFG_BOOT_MENU 0x0e #define QEMU_CFG_MAX_CPUS 0x0f #define QEMU_CFG_FILE_DIR 0x19 +#define QEMU_CFG_PCI_WINDOWS 0x1a #define QEMU_CFG_ARCH_LOCAL 0x8000 #define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) #define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) @@ -57,6 +58,7 @@ int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, int qemu_cfg_get_numa_nodes(void); void qemu_cfg_get_numa_data(u64 *data, int n); u16 qemu_cfg_get_max_cpus(void); +void qemu_cfg_get_pci_windows(u64 *pcimem);
typedef struct QemuCfgFile { u32 size; /* file size */ diff --git a/src/pciinit.c b/src/pciinit.c index 6a7a0d2..52c5b69 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -11,6 +11,7 @@ #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_COMMAND #include "xen.h" // usingXen +#include "paravirt.h" // qemu_cfg_get_pci_windows
#define PCI_DEVICE_MEM_MIN 0x1000 #define PCI_BRIDGE_IO_MIN 0x1000 @@ -29,6 +30,12 @@ static const char *region_type_name[] = { [ PCI_REGION_TYPE_PREFMEM ] = "prefmem", };
+static u64 pcimem[4]; +static u64 pcimem_start = BUILD_PCIMEM_START; +static u64 pcimem_end = BUILD_PCIMEM_END; +static u64 pcimem64_start = BUILD_PCIMEM64_START; +static u64 pcimem64_end = BUILD_PCIMEM64_END; + struct pci_region_entry { struct pci_device *dev; int bar; @@ -511,13 +518,13 @@ static int pci_bios_init_root_regions(struct pci_bus *bus) } u64 sum = pci_region_sum(r_end); u64 align = pci_region_align(r_end); - r_end->base = ALIGN_DOWN((BUILD_PCIMEM_END - sum), align); + r_end->base = ALIGN_DOWN((pcimem_end - sum), align); sum = pci_region_sum(r_start); align = pci_region_align(r_start); r_start->base = ALIGN_DOWN((r_end->base - sum), align);
- if ((r_start->base < BUILD_PCIMEM_START) || - (r_start->base > BUILD_PCIMEM_END)) + if ((r_start->base < pcimem_start) || + (r_start->base > pcimem_end)) // Memory range requested is larger than available. return -1; return 0; @@ -595,11 +602,11 @@ static void pci_bios_map_devices(struct pci_bus *busses) if (pci_bios_init_root_regions(busses)) panic("PCI: out of 32bit address space\n");
- r64_mem.base = BUILD_PCIMEM64_START; + r64_mem.base = pcimem64_start; u64 sum = pci_region_sum(&r64_mem); u64 align = pci_region_align(&r64_pref); r64_pref.base = ALIGN(r64_mem.base + sum, align); - if (r64_pref.base + pci_region_sum(&r64_pref) > BUILD_PCIMEM64_END) + if (r64_pref.base + pci_region_sum(&r64_pref) > pcimem64_end) panic("PCI: out of 64bit address space\n"); pci_region_map_entries(busses, &r64_mem); pci_region_map_entries(busses, &r64_pref); @@ -629,6 +636,18 @@ pci_setup(void)
dprintf(3, "pci setup\n");
+ qemu_cfg_get_pci_windows(pcimem); + if (pcimem[0] && pcimem[1]) { + pcimem_start = pcimem[0]; + pcimem_end = pcimem[1] + 1; + dprintf(1, "32bit pci window: %llx - %llx\n", pcimem_start, pcimem_end); + } + if (pcimem[2] && pcimem[3]) { + pcimem64_start = pcimem[2]; + pcimem64_end = pcimem[3] + 1; + dprintf(1, "64bit pci window: %llx - %llx\n", pcimem64_start, pcimem64_end); + } + dprintf(1, "=== PCI bus & bridge init ===\n"); if (pci_probe_host() != 0) { return;