When the guest and the host have a different endian order, the data being accessed in the vring queues needs to be byteswapped if we run in legacy mode.
This patch adds a flag to inform the vhost kernel backend about the endianness to use. This patch is based on previous work by Cédric Le Goater. Cc: Cédric Le Goater <c...@fr.ibm.com> Signed-off-by: Greg Kurz <gk...@linux.vnet.ibm.com> --- hw/virtio/vhost.c | 10 +++++++++- include/hw/virtio/vhost.h | 1 + linux-headers/linux/vhost.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 5a12861..bd442f1 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -539,7 +539,13 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, .log_guest_addr = vq->used_phys, .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0, }; - int r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ADDR, &addr); + int r; + + if (vq->legacy_big_endian) { + addr.flags |= (1 << VHOST_VRING_F_LEGACY_BIG_ENDIAN); + } + + r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ADDR, &addr); if (r < 0) { return -errno; } @@ -707,6 +713,8 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, goto fail_alloc_ring; } + vq->legacy_big_endian = virtio_is_big_endian(vdev); + r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); if (r < 0) { r = -errno; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index d5593d1..991fa20 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -20,6 +20,7 @@ struct vhost_virtqueue { unsigned long long ring_phys; unsigned ring_size; EventNotifier masked_notifier; + bool legacy_big_endian; /* Only used with legacy virtio devices */ }; typedef unsigned long vhost_log_chunk_t; diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h index c656f61..ffbb8ee 100644 --- a/linux-headers/linux/vhost.h +++ b/linux-headers/linux/vhost.h @@ -34,6 +34,8 @@ struct vhost_vring_addr { /* Flag values: */ /* Whether log address is valid. If set enables logging. */ #define VHOST_VRING_F_LOG 0 + /* Whether we have a big-endian legacy virtio device. */ +#define VHOST_VRING_F_LEGACY_BIG_ENDIAN 1 /* Start of array of descriptors (virtually contiguous) */ __u64 desc_user_addr;