virtio data structures are defined as "target endian", which assumes that's a fixed value. In fact, that actually means it's platform-specific.
Hopefully the OASIS virtio 1.0 spec will fix this. Meanwhile, create a hook for little endian ppc. Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> --- include/hw/virtio/virtio-access.h | 130 ++++++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio.h | 2 + stubs/Makefile.objs | 1 + stubs/virtio_get_byteswap.c | 6 ++ 4 files changed, 139 insertions(+) create mode 100644 include/hw/virtio/virtio-access.h create mode 100644 stubs/virtio_get_byteswap.c diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h new file mode 100644 index 0000000..01d7dd6 --- /dev/null +++ b/include/hw/virtio/virtio-access.h @@ -0,0 +1,130 @@ +/* + * Virtio Accessor Support: In case your target can change endian. + * + * Copyright IBM, Corp. 2013 + * + * Authors: + * Rusty Russell <ru...@au.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ +#ifndef _QEMU_VIRTIO_ACCESS_H +#define _QEMU_VIRTIO_ACCESS_H +#include "hw/virtio/virtio.h" + +static inline uint16_t virtio_lduw_phys(hwaddr pa) +{ + if (virtio_get_byteswap()) { + return bswap16(lduw_phys(pa)); + } + return lduw_phys(pa); + +} + +static inline uint32_t virtio_ldl_phys(hwaddr pa) +{ + if (virtio_get_byteswap()) { + return bswap32(ldl_phys(pa)); + } + return ldl_phys(pa); +} + +static inline uint64_t virtio_ldq_phys(hwaddr pa) +{ + if (virtio_get_byteswap()) { + return bswap64(ldq_phys(pa)); + } + return ldq_phys(pa); +} + +static inline void virtio_stw_phys(hwaddr pa, uint16_t value) +{ + if (virtio_get_byteswap()) { + stw_phys(pa, bswap16(value)); + } else { + stw_phys(pa, value); + } +} + +static inline void virtio_stl_phys(hwaddr pa, uint32_t value) +{ + if (virtio_get_byteswap()) { + stl_phys(pa, bswap32(value)); + } else { + stl_phys(pa, value); + } +} + +static inline void virtio_stw_p(void *ptr, uint16_t v) +{ + if (virtio_get_byteswap()) { + stw_p(ptr, bswap16(v)); + } else { + stw_p(ptr, v); + } +} + +static inline void virtio_stl_p(void *ptr, uint32_t v) +{ + if (virtio_get_byteswap()) { + stl_p(ptr, bswap32(v)); + } else { + stl_p(ptr, v); + } +} + +static inline void virtio_stq_p(void *ptr, uint64_t v) +{ + if (virtio_get_byteswap()) { + stq_p(ptr, bswap64(v)); + } else { + stq_p(ptr, v); + } +} + +static inline int virtio_lduw_p(const void *ptr) +{ + if (virtio_get_byteswap()) { + return bswap16(lduw_p(ptr)); + } else { + return lduw_p(ptr); + } +} + +static inline int virtio_ldl_p(const void *ptr) +{ + if (virtio_get_byteswap()) { + return bswap32(ldl_p(ptr)); + } else { + return ldl_p(ptr); + } +} + +static inline uint64_t virtio_ldq_p(const void *ptr) +{ + if (virtio_get_byteswap()) { + return bswap64(ldq_p(ptr)); + } else { + return ldq_p(ptr); + } +} + +static inline uint32_t virtio_tswap32(uint32_t s) +{ + if (virtio_get_byteswap()) { + return bswap32(tswap32(s)); + } else { + return tswap32(s); + } +} + +static inline void virtio_tswap32s(uint32_t *s) +{ + tswap32s(s); + if (virtio_get_byteswap()) { + *s = bswap32(*s); + } +} +#endif /* _QEMU_VIRTIO_ACCESS_H */ diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index d7e9e0f..18ca725 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -248,4 +248,6 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, bool set_handler); void virtio_queue_notify_vq(VirtQueue *vq); void virtio_irq(VirtQueue *vq); + +extern bool virtio_get_byteswap(void); #endif diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index f306cba..05f7bab 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -26,3 +26,4 @@ stub-obj-y += vm-stop.o stub-obj-y += vmstate.o stub-obj-$(CONFIG_WIN32) += fd-register.o stub-obj-y += cpus.o +stub-obj-y += virtio_get_byteswap.o diff --git a/stubs/virtio_get_byteswap.c b/stubs/virtio_get_byteswap.c new file mode 100644 index 0000000..7cf764d --- /dev/null +++ b/stubs/virtio_get_byteswap.c @@ -0,0 +1,6 @@ +#include "hw/virtio/virtio.h" + +bool virtio_get_byteswap(void) +{ + return false; +} -- 1.8.1.2