When adding cross-endian support, we introduced the TARGET_IS_BIENDIAN macro and the virtio_access_is_big_endian() helper to have a branchless fast path in the virtio memory accessors for targets that don't switch endian.
This was considered as a strong requirement at the time. Now we have added a runtime check for virtio 1.0, which ruins the benefit of the virtio_access_is_big_endian() helper for always little-endian targets. With this patch, fixed little-endian targets stop checking for virtio 1.0, since the result is little-endian in all cases. The helper also gets renamed so it is clear it is optimized for fast paths. Signed-off-by: Greg Kurz <gk...@linux.vnet.ibm.com> --- include/hw/virtio/virtio-access.h | 43 ++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h index ba1530619939..ff013519b9dc 100644 --- a/include/hw/virtio/virtio-access.h +++ b/include/hw/virtio/virtio-access.h @@ -17,12 +17,15 @@ #include "hw/virtio/virtio.h" #include "exec/address-spaces.h" -static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) +static inline bool virtio_is_big_endian_fast(VirtIODevice *vdev) { +#if defined(TARGET_IS_BIENDIAN) || defined(TARGET_WORDS_BIGENDIAN) if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { /* Devices conforming to VIRTIO 1.0 or later are always LE. */ return false; } +#endif + #if defined(TARGET_IS_BIENDIAN) return virtio_is_big_endian(vdev); #elif defined(TARGET_WORDS_BIGENDIAN) @@ -34,7 +37,7 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { return lduw_be_phys(&address_space_memory, pa); } return lduw_le_phys(&address_space_memory, pa); @@ -42,7 +45,7 @@ static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { return ldl_be_phys(&address_space_memory, pa); } return ldl_le_phys(&address_space_memory, pa); @@ -50,7 +53,7 @@ static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { return ldq_be_phys(&address_space_memory, pa); } return ldq_le_phys(&address_space_memory, pa); @@ -59,7 +62,7 @@ static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, uint16_t value) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { stw_be_phys(&address_space_memory, pa, value); } else { stw_le_phys(&address_space_memory, pa, value); @@ -69,7 +72,7 @@ static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, uint32_t value) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { stl_be_phys(&address_space_memory, pa, value); } else { stl_le_phys(&address_space_memory, pa, value); @@ -78,7 +81,7 @@ static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { stw_be_p(ptr, v); } else { stw_le_p(ptr, v); @@ -87,7 +90,7 @@ static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { stl_be_p(ptr, v); } else { stl_le_p(ptr, v); @@ -96,7 +99,7 @@ static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { stq_be_p(ptr, v); } else { stq_le_p(ptr, v); @@ -105,7 +108,7 @@ static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { return lduw_be_p(ptr); } else { return lduw_le_p(ptr); @@ -114,7 +117,7 @@ static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { return ldl_be_p(ptr); } else { return ldl_le_p(ptr); @@ -123,7 +126,7 @@ static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) { - if (virtio_access_is_big_endian(vdev)) { + if (virtio_is_big_endian_fast(vdev)) { return ldq_be_p(ptr); } else { return ldq_le_p(ptr); @@ -133,18 +136,18 @@ static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) static inline bool virtio_needs_swap(VirtIODevice *vdev) { #ifdef HOST_WORDS_BIGENDIAN - return virtio_access_is_big_endian(vdev) ? false : true; + return virtio_is_big_endian_fast(vdev) ? false : true; #else - return virtio_access_is_big_endian(vdev) ? true : false; + return virtio_is_big_endian_fast(vdev) ? true : false; #endif } static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) { #ifdef HOST_WORDS_BIGENDIAN - return virtio_access_is_big_endian(vdev) ? s : bswap16(s); + return virtio_is_big_endian_fast(vdev) ? s : bswap16(s); #else - return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; + return virtio_is_big_endian_fast(vdev) ? bswap16(s) : s; #endif } @@ -156,9 +159,9 @@ static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) { #ifdef HOST_WORDS_BIGENDIAN - return virtio_access_is_big_endian(vdev) ? s : bswap32(s); + return virtio_is_big_endian_fast(vdev) ? s : bswap32(s); #else - return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; + return virtio_is_big_endian_fast(vdev) ? bswap32(s) : s; #endif } @@ -170,9 +173,9 @@ static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) { #ifdef HOST_WORDS_BIGENDIAN - return virtio_access_is_big_endian(vdev) ? s : bswap64(s); + return virtio_is_big_endian_fast(vdev) ? s : bswap64(s); #else - return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; + return virtio_is_big_endian_fast(vdev) ? bswap64(s) : s; #endif }