]> git.proxmox.com Git - qemu.git/blobdiff - hw/vhost.c
misc: move include files to include/qemu/
[qemu.git] / hw / vhost.c
index cd56e75d0a6be62b0553b5013265eb26927bc1b0..4e1cb474187f86987b54fd225309db813a482055 100644 (file)
@@ -8,13 +8,17 @@
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
  */
 
 #include <sys/ioctl.h>
 #include "vhost.h"
 #include "hw/hw.h"
-#include "range.h"
+#include "qemu/range.h"
 #include <linux/vhost.h>
+#include "exec/address-spaces.h"
 
 static void vhost_dev_sync_region(struct vhost_dev *dev,
                                   MemoryRegionSection *section,
@@ -27,11 +31,12 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
     vhost_log_chunk_t *to = dev->log + end / VHOST_LOG_CHUNK + 1;
     uint64_t addr = (start / VHOST_LOG_CHUNK) * VHOST_LOG_CHUNK;
 
-    assert(end / VHOST_LOG_CHUNK < dev->log_size);
-    assert(start / VHOST_LOG_CHUNK < dev->log_size);
     if (end < start) {
         return;
     }
+    assert(end / VHOST_LOG_CHUNK < dev->log_size);
+    assert(start / VHOST_LOG_CHUNK < dev->log_size);
+
     for (;from < to; ++from) {
         vhost_log_chunk_t log;
         int bit;
@@ -51,7 +56,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
             ram_addr_t ram_addr;
             bit -= 1;
             ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE;
-            memory_region_set_dirty(section->mr, ram_addr);
+            memory_region_set_dirty(section->mr, ram_addr, VHOST_LOG_PAGE);
             log &= ~(0x1ull << bit);
         }
         addr += VHOST_LOG_CHUNK;
@@ -60,8 +65,8 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
 
 static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
                                    MemoryRegionSection *section,
-                                   target_phys_addr_t start_addr,
-                                   target_phys_addr_t end_addr)
+                                   hwaddr start_addr,
+                                   hwaddr end_addr)
 {
     int i;
 
@@ -88,8 +93,8 @@ static void vhost_log_sync(MemoryListener *listener,
 {
     struct vhost_dev *dev = container_of(listener, struct vhost_dev,
                                          memory_listener);
-    target_phys_addr_t start_addr = section->offset_within_address_space;
-    target_phys_addr_t end_addr = start_addr + section->size;
+    hwaddr start_addr = section->offset_within_address_space;
+    hwaddr end_addr = start_addr + section->size;
 
     vhost_sync_dirty_bitmap(dev, section, start_addr, end_addr);
 }
@@ -273,8 +278,9 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
     r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
     assert(r >= 0);
     for (i = 0; i < dev->n_mem_sections; ++i) {
-        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i],
-                                0, (target_phys_addr_t)~0x0ull);
+        /* Sync only the range covered by the old log */
+        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i], 0,
+                                dev->log_size * VHOST_LOG_CHUNK - 1);
     }
     if (dev->log) {
         g_free(dev->log);
@@ -290,7 +296,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
     int i;
     for (i = 0; i < dev->nvqs; ++i) {
         struct vhost_virtqueue *vq = dev->vqs + i;
-        target_phys_addr_t l;
+        hwaddr l;
         void *p;
 
         if (!ranges_overlap(start_addr, size, vq->ring_phys, vq->ring_size)) {
@@ -356,7 +362,7 @@ static void vhost_set_memory(MemoryListener *listener,
 {
     struct vhost_dev *dev = container_of(listener, struct vhost_dev,
                                          memory_listener);
-    target_phys_addr_t start_addr = section->offset_within_address_space;
+    hwaddr start_addr = section->offset_within_address_space;
     ram_addr_t size = section->size;
     bool log_dirty = memory_region_is_logging(section->mr);
     int s = offsetof(struct vhost_memory, regions) +
@@ -365,10 +371,6 @@ static void vhost_set_memory(MemoryListener *listener,
     int r;
     void *ram;
 
-    if (!memory_region_is_ram(section->mr)) {
-        return;
-    }
-
     dev->mem = g_realloc(dev->mem, s);
 
     if (log_dirty) {
@@ -378,7 +380,7 @@ static void vhost_set_memory(MemoryListener *listener,
     assert(size);
 
     /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */
-    ram = memory_region_get_ram_ptr(section->mr);
+    ram = memory_region_get_ram_ptr(section->mr) + section->offset_within_region;
     if (add) {
         if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) {
             /* Region exists with same address. Nothing to do. */
@@ -430,12 +432,29 @@ static void vhost_set_memory(MemoryListener *listener,
     }
 }
 
+static bool vhost_section(MemoryRegionSection *section)
+{
+    return memory_region_is_ram(section->mr);
+}
+
+static void vhost_begin(MemoryListener *listener)
+{
+}
+
+static void vhost_commit(MemoryListener *listener)
+{
+}
+
 static void vhost_region_add(MemoryListener *listener,
                              MemoryRegionSection *section)
 {
     struct vhost_dev *dev = container_of(listener, struct vhost_dev,
                                          memory_listener);
 
+    if (!vhost_section(section)) {
+        return;
+    }
+
     ++dev->n_mem_sections;
     dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
                                 dev->n_mem_sections);
@@ -450,18 +469,27 @@ static void vhost_region_del(MemoryListener *listener,
                                          memory_listener);
     int i;
 
+    if (!vhost_section(section)) {
+        return;
+    }
+
     vhost_set_memory(listener, section, false);
     for (i = 0; i < dev->n_mem_sections; ++i) {
         if (dev->mem_sections[i].offset_within_address_space
             == section->offset_within_address_space) {
             --dev->n_mem_sections;
             memmove(&dev->mem_sections[i], &dev->mem_sections[i+1],
-                    dev->n_mem_sections - i);
+                    (dev->n_mem_sections - i) * sizeof(*dev->mem_sections));
             break;
         }
     }
 }
 
+static void vhost_region_nop(MemoryListener *listener,
+                             MemoryRegionSection *section)
+{
+}
+
 static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
                                     struct vhost_virtqueue *vq,
                                     unsigned idx, bool enable_log)
@@ -589,7 +617,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
                                 struct vhost_virtqueue *vq,
                                 unsigned idx)
 {
-    target_phys_addr_t s, l, a;
+    hwaddr s, l, a;
     int r;
     struct vhost_vring_file file = {
         .index = idx,
@@ -706,14 +734,27 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
                               0, virtio_queue_get_desc_size(vdev, idx));
 }
 
-int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
+static void vhost_eventfd_add(MemoryListener *listener,
+                              MemoryRegionSection *section,
+                              bool match_data, uint64_t data, EventNotifier *e)
+{
+}
+
+static void vhost_eventfd_del(MemoryListener *listener,
+                              MemoryRegionSection *section,
+                              bool match_data, uint64_t data, EventNotifier *e)
+{
+}
+
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath,
+                   bool force)
 {
     uint64_t features;
     int r;
     if (devfd >= 0) {
         hdev->control = devfd;
     } else {
-        hdev->control = open("/dev/vhost-net", O_RDWR);
+        hdev->control = open(devpath, O_RDWR);
         if (hdev->control < 0) {
             return -errno;
         }
@@ -730,13 +771,19 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
     hdev->features = features;
 
     hdev->memory_listener = (MemoryListener) {
+        .begin = vhost_begin,
+        .commit = vhost_commit,
         .region_add = vhost_region_add,
         .region_del = vhost_region_del,
+        .region_nop = vhost_region_nop,
         .log_start = vhost_log_start,
         .log_stop = vhost_log_stop,
         .log_sync = vhost_log_sync,
         .log_global_start = vhost_log_global_start,
         .log_global_stop = vhost_log_global_stop,
+        .eventfd_add = vhost_eventfd_add,
+        .eventfd_del = vhost_eventfd_del,
+        .priority = 10
     };
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
     hdev->n_mem_sections = 0;
@@ -745,7 +792,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
     hdev->log_size = 0;
     hdev->log_enabled = false;
     hdev->started = false;
-    memory_listener_register(&hdev->memory_listener);
+    memory_listener_register(&hdev->memory_listener, &address_space_memory);
     hdev->force = force;
     return 0;
 fail:
@@ -901,7 +948,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
     }
     for (i = 0; i < hdev->n_mem_sections; ++i) {
         vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i],
-                                0, (target_phys_addr_t)~0x0ull);
+                                0, (hwaddr)~0x0ull);
     }
     r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false);
     if (r < 0) {