Blame SOURCES/seabios-pci-improve-io-address-space-allocation.patch

6a2d3c
From b2d132c9e3a65858fb745bdeafd1700a58db9bdc Mon Sep 17 00:00:00 2001
6a2d3c
From: Gerd Hoffmann <kraxel@redhat.com>
6a2d3c
Date: Mon, 27 Jan 2014 15:31:28 -0500
6a2d3c
Subject: [PATCH 6/6] pci: improve io address space allocation
6a2d3c
6a2d3c
Message-id: <1390836688-16749-4-git-send-email-kraxel@redhat.com>
6a2d3c
Patchwork-id: 56958
6a2d3c
O-Subject: [RHEL-7 seabios PATCH 3/3] pci: improve io address space allocation
6a2d3c
Bugzilla: 1055832
6a2d3c
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
6a2d3c
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
6a2d3c
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
6a2d3c
6a2d3c
This patch improves the io address space allocation.  It adds a check
6a2d3c
that the region above 0xc000 which is traditionally used for pci io
6a2d3c
is actually big enougth.  If it isn't it tries the larger window at
6a2d3c
0x1000.  If that is to small too it errors out.
6a2d3c
6a2d3c
When creating guests with multiple pci-pci bridges (and devices with
6a2d3c
io regions behind them) the 0xc000 -> 0xffff region quickly becomes
6a2d3c
too small.
6a2d3c
6a2d3c
While being at it document the io address space layout used by
6a2d3c
qemu/seabios.
6a2d3c
6a2d3c
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
6a2d3c
(cherry picked from commit fc3cd00045cbe96ca1e6b6601d26901f040bfcdb)
6a2d3c
---
6a2d3c
 src/pciinit.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
6a2d3c
 1 file changed, 40 insertions(+), 5 deletions(-)
6a2d3c
6a2d3c
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
6a2d3c
---
6a2d3c
 src/pciinit.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
6a2d3c
 1 file changed, 40 insertions(+), 5 deletions(-)
6a2d3c
6a2d3c
diff --git a/src/pciinit.c b/src/pciinit.c
6a2d3c
index 4e5d7d0..fe58f59 100644
6a2d3c
--- a/src/pciinit.c
6a2d3c
+++ b/src/pciinit.c
6a2d3c
@@ -663,10 +663,42 @@ static int pci_bios_check_devices(struct pci_bus *busses)
6a2d3c
  ****************************************************************/
6a2d3c
 
6a2d3c
 // Setup region bases (given the regions' size and alignment)
6a2d3c
-static int pci_bios_init_root_regions(struct pci_bus *bus)
6a2d3c
-{
6a2d3c
-    bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
6a2d3c
+static int pci_bios_init_root_regions_io(struct pci_bus *bus)
6a2d3c
+{
6a2d3c
+    /*
6a2d3c
+     * QEMU I/O address space usage:
6a2d3c
+     *   0000 - 0fff    legacy isa, pci config, pci root bus, ...
6a2d3c
+     *   1000 - 9fff    free
6a2d3c
+     *   a000 - afff    hotplug (cpu, pci via acpi, i440fx/piix only)
6a2d3c
+     *   b000 - bfff    power management (PORT_ACPI_PM_BASE)
6a2d3c
+     *                  [ qemu 1.4+ implements pci config registers
6a2d3c
+     *                    properly so guests can place the registers
6a2d3c
+     *                    where they want, on older versions its fixed ]
6a2d3c
+     *   c000 - ffff    free, traditionally used for pci io
6a2d3c
+     */
6a2d3c
+    struct pci_region *r_io = &bus->r[PCI_REGION_TYPE_IO];
6a2d3c
+    u64 sum = pci_region_sum(r_io);
6a2d3c
+    if (sum < 0x4000) {
6a2d3c
+        /* traditional region is big enougth, use it */
6a2d3c
+        r_io->base = 0xc000;
6a2d3c
+    } else if (sum < 0x9000) {
6a2d3c
+        /* use the larger region at 0x1000 */
6a2d3c
+        r_io->base = 0x1000;
6a2d3c
+    } else {
6a2d3c
+        /*
6a2d3c
+         * Not enougth io address space -> error out.
6a2d3c
+         *
6a2d3c
+         * TODO: on q35 we can move PORT_ACPI_PM_BASE out of
6a2d3c
+         * the way, then use the whole 1000 -> ffff region.
6a2d3c
+         */
6a2d3c
+        return -1;
6a2d3c
+    }
6a2d3c
+    dprintf(1, "PCI: IO: %4llx - %4llx\n", r_io->base, r_io->base + sum - 1);
6a2d3c
+    return 0;
6a2d3c
+}
6a2d3c
 
6a2d3c
+static int pci_bios_init_root_regions_mem(struct pci_bus *bus)
6a2d3c
+{
6a2d3c
     struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM];
6a2d3c
     struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM];
6a2d3c
 
6a2d3c
@@ -744,8 +776,11 @@ static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
6a2d3c
 
6a2d3c
 static void pci_bios_map_devices(struct pci_bus *busses)
6a2d3c
 {
6a2d3c
+    if (pci_bios_init_root_regions_io(busses))
6a2d3c
+        panic("PCI: out of I/O address space\n");
6a2d3c
+
6a2d3c
     dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end);
6a2d3c
-    if (pci_bios_init_root_regions(busses)) {
6a2d3c
+    if (pci_bios_init_root_regions_mem(busses)) {
6a2d3c
         struct pci_region r64_mem, r64_pref;
6a2d3c
         r64_mem.list = NULL;
6a2d3c
         r64_pref.list = NULL;
6a2d3c
@@ -754,7 +789,7 @@ static void pci_bios_map_devices(struct pci_bus *busses)
6a2d3c
         pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
6a2d3c
                                          &r64_pref);
6a2d3c
 
6a2d3c
-        if (pci_bios_init_root_regions(busses))
6a2d3c
+        if (pci_bios_init_root_regions_mem(busses))
6a2d3c
             panic("PCI: out of 32bit address space\n");
6a2d3c
 
6a2d3c
         u64 sum_mem = pci_region_sum(&r64_mem);
6a2d3c
-- 
6a2d3c
1.8.3.1
6a2d3c