diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-06-11 15:33:38 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-06-11 15:33:38 +0100 |
commit | d8e3b729cf452d2689c8669f1ec18158db29fd5a (patch) | |
tree | accc62ac8989a64ef70291ad1d1ca09f374d71a6 /hw/virtio/dataplane/vring.c | |
parent | afa25c4bb5bd0732dca4aa0691fd4682d242925f (diff) | |
parent | 4ebc736e9938a7e88ecc785734b17145bf802a56 (diff) |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc, acpi, virtio
Most notably this includes virtio 1 patches
Still not all devices converted, and not fully spec compliant,
so disabled by default.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Thu Jun 11 12:53:08 2015 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream: (42 commits)
i386/acpi-build: fix PXB workarounds for unsupported BIOSes
i386/acpi-build: more traditional _UID and _HID for PXB root buses
vhost-scsi: move qdev properties into vhost-scsi.c
virtio-9p-device: move qdev properties into virtio-9p-device.c
virtio-serial-bus: move qdev properties into virtio-serial-bus.c
virtio-rng: move qdev properties into virtio-rng.c
virtio-scsi: move qdev properties into virtio-scsi.c
virtio-net.h: Remove unsed DEFINE_VIRTIO_NET_PROPERTIES
virtio-net: move qdev properties into virtio-net.c
virtio-input: emulated devices [pci]
virtio-input: core code & base class [pci]
pci: add PCI_CLASS_INPUT_*
virtio-pci: fill VirtIOPCIRegions early.
virtio-pci: drop identical virtio_pci_cap
virtio-pci: move cap type to VirtIOPCIRegion
virtio-pci: move virtio_pci_add_mem_cap call to virtio_pci_modern_region_map
virtio-pci: add virtio_pci_modern_region_map()
virtio-pci: add virtio_pci_modern_regions_init()
virtio-pci: add struct VirtIOPCIRegion for virtio-1 regions
virtio-balloon: switch to virtio_add_feature
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/virtio/dataplane/vring.c')
-rw-r--r-- | hw/virtio/dataplane/vring.c | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index e37873384f..35891856ee 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++; |