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 static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) 21 { 22 if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { 23 /* Devices conforming to VIRTIO 1.0 or later are always LE. */ 24 return false; 25 } 26 #if defined(TARGET_IS_BIENDIAN) 27 return virtio_is_big_endian(vdev); 28 #elif defined(TARGET_WORDS_BIGENDIAN) 29 return true; 30 #else 31 return false; 32 #endif 33 } 34 35 static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev) 36 { 37 #ifdef TARGET_IS_BIENDIAN 38 #ifdef HOST_WORDS_BIGENDIAN 39 return !virtio_is_big_endian(vdev); 40 #else 41 return virtio_is_big_endian(vdev); 42 #endif 43 #else 44 return false; 45 #endif 46 } 47 48 static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) 49 { 50 if (virtio_access_is_big_endian(vdev)) { 51 return lduw_be_phys(&address_space_memory, pa); 52 } 53 return lduw_le_phys(&address_space_memory, pa); 54 } 55 56 static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) 57 { 58 if (virtio_access_is_big_endian(vdev)) { 59 return ldl_be_phys(&address_space_memory, pa); 60 } 61 return ldl_le_phys(&address_space_memory, pa); 62 } 63 64 static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) 65 { 66 if (virtio_access_is_big_endian(vdev)) { 67 return ldq_be_phys(&address_space_memory, pa); 68 } 69 return ldq_le_phys(&address_space_memory, pa); 70 } 71 72 static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, 73 uint16_t value) 74 { 75 if (virtio_access_is_big_endian(vdev)) { 76 stw_be_phys(&address_space_memory, pa, value); 77 } else { 78 stw_le_phys(&address_space_memory, pa, value); 79 } 80 } 81 82 static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, 83 uint32_t value) 84 { 85 if (virtio_access_is_big_endian(vdev)) { 86 stl_be_phys(&address_space_memory, pa, value); 87 } else { 88 stl_le_phys(&address_space_memory, pa, value); 89 } 90 } 91 92 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) 93 { 94 if (virtio_access_is_big_endian(vdev)) { 95 stw_be_p(ptr, v); 96 } else { 97 stw_le_p(ptr, v); 98 } 99 } 100 101 static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) 102 { 103 if (virtio_access_is_big_endian(vdev)) { 104 stl_be_p(ptr, v); 105 } else { 106 stl_le_p(ptr, v); 107 } 108 } 109 110 static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) 111 { 112 if (virtio_access_is_big_endian(vdev)) { 113 stq_be_p(ptr, v); 114 } else { 115 stq_le_p(ptr, v); 116 } 117 } 118 119 static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) 120 { 121 if (virtio_access_is_big_endian(vdev)) { 122 return lduw_be_p(ptr); 123 } else { 124 return lduw_le_p(ptr); 125 } 126 } 127 128 static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) 129 { 130 if (virtio_access_is_big_endian(vdev)) { 131 return ldl_be_p(ptr); 132 } else { 133 return ldl_le_p(ptr); 134 } 135 } 136 137 static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) 138 { 139 if (virtio_access_is_big_endian(vdev)) { 140 return ldq_be_p(ptr); 141 } else { 142 return ldq_le_p(ptr); 143 } 144 } 145 146 static inline bool virtio_needs_swap(VirtIODevice *vdev) 147 { 148 #ifdef HOST_WORDS_BIGENDIAN 149 return virtio_access_is_big_endian(vdev) ? false : true; 150 #else 151 return virtio_access_is_big_endian(vdev) ? true : false; 152 #endif 153 } 154 155 static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 156 { 157 #ifdef HOST_WORDS_BIGENDIAN 158 return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 159 #else 160 return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 161 #endif 162 } 163 164 static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 165 { 166 *s = virtio_tswap16(vdev, *s); 167 } 168 169 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 170 { 171 #ifdef HOST_WORDS_BIGENDIAN 172 return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 173 #else 174 return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 175 #endif 176 } 177 178 static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 179 { 180 *s = virtio_tswap32(vdev, *s); 181 } 182 183 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 184 { 185 #ifdef HOST_WORDS_BIGENDIAN 186 return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 187 #else 188 return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 189 #endif 190 } 191 192 static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 193 { 194 *s = virtio_tswap64(vdev, *s); 195 } 196 #endif /* _QEMU_VIRTIO_ACCESS_H */ 197