From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50047) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z317n-0006lm-L3 for qemu-devel@nongnu.org; Thu, 11 Jun 2015 07:58:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z317m-0006P9-Ge for qemu-devel@nongnu.org; Thu, 11 Jun 2015 07:58:23 -0400 Date: Thu, 11 Jun 2015 13:58:16 +0200 From: "Michael S. Tsirkin" Message-ID: <1434023714-30366-5-git-send-email-mst@redhat.com> References: <1434023714-30366-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1434023714-30366-1-git-send-email-mst@redhat.com> Subject: [Qemu-devel] [PULL 04/42] dataplane: allow virtio-1 devices List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Cornelia Huck , Peter Maydell , qemu-block@nongnu.org, Stefan Hajnoczi From: Cornelia Huck Handle endianness conversion for virtio-1 virtqueues correctly. Note that dataplane now needs to be built per-target. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/dataplane/vring.c | 47 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 5c7b8c2..fabb810 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -157,15 +157,18 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) } -static int get_desc(Vring *vring, VirtQueueElement *elem, +static int get_desc(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, struct vring_desc *desc) { unsigned *num; struct iovec *iov; hwaddr *addr; MemoryRegion *mr; + int is_write = virtio_tswap16(vdev, desc->flags) & VRING_DESC_F_WRITE; + uint32_t len = virtio_tswap32(vdev, desc->len); + uint64_t desc_addr = virtio_tswap64(vdev, desc->addr); - if (desc->flags & VRING_DESC_F_WRITE) { + if (is_write) { num = &elem->in_num; iov = &elem->in_sg[*num]; addr = &elem->in_addr[*num]; @@ -189,18 +192,17 @@ static int get_desc(Vring *vring, VirtQueueElement *elem, } /* TODO handle non-contiguous memory across region boundaries */ - iov->iov_base = vring_map(&mr, desc->addr, desc->len, - desc->flags & VRING_DESC_F_WRITE); + iov->iov_base = vring_map(&mr, desc_addr, len, is_write); if (!iov->iov_base) { error_report("Failed to map descriptor addr %#" PRIx64 " len %u", - (uint64_t)desc->addr, desc->len); + (uint64_t)desc_addr, len); return -EFAULT; } /* The MemoryRegion is looked up again and unref'ed later, leave the * ref in place. */ - iov->iov_len = desc->len; - *addr = desc->addr; + iov->iov_len = len; + *addr = desc_addr; *num += 1; return 0; } @@ -222,21 +224,23 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, struct vring_desc desc; unsigned int i = 0, count, found = 0; int ret; + uint32_t len = virtio_tswap32(vdev, indirect->len); + uint64_t addr = virtio_tswap64(vdev, indirect->addr); /* Sanity check */ - if (unlikely(indirect->len % sizeof(desc))) { + if (unlikely(len % sizeof(desc))) { error_report("Invalid length in indirect descriptor: " "len %#x not multiple of %#zx", - indirect->len, sizeof(desc)); + len, sizeof(desc)); vring->broken = true; return -EFAULT; } - count = indirect->len / sizeof(desc); + count = len / sizeof(desc); /* Buffers are chained via a 16 bit next field, so * we can have at most 2^16 of these. */ if (unlikely(count > USHRT_MAX + 1)) { - error_report("Indirect buffer length too big: %d", indirect->len); + error_report("Indirect buffer length too big: %d", len); vring->broken = true; return -EFAULT; } @@ -247,12 +251,12 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, /* Translate indirect descriptor */ desc_ptr = vring_map(&mr, - indirect->addr + found * sizeof(desc), + addr + found * sizeof(desc), sizeof(desc), false); if (!desc_ptr) { error_report("Failed to map indirect descriptor " "addr %#" PRIx64 " len %zu", - (uint64_t)indirect->addr + found * sizeof(desc), + (uint64_t)addr + found * sizeof(desc), sizeof(desc)); vring->broken = true; return -EFAULT; @@ -270,19 +274,20 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, return -EFAULT; } - if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) { + if (unlikely(virtio_tswap16(vdev, desc.flags) + & VRING_DESC_F_INDIRECT)) { error_report("Nested indirect descriptor"); vring->broken = true; return -EFAULT; } - ret = get_desc(vring, elem, &desc); + ret = get_desc(vdev, vring, elem, &desc); if (ret < 0) { vring->broken |= (ret == -EFAULT); return ret; } - i = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); + i = virtio_tswap16(vdev, desc.next); + } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT); return 0; } @@ -383,7 +388,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* Ensure descriptor is loaded before accessing fields */ barrier(); - if (desc.flags & VRING_DESC_F_INDIRECT) { + if (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_INDIRECT) { ret = get_indirect(vdev, vring, elem, &desc); if (ret < 0) { goto out; @@ -391,13 +396,13 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, continue; } - ret = get_desc(vring, elem, &desc); + ret = get_desc(vdev, vring, elem, &desc); if (ret < 0) { goto out; } - i = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); + i = virtio_tswap16(vdev, desc.next); + } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT); /* On success, increment avail index. */ vring->last_avail_idx++; -- MST