aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio/virtio.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-07-22 10:14:24 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-07-22 10:14:24 -0500
commit549c272b3c7c2aac69155be2e158c970828b2844 (patch)
tree18c407ca7c3c83b3e069987921d8b5e068f8742e /hw/virtio/virtio.c
parentc9fea5d701f8fd33f0843728ec264d95cee3ed37 (diff)
parentfd76663e3fe59dc7f7d5c439561b74f472727137 (diff)
Merge remote-tracking branch 'pmaydell/tags/pull-arm-devs-20130722' into staging
arm-devs queue # gpg: Signature made Mon 22 Jul 2013 06:38:52 AM CDT using RSA key ID 14360CDE # gpg: Can't check signature: public key not found # By Peter Maydell (8) and Soren Brinkmann (2) # Via Peter Maydell * pmaydell/tags/pull-arm-devs-20130722: hw/arm: Use 'load_ramdisk()' for loading ramdisks w/ U-Boot header hw/loader: Support ramdisk with u-boot header vexpress: Add virtio-mmio transports vexpress: Make VEDBoardInfo extend arm_boot_info arm/boot: Allow boards to modify the FDT blob virtio: Implement MMIO based virtio transport virtio: Support transports which can specify the vring alignment virtio: Add support for guest setting of queue size arm/boot: Use qemu_devtree_setprop_sized_cells() device_tree: Add qemu_devtree_setprop_sized_cells() utility functions Message-id: 1374493427-3254-1-git-send-email-peter.maydell@linaro.org Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/virtio/virtio.c')
-rw-r--r--hw/virtio/virtio.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 8176c147e1..09f62c6c70 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -19,8 +19,11 @@
#include "qemu/atomic.h"
#include "hw/virtio/virtio-bus.h"
-/* The alignment to use between consumer and producer parts of vring.
- * x86 pagesize again. */
+/*
+ * The alignment to use between consumer and producer parts of vring.
+ * x86 pagesize again. This is the default, used by transports like PCI
+ * which don't provide a means for the guest to tell the host the alignment.
+ */
#define VIRTIO_PCI_VRING_ALIGN 4096
typedef struct VRingDesc
@@ -54,6 +57,7 @@ typedef struct VRingUsed
typedef struct VRing
{
unsigned int num;
+ unsigned int align;
hwaddr desc;
hwaddr avail;
hwaddr used;
@@ -93,7 +97,7 @@ static void virtqueue_init(VirtQueue *vq)
vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
vq->vring.used = vring_align(vq->vring.avail +
offsetof(VRingAvail, ring[vq->vring.num]),
- VIRTIO_PCI_VRING_ALIGN);
+ vq->vring.align);
}
static inline uint64_t vring_desc_addr(hwaddr desc_pa, int i)
@@ -667,6 +671,14 @@ hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n)
return vdev->vq[n].pa;
}
+void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
+{
+ if (num <= VIRTQUEUE_MAX_SIZE) {
+ vdev->vq[n].vring.num = num;
+ virtqueue_init(&vdev->vq[n]);
+ }
+}
+
int virtio_queue_get_num(VirtIODevice *vdev, int n)
{
return vdev->vq[n].vring.num;
@@ -679,6 +691,21 @@ int virtio_queue_get_id(VirtQueue *vq)
return vq - &vdev->vq[0];
}
+void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
+{
+ BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+
+ /* Check that the transport told us it was going to do this
+ * (so a buggy transport will immediately assert rather than
+ * silently failing to migrate this state)
+ */
+ assert(k->has_variable_vring_alignment);
+
+ vdev->vq[n].vring.align = align;
+ virtqueue_init(&vdev->vq[n]);
+}
+
void virtio_queue_notify_vq(VirtQueue *vq)
{
if (vq->vring.desc) {
@@ -719,6 +746,7 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
abort();
vdev->vq[i].vring.num = queue_size;
+ vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
vdev->vq[i].handle_output = handle_output;
return &vdev->vq[i];
@@ -825,6 +853,9 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
break;
qemu_put_be32(f, vdev->vq[i].vring.num);
+ if (k->has_variable_vring_alignment) {
+ qemu_put_be32(f, vdev->vq[i].vring.align);
+ }
qemu_put_be64(f, vdev->vq[i].pa);
qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
if (k->save_queue) {
@@ -881,6 +912,9 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
for (i = 0; i < num; i++) {
vdev->vq[i].vring.num = qemu_get_be32(f);
+ if (k->has_variable_vring_alignment) {
+ vdev->vq[i].vring.align = qemu_get_be32(f);
+ }
vdev->vq[i].pa = qemu_get_be64(f);
qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
vdev->vq[i].signalled_used_valid = false;