1 /* 2 * Virtio Accessor Support: In case your target can change endian. 3 * 4 * Copyright IBM, Corp. 2013 5 * 6 * Authors: 7 * Rusty Russell <rusty@au.ibm.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation, either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 */ 15 #ifndef _QEMU_VIRTIO_ACCESS_H 16 #define _QEMU_VIRTIO_ACCESS_H 17 #include "hw/virtio/virtio.h" 18 #include "exec/address-spaces.h" 19 20 #if defined(TARGET_PPC64) || defined(TARGET_ARM) 21 #define LEGACY_VIRTIO_IS_BIENDIAN 1 22 #endif 23 24 static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) 25 { 26 #if defined(LEGACY_VIRTIO_IS_BIENDIAN) 27 return virtio_is_big_endian(vdev); 28 #elif defined(TARGET_WORDS_BIGENDIAN) 29 if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { 30 /* Devices conforming to VIRTIO 1.0 or later are always LE. */ 31 return false; 32 } 33 return true; 34 #else 35 return false; 36 #endif 37 } 38 39 static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) 40 { 41 if (virtio_access_is_big_endian(vdev)) { 42 return lduw_be_phys(&address_space_memory, pa); 43 } 44 return lduw_le_phys(&address_space_memory, pa); 45 } 46 47 static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) 48 { 49 if (virtio_access_is_big_endian(vdev)) { 50 return ldl_be_phys(&address_space_memory, pa); 51 } 52 return ldl_le_phys(&address_space_memory, pa); 53 } 54 55 static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) 56 { 57 if (virtio_access_is_big_endian(vdev)) { 58 return ldq_be_phys(&address_space_memory, pa); 59 } 60 return ldq_le_phys(&address_space_memory, pa); 61 } 62 63 static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, 64 uint16_t value) 65 { 66 if (virtio_access_is_big_endian(vdev)) { 67 stw_be_phys(&address_space_memory, pa, value); 68 } else { 69 stw_le_phys(&address_space_memory, pa, value); 70 } 71 } 72 73 static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, 74 uint32_t value) 75 { 76 if (virtio_access_is_big_endian(vdev)) { 77 stl_be_phys(&address_space_memory, pa, value); 78 } else { 79 stl_le_phys(&address_space_memory, pa, value); 80 } 81 } 82 83 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) 84 { 85 if (virtio_access_is_big_endian(vdev)) { 86 stw_be_p(ptr, v); 87 } else { 88 stw_le_p(ptr, v); 89 } 90 } 91 92 static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) 93 { 94 if (virtio_access_is_big_endian(vdev)) { 95 stl_be_p(ptr, v); 96 } else { 97 stl_le_p(ptr, v); 98 } 99 } 100 101 static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) 102 { 103 if (virtio_access_is_big_endian(vdev)) { 104 stq_be_p(ptr, v); 105 } else { 106 stq_le_p(ptr, v); 107 } 108 } 109 110 static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) 111 { 112 if (virtio_access_is_big_endian(vdev)) { 113 return lduw_be_p(ptr); 114 } else { 115 return lduw_le_p(ptr); 116 } 117 } 118 119 static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) 120 { 121 if (virtio_access_is_big_endian(vdev)) { 122 return ldl_be_p(ptr); 123 } else { 124 return ldl_le_p(ptr); 125 } 126 } 127 128 static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) 129 { 130 if (virtio_access_is_big_endian(vdev)) { 131 return ldq_be_p(ptr); 132 } else { 133 return ldq_le_p(ptr); 134 } 135 } 136 137 static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 138 { 139 #ifdef HOST_WORDS_BIGENDIAN 140 return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 141 #else 142 return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 143 #endif 144 } 145 146 static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 147 { 148 *s = virtio_tswap16(vdev, *s); 149 } 150 151 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 152 { 153 #ifdef HOST_WORDS_BIGENDIAN 154 return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 155 #else 156 return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 157 #endif 158 } 159 160 static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 161 { 162 *s = virtio_tswap32(vdev, *s); 163 } 164 165 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 166 { 167 #ifdef HOST_WORDS_BIGENDIAN 168 return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 169 #else 170 return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 171 #endif 172 } 173 174 static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 175 { 176 *s = virtio_tswap64(vdev, *s); 177 } 178 #endif /* _QEMU_VIRTIO_ACCESS_H */ 179