|
|
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 |
|