提交 f5a5628c 编写于 作者: C Cornelia Huck 提交者: Michael S. Tsirkin

dataplane: allow virtio-1 devices

Handle endianness conversion for virtio-1 virtqueues correctly.

Note that dataplane now needs to be built per-target.
Signed-off-by: NCornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: NMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
Reviewed-by: NMichael S. Tsirkin <mst@redhat.com>
上级 ab223c95
...@@ -157,15 +157,18 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) ...@@ -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) struct vring_desc *desc)
{ {
unsigned *num; unsigned *num;
struct iovec *iov; struct iovec *iov;
hwaddr *addr; hwaddr *addr;
MemoryRegion *mr; 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; num = &elem->in_num;
iov = &elem->in_sg[*num]; iov = &elem->in_sg[*num];
addr = &elem->in_addr[*num]; addr = &elem->in_addr[*num];
...@@ -189,18 +192,17 @@ static int get_desc(Vring *vring, VirtQueueElement *elem, ...@@ -189,18 +192,17 @@ static int get_desc(Vring *vring, VirtQueueElement *elem,
} }
/* TODO handle non-contiguous memory across region boundaries */ /* TODO handle non-contiguous memory across region boundaries */
iov->iov_base = vring_map(&mr, desc->addr, desc->len, iov->iov_base = vring_map(&mr, desc_addr, len, is_write);
desc->flags & VRING_DESC_F_WRITE);
if (!iov->iov_base) { if (!iov->iov_base) {
error_report("Failed to map descriptor addr %#" PRIx64 " len %u", error_report("Failed to map descriptor addr %#" PRIx64 " len %u",
(uint64_t)desc->addr, desc->len); (uint64_t)desc_addr, len);
return -EFAULT; return -EFAULT;
} }
/* The MemoryRegion is looked up again and unref'ed later, leave the /* The MemoryRegion is looked up again and unref'ed later, leave the
* ref in place. */ * ref in place. */
iov->iov_len = desc->len; iov->iov_len = len;
*addr = desc->addr; *addr = desc_addr;
*num += 1; *num += 1;
return 0; return 0;
} }
...@@ -222,21 +224,23 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, ...@@ -222,21 +224,23 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring,
struct vring_desc desc; struct vring_desc desc;
unsigned int i = 0, count, found = 0; unsigned int i = 0, count, found = 0;
int ret; int ret;
uint32_t len = virtio_tswap32(vdev, indirect->len);
uint64_t addr = virtio_tswap64(vdev, indirect->addr);
/* Sanity check */ /* Sanity check */
if (unlikely(indirect->len % sizeof(desc))) { if (unlikely(len % sizeof(desc))) {
error_report("Invalid length in indirect descriptor: " error_report("Invalid length in indirect descriptor: "
"len %#x not multiple of %#zx", "len %#x not multiple of %#zx",
indirect->len, sizeof(desc)); len, sizeof(desc));
vring->broken = true; vring->broken = true;
return -EFAULT; return -EFAULT;
} }
count = indirect->len / sizeof(desc); count = len / sizeof(desc);
/* Buffers are chained via a 16 bit next field, so /* Buffers are chained via a 16 bit next field, so
* we can have at most 2^16 of these. */ * we can have at most 2^16 of these. */
if (unlikely(count > USHRT_MAX + 1)) { 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; vring->broken = true;
return -EFAULT; return -EFAULT;
} }
...@@ -247,12 +251,12 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, ...@@ -247,12 +251,12 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring,
/* Translate indirect descriptor */ /* Translate indirect descriptor */
desc_ptr = vring_map(&mr, desc_ptr = vring_map(&mr,
indirect->addr + found * sizeof(desc), addr + found * sizeof(desc),
sizeof(desc), false); sizeof(desc), false);
if (!desc_ptr) { if (!desc_ptr) {
error_report("Failed to map indirect descriptor " error_report("Failed to map indirect descriptor "
"addr %#" PRIx64 " len %zu", "addr %#" PRIx64 " len %zu",
(uint64_t)indirect->addr + found * sizeof(desc), (uint64_t)addr + found * sizeof(desc),
sizeof(desc)); sizeof(desc));
vring->broken = true; vring->broken = true;
return -EFAULT; return -EFAULT;
...@@ -270,19 +274,20 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, ...@@ -270,19 +274,20 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring,
return -EFAULT; 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"); error_report("Nested indirect descriptor");
vring->broken = true; vring->broken = true;
return -EFAULT; return -EFAULT;
} }
ret = get_desc(vring, elem, &desc); ret = get_desc(vdev, vring, elem, &desc);
if (ret < 0) { if (ret < 0) {
vring->broken |= (ret == -EFAULT); vring->broken |= (ret == -EFAULT);
return ret; return ret;
} }
i = desc.next; i = virtio_tswap16(vdev, desc.next);
} while (desc.flags & VRING_DESC_F_NEXT); } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT);
return 0; return 0;
} }
...@@ -383,7 +388,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, ...@@ -383,7 +388,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
/* Ensure descriptor is loaded before accessing fields */ /* Ensure descriptor is loaded before accessing fields */
barrier(); 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); ret = get_indirect(vdev, vring, elem, &desc);
if (ret < 0) { if (ret < 0) {
goto out; goto out;
...@@ -391,13 +396,13 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, ...@@ -391,13 +396,13 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
continue; continue;
} }
ret = get_desc(vring, elem, &desc); ret = get_desc(vdev, vring, elem, &desc);
if (ret < 0) { if (ret < 0) {
goto out; goto out;
} }
i = desc.next; i = virtio_tswap16(vdev, desc.next);
} while (desc.flags & VRING_DESC_F_NEXT); } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT);
/* On success, increment avail index. */ /* On success, increment avail index. */
vring->last_avail_idx++; vring->last_avail_idx++;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册