Blame SOURCES/kvm-virtio-pci-Replace-modern_as-with-direct-access-to-m.patch

9bac43
From ff5e61b600d9a130faad32ceda3cd212dcb387d4 Mon Sep 17 00:00:00 2001
9bac43
From: David Gibson <dgibson@redhat.com>
9bac43
Date: Thu, 16 Nov 2017 03:07:11 +0100
9bac43
Subject: [PATCH 07/30] virtio-pci: Replace modern_as with direct access to
9bac43
 modern_bar
9bac43
9bac43
RH-Author: David Gibson <dgibson@redhat.com>
9bac43
Message-id: <20171116030732.8560-2-dgibson@redhat.com>
9bac43
Patchwork-id: 77689
9bac43
O-Subject: [PATCH 01/22] virtio-pci: Replace modern_as with direct access to modern_bar
9bac43
Bugzilla: 1481593
9bac43
RH-Acked-by: Thomas Huth <thuth@redhat.com>
9bac43
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9bac43
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
9bac43
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
9bac43
9bac43
From: Alexey Kardashevskiy <aik@ozlabs.ru>
9bac43
9bac43
The modern bar is accessed now via yet another address space created just
9bac43
for that purpose and it does not really need FlatView and dispatch tree
9bac43
as it has a single memory region so it is just a waste of memory. Things
9bac43
get even worse when there are dozens or hundreds of virtio-pci devices -
9bac43
since these address spaces are global, changing any of them triggers
9bac43
rebuilding all address spaces.
9bac43
9bac43
This replaces indirect accesses to the modern BAR with a simple lookup
9bac43
and direct calls to memory_region_dispatch_read/write.
9bac43
9bac43
This is expected to save lots of memory at boot time after applying:
9bac43
[Qemu-devel] [PULL 00/32] Misc changes for 2017-09-22
9bac43
9bac43
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
9bac43
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9bac43
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
9bac43
(cherry picked from commit a93c8d828af186d9a6a1c915a1be8ba22fb89849)
9bac43
9bac43
Signed-off-by: David Gibson <dgibson@redhat.com>
9bac43
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9bac43
---
9bac43
 hw/virtio/virtio-pci.c | 75 +++++++++++++++++++++++++++++---------------------
9bac43
 hw/virtio/virtio-pci.h | 17 +++++++-----
9bac43
 2 files changed, 54 insertions(+), 38 deletions(-)
9bac43
9bac43
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
9bac43
index 6e497c8..4b041bb 100644
9bac43
--- a/hw/virtio/virtio-pci.c
9bac43
+++ b/hw/virtio/virtio-pci.c
9bac43
@@ -545,6 +545,24 @@ static const MemoryRegionOps virtio_pci_config_ops = {
9bac43
     .endianness = DEVICE_LITTLE_ENDIAN,
9bac43
 };
9bac43
 
9bac43
+static MemoryRegion *virtio_address_space_lookup(VirtIOPCIProxy *proxy,
9bac43
+                                                 hwaddr *off, int len)
9bac43
+{
9bac43
+    int i;
9bac43
+    VirtIOPCIRegion *reg;
9bac43
+
9bac43
+    for (i = 0; i < ARRAY_SIZE(proxy->regs); ++i) {
9bac43
+        reg = &proxy->regs[i];
9bac43
+        if (*off >= reg->offset &&
9bac43
+            *off + len <= reg->offset + reg->size) {
9bac43
+            *off -= reg->offset;
9bac43
+            return &reg->mr;
9bac43
+        }
9bac43
+    }
9bac43
+
9bac43
+    return NULL;
9bac43
+}
9bac43
+
9bac43
 /* Below are generic functions to do memcpy from/to an address space,
9bac43
  * without byteswaps, with input validation.
9bac43
  *
9bac43
@@ -558,63 +576,72 @@ static const MemoryRegionOps virtio_pci_config_ops = {
9bac43
  * Note: host pointer must be aligned.
9bac43
  */
9bac43
 static
