[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 04/10] vhost: set vring endianness for legacy virtio
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] [PULL 04/10] vhost: set vring endianness for legacy virtio |
Date: |
Wed, 17 Jun 2015 21:38:12 +0200 |
From: Greg Kurz <address@hidden>
Legacy virtio is native endian: if the guest and host endianness differ,
we have to tell vhost so it can swap bytes where appropriate. This is
done through a vhost ring ioctl.
Signed-off-by: Greg Kurz <address@hidden>
Reviewed-by: Michael S. Tsirkin <address@hidden>
Signed-off-by: Michael S. Tsirkin <address@hidden>
---
hw/virtio/vhost.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7908255..7ea45b3 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -17,9 +17,11 @@
#include "hw/hw.h"
#include "qemu/atomic.h"
#include "qemu/range.h"
+#include "qemu/error-report.h"
#include <linux/vhost.h>
#include "exec/address-spaces.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/virtio-access.h"
#include "migration/migration.h"
static struct vhost_log *vhost_log;
@@ -686,6 +688,27 @@ static void vhost_log_stop(MemoryListener *listener,
/* FIXME: implement */
}
+static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
+ bool is_big_endian,
+ int vhost_vq_index)
+{
+ struct vhost_vring_state s = {
+ .index = vhost_vq_index,
+ .num = is_big_endian
+ };
+
+ if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) {
+ return 0;
+ }
+
+ if (errno == ENOTTY) {
+ error_report("vhost does not support cross-endian");
+ return -ENOSYS;
+ }
+
+ return -errno;
+}
+
static int vhost_virtqueue_start(struct vhost_dev *dev,
struct VirtIODevice *vdev,
struct vhost_virtqueue *vq,
@@ -716,6 +739,16 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
return -errno;
}
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ virtio_legacy_is_cross_endian(vdev)) {
+ r = vhost_virtqueue_set_vring_endian_legacy(dev,
+ virtio_is_big_endian(vdev),
+ vhost_vq_index);
+ if (r) {
+ return -errno;
+ }
+ }
+
s = l = virtio_queue_get_desc_size(vdev, idx);
a = virtio_queue_get_desc_addr(vdev, idx);
vq->desc = cpu_physical_memory_map(a, &l, 0);
@@ -786,8 +819,9 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
struct vhost_virtqueue *vq,
unsigned idx)
{
+ int vhost_vq_index = idx - dev->vq_index;
struct vhost_vring_state state = {
- .index = idx - dev->vq_index
+ .index = vhost_vq_index,
};
int r;
assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
@@ -798,6 +832,20 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
}
virtio_queue_set_last_avail_idx(vdev, idx, state.num);
virtio_queue_invalidate_signalled_used(vdev, idx);
+
+ /* In the cross-endian case, we need to reset the vring endianness to
+ * native as legacy devices expect so by default.
+ */
+ if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1) &&
+ virtio_legacy_is_cross_endian(vdev)) {
+ r = vhost_virtqueue_set_vring_endian_legacy(dev,
+
!virtio_is_big_endian(vdev),
+ vhost_vq_index);
+ if (r < 0) {
+ error_report("failed to reset vring endianness");
+ }
+ }
+
assert (r >= 0);
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
0, virtio_queue_get_ring_size(vdev, idx));
--
MST
- [Qemu-devel] [PULL 00/10] virtio, pci fixes, enhancements, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 01/10] vhost-user: part of virtio, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 02/10] linux-headers: sync vhost.h, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 03/10] virtio: introduce virtio_legacy_is_cross_endian(), Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 04/10] vhost: set vring endianness for legacy virtio,
Michael S. Tsirkin <=
- [Qemu-devel] [PULL 05/10] tap: add VNET_LE/VNET_BE operations, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 07/10] vhost_net: re-enable when cross endian, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 08/10] hw/core: rebase sysbus_get_fw_dev_path() to g_strdup_printf(), Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 06/10] vhost-net: tell tap backend about the vnet endianness, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 09/10] pci: Don't register a specialized 'config_write' if default behavior is intended, Michael S. Tsirkin, 2015/06/17
- [Qemu-devel] [PULL 10/10] vhost: enable vhost without without MSI-X, Michael S. Tsirkin, 2015/06/17
- Re: [Qemu-devel] [PULL 00/10] virtio, pci fixes, enhancements, Peter Maydell, 2015/06/18