diff mbox

[3/3] qemu-kvm: pci-assign: Consolidate and fix slow mmio region mappings

Message ID 478c7a8e59ac5b5e4fd598e9fb874a4e4b03525c.1303553132.git.jan.kiszka@web.de (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kiszka April 23, 2011, 10:05 a.m. UTC
From: Jan Kiszka <jan.kiszka@siemens.com>

By registering the io-memory for slow regions already in
assigned_dev_register_regions we can achieve several cleanups and fixes:
 - use assigned_dev_iomem_map for both normal and slow mappings
 - release slow io-region on clean up
 - avoid unregistering zero-size regions (i.e. yet unmapped ones) which
   causes abort() these days

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/device-assignment.c |   65 ++++++++++++++---------------------------------
 1 files changed, 20 insertions(+), 45 deletions(-)
diff mbox

Patch

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 8a7cfcf..606d725 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -242,31 +242,6 @@  static CPUReadMemoryFunc * const slow_bar_read[] = {
     &slow_bar_readl
 };
 
-static void assigned_dev_iomem_map_slow(PCIDevice *pci_dev, int region_num,
-                                        pcibus_t e_phys, pcibus_t e_size,
-                                        int type)
-{
-    AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
-    AssignedDevRegion *region = &r_dev->v_addrs[region_num];
-    PCIRegion *real_region = &r_dev->real_device.regions[region_num];
-    int m;
-
-    DEBUG("%s", "slow map\n");
-    m = cpu_register_io_memory(slow_bar_read, slow_bar_write, region,
-                               DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(e_phys, e_size, m);
-
-    /* MSI-X MMIO page */
-    if ((e_size > 0) &&
-        real_region->base_addr <= r_dev->msix_table_addr &&
-        real_region->base_addr + real_region->size >= r_dev->msix_table_addr) {
-        int offset = r_dev->msix_table_addr - real_region->base_addr;
-
-        cpu_register_physical_memory(e_phys + offset,
-                TARGET_PAGE_SIZE, r_dev->mmio_index);
-    }
-}
-
 static void assigned_dev_iomem_map(PCIDevice *pci_dev, int region_num,
                                    pcibus_t e_phys, pcibus_t e_size, int type)
 {
@@ -531,21 +506,10 @@  static int assigned_dev_register_regions(PCIRegion *io_regions,
 
         /* handle memory io regions */
         if (cur_region->type & IORESOURCE_MEM) {
-            int slow_map = 0;
             int t = cur_region->type & IORESOURCE_PREFETCH
                 ? PCI_BASE_ADDRESS_MEM_PREFETCH
                 : PCI_BASE_ADDRESS_SPACE_MEMORY;
 
-            if (cur_region->size & 0xFFF) {
-                fprintf(stderr, "PCI region %d at address 0x%llx "
-                        "has size 0x%x, which is not a multiple of 4K. "
-                        "You might experience some performance hit "
-                        "due to that.\n",
-                        i, (unsigned long long)cur_region->base_addr,
-                        cur_region->size);
-                slow_map = 1;
-            }
-
             /* map physical memory */
             pci_dev->v_addrs[i].e_physbase = cur_region->base_addr;
             pci_dev->v_addrs[i].u.r_virtbase = mmap(NULL, cur_region->size,
@@ -569,8 +533,18 @@  static int assigned_dev_register_regions(PCIRegion *io_regions,
             pci_dev->v_addrs[i].u.r_virtbase +=
                 (cur_region->base_addr & 0xFFF);
 
-
-            if (!slow_map) {
+            if (cur_region->size & 0xFFF) {
+                fprintf(stderr, "PCI region %d at address 0x%llx "
+                        "has size 0x%x, which is not a multiple of 4K. "
+                        "You might experience some performance hit "
+                        "due to that.\n",
+                        i, (unsigned long long)cur_region->base_addr,
+                        cur_region->size);
+                pci_dev->v_addrs[i].memory_index =
+                    cpu_register_io_memory(slow_bar_read, slow_bar_write,
+                                           &pci_dev->v_addrs[i],
+                                           DEVICE_NATIVE_ENDIAN);
+            } else {
                 void *virtbase = pci_dev->v_addrs[i].u.r_virtbase;
                 char name[32];
                 snprintf(name, sizeof(name), "%s.bar%d",
@@ -580,13 +554,10 @@  static int assigned_dev_register_regions(PCIRegion *io_regions,
                                                          &pci_dev->dev.qdev,
                                                          name, cur_region->size,
                                                          virtbase);
-            } else
-                pci_dev->v_addrs[i].memory_index = 0;
+            }
 
-            pci_register_bar((PCIDevice *) pci_dev, i,
-                             cur_region->size, t,
-                             slow_map ? assigned_dev_iomem_map_slow
-                                      : assigned_dev_iomem_map);
+            pci_register_bar((PCIDevice *) pci_dev, i, cur_region->size, t,
+                             assigned_dev_iomem_map);
             continue;
         } else {
             /* handle port io regions */
@@ -810,10 +781,14 @@  static void free_assigned_device(AssignedDevice *dev)
             }
         } else if (pci_region->type & IORESOURCE_MEM) {
             if (region->u.r_virtbase) {
-                if (region->memory_index) {
+                if (region->e_size > 0) {
                     cpu_register_physical_memory(region->e_physbase,
                                                  region->e_size,
                                                  IO_MEM_UNASSIGNED);
+                }
+                if (region->r_size & 0xFFF) {
+                    cpu_unregister_io_memory(region->memory_index);
+                } else {
                     qemu_ram_unmap(region->memory_index);
                 }
                 if (munmap(region->u.r_virtbase,