9bac43
-void virtio_address_space_write(AddressSpace *as, hwaddr addr,
9bac43
+void virtio_address_space_write(VirtIOPCIProxy *proxy, hwaddr addr,
9bac43
                                 const uint8_t *buf, int len)
9bac43
 {
9bac43
-    uint32_t val;
9bac43
+    uint64_t val;
9bac43
+    MemoryRegion *mr;
9bac43
 
9bac43
     /* address_space_* APIs assume an aligned address.
9bac43
      * As address is under guest control, handle illegal values.
9bac43
      */
9bac43
     addr &= ~(len - 1);
9bac43
 
9bac43
+    mr = virtio_address_space_lookup(proxy, &addr, len);
9bac43
+    if (!mr) {
9bac43
+        return;
9bac43
+    }
9bac43
+
9bac43
     /* Make sure caller aligned buf properly */
9bac43
     assert(!(((uintptr_t)buf) & (len - 1)));
9bac43
 
9bac43
     switch (len) {
9bac43
     case 1:
9bac43
         val = pci_get_byte(buf);
9bac43
-        address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
9bac43
         break;
9bac43
     case 2:
9bac43
-        val = pci_get_word(buf);
9bac43
-        address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
9bac43
+        val = cpu_to_le16(pci_get_word(buf));
9bac43
         break;
9bac43
     case 4:
9bac43
-        val = pci_get_long(buf);
9bac43
-        address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
9bac43
+        val = cpu_to_le32(pci_get_long(buf));
9bac43
         break;
9bac43
     default:
9bac43
         /* As length is under guest control, handle illegal values. */
9bac43
-        break;
9bac43
+        return;
9bac43
     }
9bac43
+    memory_region_dispatch_write(mr, addr, val, len, MEMTXATTRS_UNSPECIFIED);
9bac43
 }
9bac43
 
9bac43
 static void
9bac43
-virtio_address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
9bac43
+virtio_address_space_read(VirtIOPCIProxy *proxy, hwaddr addr,
9bac43
+                          uint8_t *buf, int len)
9bac43
 {
9bac43
-    uint32_t val;
9bac43
+    uint64_t val;
9bac43
+    MemoryRegion *mr;
9bac43
 
9bac43
     /* address_space_* APIs assume an aligned address.
9bac43
      * As address is under guest control, handle illegal values.
9bac43
      */
9bac43
     addr &= ~(len - 1);
9bac43
 
9bac43
+    mr = virtio_address_space_lookup(proxy, &addr, len);
9bac43
+    if (!mr) {
9bac43
+        return;
9bac43
+    }
9bac43
+
9bac43
     /* Make sure caller aligned buf properly */
9bac43
     assert(!(((uintptr_t)buf) & (len - 1)));
9bac43
 
9bac43
+    memory_region_dispatch_read(mr, addr, &val, len, MEMTXATTRS_UNSPECIFIED);
9bac43
     switch (len) {
9bac43
     case 1:
9bac43
-        val = address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
9bac43
         pci_set_byte(buf, val);
9bac43
         break;
9bac43
     case 2:
9bac43
-        val = address_space_lduw_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
9bac43
-        pci_set_word(buf, val);
9bac43
+        pci_set_word(buf, le16_to_cpu(val));
9bac43
         break;
9bac43
     case 4:
9bac43
-        val = address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
9bac43
-        pci_set_long(buf, val);
9bac43
+        pci_set_long(buf, le32_to_cpu(val));
9bac43
         break;
9bac43
     default:
9bac43
         /* As length is under guest control, handle illegal values. */
9bac43
@@ -650,8 +677,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
9bac43
 
9bac43
         if (len == 1 || len == 2 || len == 4) {
9bac43
             assert(len <= sizeof cfg->pci_cfg_data);
9bac43
-            virtio_address_space_write(&proxy->modern_as, off,
9bac43
-                                       cfg->pci_cfg_data, len);
9bac43
+            virtio_address_space_write(proxy, off, cfg->pci_cfg_data, len);
9bac43
         }
9bac43
     }
9bac43
 }
9bac43
@@ -675,8 +701,7 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev,
9bac43
 
9bac43
         if (len == 1 || len == 2 || len == 4) {
9bac43
             assert(len <= sizeof cfg->pci_cfg_data);
9bac43
-            virtio_address_space_read(&proxy->modern_as, off,
9bac43
-                                      cfg->pci_cfg_data, len);
9bac43
+            virtio_address_space_read(proxy, off, cfg->pci_cfg_data, len);
9bac43
         }
9bac43
     }
9bac43
 
9bac43
@@ -1783,15 +1808,6 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
9bac43
                        /* PCI BAR regions must be powers of 2 */
9bac43
                        pow2ceil(proxy->notify.offset + proxy->notify.size));
9bac43
 
9bac43
-    memory_region_init_alias(&proxy->modern_cfg,
9bac43
-                             OBJECT(proxy),
9bac43
-                             "virtio-pci-cfg",
9bac43
-                             &proxy->modern_bar,
9bac43
-                             0,
9bac43
-                             memory_region_size(&proxy->modern_bar));
9bac43
-
9bac43
-    address_space_init(&proxy->modern_as, &proxy->modern_cfg, "virtio-pci-cfg-as");
9bac43
-
9bac43
     if (proxy->disable_legacy == ON_OFF_AUTO_AUTO) {
9bac43
         proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
9bac43
     }
9bac43
@@ -1860,10 +1876,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
9bac43
 
9bac43
 static void virtio_pci_exit(PCIDevice *pci_dev)
9bac43
 {
9bac43
-    VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
9bac43
-
9bac43
     msix_uninit_exclusive_bar(pci_dev);
9bac43
-    address_space_destroy(&proxy->modern_as);
9bac43
 }
9bac43
 
9bac43
 static void virtio_pci_reset(DeviceState *qdev)
9bac43
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
9bac43
index 69f5959..12d3a90 100644
9bac43
--- a/hw/virtio/virtio-pci.h
9bac43
+++ b/hw/virtio/virtio-pci.h
9bac43
@@ -155,15 +155,18 @@ typedef struct VirtIOPCIQueue {
9bac43
 struct VirtIOPCIProxy {
9bac43
     PCIDevice pci_dev;
9bac43
     MemoryRegion bar;
9bac43
-    VirtIOPCIRegion common;
9bac43
-    VirtIOPCIRegion isr;
9bac43
-    VirtIOPCIRegion device;
9bac43
-    VirtIOPCIRegion notify;
9bac43
-    VirtIOPCIRegion notify_pio;
9bac43
+    union {
9bac43
+        struct {
9bac43
+            VirtIOPCIRegion common;
9bac43
+            VirtIOPCIRegion isr;
9bac43
+            VirtIOPCIRegion device;
9bac43
+            VirtIOPCIRegion notify;
9bac43
+            VirtIOPCIRegion notify_pio;
9bac43
+        };
9bac43
+        VirtIOPCIRegion regs[5];
9bac43
+    };
9bac43
     MemoryRegion modern_bar;
9bac43
     MemoryRegion io_bar;
9bac43
-    MemoryRegion modern_cfg;
9bac43
-    AddressSpace modern_as;
9bac43
     uint32_t legacy_io_bar_idx;
9bac43
     uint32_t msix_bar_idx;
9bac43
     uint32_t modern_io_bar_idx;
9bac43
-- 
9bac43
1.8.3.1
9bac43