Re: [PATCH 2/7] kvmtool: virt_queue: handle guest endianness

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/10/13 15:50, Will Deacon wrote:
On Fri, Oct 11, 2013 at 03:36:30PM +0100, Marc Zyngier wrote:
Wrap all accesses to virt_queue data structures shared between
host and guest with byte swapping helpers.

Should the architecture only support one endianness, these helpers
are reduced to the identity function.

Cc: Pekka Enberg <penberg@xxxxxxxxxx>
Cc: Will Deacon <will.deacon@xxxxxxx>
Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
---
  tools/kvm/include/kvm/virtio.h | 189 ++++++++++++++++++++++++++++++++++++++++-
  tools/kvm/virtio/core.c        |  59 +++++++------
  2 files changed, 219 insertions(+), 29 deletions(-)

diff --git a/tools/kvm/include/kvm/virtio.h b/tools/kvm/include/kvm/virtio.h
index d6b0f47..04ec137 100644
--- a/tools/kvm/include/kvm/virtio.h
+++ b/tools/kvm/include/kvm/virtio.h
@@ -1,6 +1,8 @@
  #ifndef KVM__VIRTIO_H
  #define KVM__VIRTIO_H

+#include <endian.h>
+
  #include <linux/virtio_ring.h>
  #include <linux/virtio_pci.h>

@@ -29,15 +31,194 @@ struct virt_queue {
  	u16		endian;
  };

+/*
+ * The default policy is not to cope with the guest endianness.
+ * It also helps not breaking archs that do not care about supporting
+ * such a configuration.
+ */

Jesus Marc, are you *trying* to crash my preprocessor? Seriously though,
maybe this is better done as a block:

#if __BYTE_ORDER == __BIG_ENDIAN
#define	virtio_le16toh(x)	le16toh(x)
#define virtio_be16toh(x)
[...]


The preprocessor magic to turn the functions into one-liners is pretty gruesome in itself, though...

+#ifndef VIRTIO_RING_ENDIAN
+#define VIRTIO_RING_ENDIAN 0
+#endif
+
+#if (VIRTIO_RING_ENDIAN & ((1UL << VIRTIO_RING_F_GUEST_LE) | (1UL << VIRTIO_RING_F_GUEST_BE)))
+
+#ifndef __BYTE_ORDER
+#error "No byteorder? Giving up..."
+#endif

#ifdef __BYTE_ORDER
#if __BYTE_ORDER == __BIG_ENDIAN
#define BYTEORDER_TOKEN	be
#define ENDIAN_OPPOSITE	VIRTIO_ENDIAN_LE
#else
#define BYTEORDER_TOKEN	le
#define ENDIAN_OPPOSITE	VIRTIO_ENDIAN_BE
#endif
#define _CAT3(a,b,c)	a##b##c
#define CAT3(a,b,c)	_CAT3(a,b,c)
#define vio_gtoh(size, val) (endian==ENDIAN_OPPOSITE) ?\
	CAT3(BYTEORDER_TOKEN,size,toh(val)) : val
#define vio_htog(size, val) (endian==ENDIAN_OPPOSITE) ?\
	CAT3(hto,BYTEORDER_TOKEN,size(val)) : val
#else
#error "No byteorder? Giving up..."
#endif

+
+
+static inline __u16 __virtio_guest_to_host_u16(u16 endian, __u16 val)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+	if (endian == VIRTIO_ENDIAN_LE)
+		return le16toh(val);
+#else
+	if (endian == VIRTIO_ENDIAN_BE)
+		return be16toh(val);
+#endif

{
	return vio_gtoh(16, val);
}

On the upside however, it does remove all the duplication and keep all the mess in one place.

Robin.


Then you can just use the endian parameter to do the right thing.

Will

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux