vhost: support for cross endian
cover vhost: support for cross endian
This patchset allows vhost_net to be used with legacy virtio when guest and host have different endianness. It depends on the following kernel patchset:
https://lists.linuxfoundation.org/pipermail/virtualization/2015-February/029347.html
---
Cédric Le Goater (1):
vhost_net: re-enable when cross endian
Greg Kurz (1):
vhost: add VHOST_VRING_F_LEGACY_BIG_ENDIAN flag
hw/net/vhost_net.c | 19 ------------------- hw/virtio/vhost.c | 10 +++++++++- include/hw/virtio/vhost.h | 1 + linux-headers/linux/vhost.h | 2 ++ 4 files changed, 12 insertions(+), 20 deletions(-)
--
Greg
PATCH 1/2 vhost: add VHOST_VRING_F_LEGACY_BIG_ENDIAN flag
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.
--- hw/virtio/vhost.c | 10 +++++++++- include/hw/virtio/vhost.h | 1 + linux-headers/linux/vhost.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-)
hw/virtio/vhost.c +9 -1
@@ -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;
include/hw/virtio/vhost.h +1 -0
@@ -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 ;
linux-headers/linux/vhost.h +2 -0
@@ -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;
PATCH 2/2 vhost_net: re-enable when cross endian
In reply to Greg KurzFrom: Cédric Le Goater <[email protected]>
revert 371df9f5e0f1 "vhost-net: disable when cross-endian"
--- hw/net/vhost_net.c | 19 ------------------- 1 file changed, 19 deletions(-)
hw/net/vhost_net.c +0 -19
@@ -271,19 +271,6 @@ static void vhost_net_stop_one(struct vhost_net *net,vhost_dev_disable_notifiers (&net->dev, dev); } -static bool vhost_net_device_endian_ok (VirtIODevice *vdev) -{ -#ifdef TARGET_IS_BIENDIAN -#ifdef HOST_WORDS_BIGENDIAN -return virtio_is_big_endian (vdev); -#else -return !virtio_is_big_endian (vdev); -#endif -#else -return true; -#endif -} -int vhost_net_start (VirtIODevice *dev,NetClientState *ncs,int total_queues) {
@@ -292,12 +279,6 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (vbus);int r, e, i; -if (!vhost_net_device_endian_ok (dev)) { -error_report ("vhost-net does not support cross-endian" ); - r = -ENOSYS ; - goto err; - } -if (!k->set_guest_notifiers) {error_report ("binding does not support guest notifiers" ); r = -ENOSYS ;