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@xxxxxxxxxxxxxxxxxx> --- hw/virtio-blk.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) 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) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html