Patchwork [RFC,v9,04/27] virtio-blk: Map vring

login
register
mail settings
Submitter Stefan Hajnoczi
Date July 18, 2012, 3:07 p.m.
Message ID <1342624074-24650-5-git-send-email-stefanha@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/171709/
State New
Headers show

Comments

Stefan Hajnoczi - July 18, 2012, 3:07 p.m.
Map the vring to host memory so it can be accessed without the overhead
of the QEMU memory functions.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
 hw/virtio-blk.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

Patch

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index f6043bc..4c790a3 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -14,6 +14,7 @@ 
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
 #include <libaio.h>
+#include <linux/virtio_ring.h>
 #include "qemu-common.h"
 #include "qemu-thread.h"
 #include "qemu-error.h"
@@ -43,6 +44,8 @@  typedef struct VirtIOBlock
     bool data_plane_started;
     QemuThread data_plane_thread;
 
+    struct vring vring;
+
     int epoll_fd;                   /* epoll(2) file descriptor */
     io_context_t io_ctx;            /* Linux AIO context */
     EventNotifier io_notifier;      /* Linux AIO eventfd */
@@ -55,6 +58,43 @@  static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
     return (VirtIOBlock *)vdev;
 }
 
+/* Map the guest's vring to host memory
+ *
+ * This is not allowed but we know the ring won't move.
+ */
+static void map_vring(struct vring *vring, VirtIODevice *vdev, int n)
+{
+    target_phys_addr_t physaddr, len;
+
+    vring->num = virtio_queue_get_num(vdev, n);
+
+    physaddr = virtio_queue_get_desc_addr(vdev, n);
+    len = virtio_queue_get_desc_size(vdev, n);
+    vring->desc = cpu_physical_memory_map(physaddr, &len, 0);
+
+    physaddr = virtio_queue_get_avail_addr(vdev, n);
+    len = virtio_queue_get_avail_size(vdev, n);
+    vring->avail = cpu_physical_memory_map(physaddr, &len, 0);
+
+    physaddr = virtio_queue_get_used_addr(vdev, n);
+    len = virtio_queue_get_used_size(vdev, n);
+    vring->used = cpu_physical_memory_map(physaddr, &len, 0);
+
+    if (!vring->desc || !vring->avail || !vring->used) {
+        fprintf(stderr, "virtio-blk failed to map vring\n");
+        exit(1);
+    }
+
+    fprintf(stderr, "virtio-blk vring physical=%#lx desc=%p avail=%p used=%p\n",
+            virtio_queue_get_ring_addr(vdev, n),
+            vring->desc, vring->avail, vring->used);
+}
+
+static void unmap_vring(struct vring *vring, VirtIODevice *vdev, int n)
+{
+    cpu_physical_memory_unmap(vring->desc, virtio_queue_get_ring_size(vdev, n), 0, 0);
+}
+
 static void handle_io(void)
 {
     fprintf(stderr, "io completion happened\n");
@@ -109,6 +149,8 @@  static void add_event_handler(int epoll_fd, EventHandler *event_handler)
 
 static void data_plane_start(VirtIOBlock *s)
 {
+    map_vring(&s->vring, &s->vdev, 0);
+
     /* Create epoll file descriptor */
     s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
     if (s->epoll_fd < 0) {
@@ -157,6 +199,8 @@  static void data_plane_stop(VirtIOBlock *s)
     s->vdev.binding->set_host_notifier(s->vdev.binding_opaque, 0, false);
 
     close(s->epoll_fd);
+
+    unmap_vring(&s->vring, &s->vdev, 0);
 }
 
 static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t val)