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 16 #ifndef QEMU_VIRTIO_ACCESS_H 17 #define QEMU_VIRTIO_ACCESS_H 18 19 #include "hw/virtio/virtio.h" 20 #include "hw/virtio/virtio-bus.h" 21 22 #if defined(TARGET_PPC64) || defined(TARGET_ARM) 23 #define LEGACY_VIRTIO_IS_BIENDIAN 1 24 #endif 25 26 static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) 27 { 28 #if defined(LEGACY_VIRTIO_IS_BIENDIAN) 29 return virtio_is_big_endian(vdev); 30 #elif defined(TARGET_WORDS_BIGENDIAN) 31 if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { 32 /* Devices conforming to VIRTIO 1.0 or later are always LE. */ 33 return false; 34 } 35 return true; 36 #else 37 return false; 38 #endif 39 } 40 41 static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) 42 { 43 AddressSpace *dma_as = vdev->dma_as; 44 45 if (virtio_access_is_big_endian(vdev)) { 46 return lduw_be_phys(dma_as, pa); 47 } 48 return lduw_le_phys(dma_as, pa); 49 } 50 51 static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) 52 { 53 AddressSpace *dma_as = vdev->dma_as; 54 55 if (virtio_access_is_big_endian(vdev)) { 56 return ldl_be_phys(dma_as, pa); 57 } 58 return ldl_le_phys(dma_as, pa); 59 } 60 61 static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) 62 { 63 AddressSpace *dma_as = vdev->dma_as; 64 65 if (virtio_access_is_big_endian(vdev)) { 66 return ldq_be_phys(dma_as, pa); 67 } 68 return ldq_le_phys(dma_as, pa); 69 } 70 71 static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, 72 uint16_t value) 73 { 74 AddressSpace *dma_as = vdev->dma_as; 75 76 if (virtio_access_is_big_endian(vdev)) { 77 stw_be_phys(dma_as, pa, value); 78 } else { 79 stw_le_phys(dma_as, pa, value); 80 } 81 } 82 83 static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, 84 uint32_t value) 85 { 86 AddressSpace *dma_as = vdev->dma_as; 87 88 if (virtio_access_is_big_endian(vdev)) { 89 stl_be_phys(dma_as, pa, value); 90 } else { 91 stl_le_phys(dma_as, pa, value); 92 } 93 } 94 95 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) 96 { 97 if (virtio_access_is_big_endian(vdev)) { 98 stw_be_p(ptr, v); 99 } else { 100 stw_le_p(ptr, v); 101 } 102 } 103 104 static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) 105 { 106 if (virtio_access_is_big_endian(vdev)) { 107 stl_be_p(ptr, v); 108 } else { 109 stl_le_p(ptr, v); 110 } 111 } 112 113 static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) 114 { 115 if (virtio_access_is_big_endian(vdev)) { 116 stq_be_p(ptr, v); 117 } else { 118 stq_le_p(ptr, v); 119 } 120 } 121 122 static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) 123 { 124 if (virtio_access_is_big_endian(vdev)) { 125 return lduw_be_p(ptr); 126 } else { 127 return lduw_le_p(ptr); 128 } 129 } 130 131 static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) 132 { 133 if (virtio_access_is_big_endian(vdev)) { 134 return ldl_be_p(ptr); 135 } else { 136 return ldl_le_p(ptr); 137 } 138 } 139 140 static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) 141 { 142 if (virtio_access_is_big_endian(vdev)) { 143 return ldq_be_p(ptr); 144 } else { 145 return ldq_le_p(ptr); 146 } 147 } 148 149 static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 150 { 151 #ifdef HOST_WORDS_BIGENDIAN 152 return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 153 #else 154 return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 155 #endif 156 } 157 158 static inline uint16_t virtio_lduw_phys_cached(VirtIODevice *vdev, 159 MemoryRegionCache *cache, 160 hwaddr pa) 161 { 162 if (virtio_access_is_big_endian(vdev)) { 163 return lduw_be_phys_cached(cache, pa); 164 } 165 return lduw_le_phys_cached(cache, pa); 166 } 167 168 static inline uint32_t virtio_ldl_phys_cached(VirtIODevice *vdev, 169 MemoryRegionCache *cache, 170 hwaddr pa) 171 { 172 if (virtio_access_is_big_endian(vdev)) { 173 return ldl_be_phys_cached(cache, pa); 174 } 175 return ldl_le_phys_cached(cache, pa); 176 } 177 178 static inline uint64_t virtio_ldq_phys_cached(VirtIODevice *vdev, 179 MemoryRegionCache *cache, 180 hwaddr pa) 181 { 182 if (virtio_access_is_big_endian(vdev)) { 183 return ldq_be_phys_cached(cache, pa); 184 } 185 return ldq_le_phys_cached(cache, pa); 186 } 187 188 static inline void virtio_stw_phys_cached(VirtIODevice *vdev, 189 MemoryRegionCache *cache, 190 hwaddr pa, uint16_t value) 191 { 192 if (virtio_access_is_big_endian(vdev)) { 193 stw_be_phys_cached(cache, pa, value); 194 } else { 195 stw_le_phys_cached(cache, pa, value); 196 } 197 } 198 199 static inline void virtio_stl_phys_cached(VirtIODevice *vdev, 200 MemoryRegionCache *cache, 201 hwaddr pa, uint32_t value) 202 { 203 if (virtio_access_is_big_endian(vdev)) { 204 stl_be_phys_cached(cache, pa, value); 205 } else { 206 stl_le_phys_cached(cache, pa, value); 207 } 208 } 209 210 static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 211 { 212 *s = virtio_tswap16(vdev, *s); 213 } 214 215 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 216 { 217 #ifdef HOST_WORDS_BIGENDIAN 218 return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 219 #else 220 return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 221 #endif 222 } 223 224 static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 225 { 226 *s = virtio_tswap32(vdev, *s); 227 } 228 229 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 230 { 231 #ifdef HOST_WORDS_BIGENDIAN 232 return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 233 #else 234 return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 235 #endif 236 } 237 238 static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 239 { 240 *s = virtio_tswap64(vdev, *s); 241 } 242 #endif /* QEMU_VIRTIO_ACCESS_H */ 243