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_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 uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 147 { 148 #ifdef HOST_WORDS_BIGENDIAN 149 return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 150 #else 151 return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 152 #endif 153 } 154 155 static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 156 { 157 *s = virtio_tswap16(vdev, *s); 158 } 159 160 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 161 { 162 #ifdef HOST_WORDS_BIGENDIAN 163 return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 164 #else 165 return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 166 #endif 167 } 168 169 static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 170 { 171 *s = virtio_tswap32(vdev, *s); 172 } 173 174 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 175 { 176 #ifdef HOST_WORDS_BIGENDIAN 177 return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 178 #else 179 return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 180 #endif 181 } 182 183 static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 184 { 185 *s = virtio_tswap64(vdev, *s); 186 } 187 #endif /* _QEMU_VIRTIO_ACCESS_H */ 188