ddf19c
From ee360b70f179cf540faebe7e55b34e323e2bb179 Mon Sep 17 00:00:00 2001
ddf19c
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
ddf19c
Date: Mon, 27 Jan 2020 19:02:09 +0100
ddf19c
Subject: [PATCH 098/116] libvhost-user: Fix some memtable remap cases
ddf19c
MIME-Version: 1.0
ddf19c
Content-Type: text/plain; charset=UTF-8
ddf19c
Content-Transfer-Encoding: 8bit
ddf19c
ddf19c
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
ddf19c
Message-id: <20200127190227.40942-95-dgilbert@redhat.com>
ddf19c
Patchwork-id: 93548
ddf19c
O-Subject: [RHEL-AV-8.2 qemu-kvm PATCH 094/112] libvhost-user: Fix some memtable remap cases
ddf19c
Bugzilla: 1694164
ddf19c
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
ddf19c
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
ddf19c
ddf19c
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
ddf19c
ddf19c
If a new setmemtable command comes in once the vhost threads are
ddf19c
running, it will remap the guests address space and the threads
ddf19c
will now be looking in the wrong place.
ddf19c
ddf19c
Fortunately we're running this command under lock, so we can
ddf19c
update the queue mappings so that threads will look in the new-right
ddf19c
place.
ddf19c
ddf19c
Note: This doesn't fix things that the threads might be doing
ddf19c
without a lock (e.g. a readv/writev!)  That's for another time.
ddf19c
ddf19c
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
ddf19c
(cherry picked from commit 49e9ec749d4db62ae51f76354143cee183912a1d)
ddf19c
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ddf19c
---
ddf19c
 contrib/libvhost-user/libvhost-user.c | 33 +++++++++++++++++++++++++--------
ddf19c
 contrib/libvhost-user/libvhost-user.h |  3 +++
ddf19c
 2 files changed, 28 insertions(+), 8 deletions(-)
ddf19c
ddf19c
diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c
ddf19c
index 63e4106..b89bf18 100644
ddf19c
--- a/contrib/libvhost-user/libvhost-user.c
ddf19c
+++ b/contrib/libvhost-user/libvhost-user.c
ddf19c
@@ -565,6 +565,21 @@ vu_reset_device_exec(VuDev *dev, VhostUserMsg *vmsg)
ddf19c
 }
ddf19c
 
ddf19c
 static bool
ddf19c
+map_ring(VuDev *dev, VuVirtq *vq)
ddf19c
+{
ddf19c
+    vq->vring.desc = qva_to_va(dev, vq->vra.desc_user_addr);
ddf19c
+    vq->vring.used = qva_to_va(dev, vq->vra.used_user_addr);
ddf19c
+    vq->vring.avail = qva_to_va(dev, vq->vra.avail_user_addr);
ddf19c
+
ddf19c
+    DPRINT("Setting virtq addresses:\n");
ddf19c
+    DPRINT("    vring_desc  at %p\n", vq->vring.desc);
ddf19c
+    DPRINT("    vring_used  at %p\n", vq->vring.used);
ddf19c
+    DPRINT("    vring_avail at %p\n", vq->vring.avail);
ddf19c
+
ddf19c
+    return !(vq->vring.desc && vq->vring.used && vq->vring.avail);
ddf19c
+}
ddf19c
+
ddf19c
+static bool
ddf19c
 vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
ddf19c
 {
ddf19c
     int i;
ddf19c
@@ -767,6 +782,14 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg)
ddf19c
         close(vmsg->fds[i]);
ddf19c
     }
ddf19c
 
ddf19c
+    for (i = 0; i < dev->max_queues; i++) {
ddf19c
+        if (dev->vq[i].vring.desc) {
ddf19c
+            if (map_ring(dev, &dev->vq[i])) {
ddf19c
+                vu_panic(dev, "remaping queue %d during setmemtable", i);
ddf19c
+            }
ddf19c
+        }
ddf19c
+    }
ddf19c
+
ddf19c
     return false;
ddf19c
 }
ddf19c
 
ddf19c
@@ -853,18 +876,12 @@ vu_set_vring_addr_exec(VuDev *dev, VhostUserMsg *vmsg)
ddf19c
     DPRINT("    avail_user_addr:  0x%016" PRIx64 "\n", vra->avail_user_addr);
ddf19c
     DPRINT("    log_guest_addr:   0x%016" PRIx64 "\n", vra->log_guest_addr);
ddf19c
 
ddf19c
+    vq->vra = *vra;
ddf19c
     vq->vring.flags = vra->flags;
ddf19c
-    vq->vring.desc = qva_to_va(dev, vra->desc_user_addr);
ddf19c
-    vq->vring.used = qva_to_va(dev, vra->used_user_addr);
ddf19c
-    vq->vring.avail = qva_to_va(dev, vra->avail_user_addr);
ddf19c
     vq->vring.log_guest_addr = vra->log_guest_addr;
ddf19c
 
ddf19c
-    DPRINT("Setting virtq addresses:\n");
ddf19c
-    DPRINT("    vring_desc  at %p\n", vq->vring.desc);
ddf19c
-    DPRINT("    vring_used  at %p\n", vq->vring.used);
ddf19c
-    DPRINT("    vring_avail at %p\n", vq->vring.avail);
ddf19c
 
ddf19c
-    if (!(vq->vring.desc && vq->vring.used && vq->vring.avail)) {
ddf19c
+    if (map_ring(dev, vq)) {
ddf19c
         vu_panic(dev, "Invalid vring_addr message");
ddf19c
         return false;
ddf19c
     }
ddf19c
diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h
ddf19c
index 1844b6f..5cb7708 100644
ddf19c
--- a/contrib/libvhost-user/libvhost-user.h
ddf19c
+++ b/contrib/libvhost-user/libvhost-user.h
ddf19c
@@ -327,6 +327,9 @@ typedef struct VuVirtq {
ddf19c
     int err_fd;
ddf19c
     unsigned int enable;
ddf19c
     bool started;
ddf19c
+
ddf19c
+    /* Guest addresses of our ring */
ddf19c
+    struct vhost_vring_addr vra;
ddf19c
 } VuVirtq;
ddf19c
 
ddf19c
 enum VuWatchCondtion {
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c