Blame 0100-libvhost-user-Fix-some-memtable-remap-cases.patch

1d442b
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1d442b
Date: Mon, 27 Jan 2020 19:02:09 +0000
1d442b
Subject: [PATCH] libvhost-user: Fix some memtable remap cases
1d442b
1d442b
If a new setmemtable command comes in once the vhost threads are
1d442b
running, it will remap the guests address space and the threads
1d442b
will now be looking in the wrong place.
1d442b
1d442b
Fortunately we're running this command under lock, so we can
1d442b
update the queue mappings so that threads will look in the new-right
1d442b
place.
1d442b
1d442b
Note: This doesn't fix things that the threads might be doing
1d442b
without a lock (e.g. a readv/writev!)  That's for another time.
1d442b
1d442b
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442b
(cherry picked from commit 49e9ec749d4db62ae51f76354143cee183912a1d)
1d442b
---
1d442b
 contrib/libvhost-user/libvhost-user.c | 33 ++++++++++++++++++++-------
1d442b
 contrib/libvhost-user/libvhost-user.h |  3 +++
1d442b
 2 files changed, 28 insertions(+), 8 deletions(-)
1d442b
1d442b
diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c
1d442b
index 63e41062a4..b89bf18501 100644
1d442b
--- a/contrib/libvhost-user/libvhost-user.c
1d442b
+++ b/contrib/libvhost-user/libvhost-user.c
1d442b
@@ -564,6 +564,21 @@ vu_reset_device_exec(VuDev *dev, VhostUserMsg *vmsg)
1d442b
     return false;
1d442b
 }
1d442b
 
1d442b
+static bool
1d442b
+map_ring(VuDev *dev, VuVirtq *vq)
1d442b
+{
1d442b
+    vq->vring.desc = qva_to_va(dev, vq->vra.desc_user_addr);
1d442b
+    vq->vring.used = qva_to_va(dev, vq->vra.used_user_addr);
1d442b
+    vq->vring.avail = qva_to_va(dev, vq->vra.avail_user_addr);
1d442b
+
1d442b
+    DPRINT("Setting virtq addresses:\n");
1d442b
+    DPRINT("    vring_desc  at %p\n", vq->vring.desc);
1d442b
+    DPRINT("    vring_used  at %p\n", vq->vring.used);
1d442b
+    DPRINT("    vring_avail at %p\n", vq->vring.avail);
1d442b
+
1d442b
+    return !(vq->vring.desc && vq->vring.used && vq->vring.avail);
1d442b
+}
1d442b
+
1d442b
 static bool
1d442b
 vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg)
1d442b
 {
1d442b
@@ -767,6 +782,14 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg)
1d442b
         close(vmsg->fds[i]);
1d442b
     }
1d442b
 
1d442b
+    for (i = 0; i < dev->max_queues; i++) {
1d442b
+        if (dev->vq[i].vring.desc) {
1d442b
+            if (map_ring(dev, &dev->vq[i])) {
1d442b
+                vu_panic(dev, "remaping queue %d during setmemtable", i);
1d442b
+            }
1d442b
+        }
1d442b
+    }
1d442b
+
1d442b
     return false;
1d442b
 }
1d442b
 
1d442b
@@ -853,18 +876,12 @@ vu_set_vring_addr_exec(VuDev *dev, VhostUserMsg *vmsg)
1d442b
     DPRINT("    avail_user_addr:  0x%016" PRIx64 "\n", vra->avail_user_addr);
1d442b
     DPRINT("    log_guest_addr:   0x%016" PRIx64 "\n", vra->log_guest_addr);
1d442b
 
1d442b
+    vq->vra = *vra;
1d442b
     vq->vring.flags = vra->flags;
1d442b
-    vq->vring.desc = qva_to_va(dev, vra->desc_user_addr);
1d442b
-    vq->vring.used = qva_to_va(dev, vra->used_user_addr);
1d442b
-    vq->vring.avail = qva_to_va(dev, vra->avail_user_addr);
1d442b
     vq->vring.log_guest_addr = vra->log_guest_addr;
1d442b
 
1d442b
-    DPRINT("Setting virtq addresses:\n");
1d442b
-    DPRINT("    vring_desc  at %p\n", vq->vring.desc);
1d442b
-    DPRINT("    vring_used  at %p\n", vq->vring.used);
1d442b
-    DPRINT("    vring_avail at %p\n", vq->vring.avail);
1d442b
 
1d442b
-    if (!(vq->vring.desc && vq->vring.used && vq->vring.avail)) {
1d442b
+    if (map_ring(dev, vq)) {
1d442b
         vu_panic(dev, "Invalid vring_addr message");
1d442b
         return false;
1d442b
     }
1d442b
diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h
1d442b
index 1844b6f8d4..5cb7708559 100644
1d442b
--- a/contrib/libvhost-user/libvhost-user.h
1d442b
+++ b/contrib/libvhost-user/libvhost-user.h
1d442b
@@ -327,6 +327,9 @@ typedef struct VuVirtq {
1d442b
     int err_fd;
1d442b
     unsigned int enable;
1d442b
     bool started;
1d442b
+
1d442b
+    /* Guest addresses of our ring */
1d442b
+    struct vhost_vring_addr vra;
1d442b
 } VuVirtq;
1d442b
 
1d442b
 enum VuWatchCondtion {