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 "exec/address-spaces.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 if (virtio_access_is_big_endian(vdev)) { 44 return lduw_be_phys(&address_space_memory, pa); 45 } 46 return lduw_le_phys(&address_space_memory, pa); 47 } 48 49 static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) 50 { 51 if (virtio_access_is_big_endian(vdev)) { 52 return ldl_be_phys(&address_space_memory, pa); 53 } 54 return ldl_le_phys(&address_space_memory, pa); 55 } 56 57 static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) 58 { 59 if (virtio_access_is_big_endian(vdev)) { 60 return ldq_be_phys(&address_space_memory, pa); 61 } 62 return ldq_le_phys(&address_space_memory, pa); 63 } 64 65 static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, 66 uint16_t value) 67 { 68 if (virtio_access_is_big_endian(vdev)) { 69 stw_be_phys(&address_space_memory, pa, value); 70 } else { 71 stw_le_phys(&address_space_memory, pa, value); 72 } 73 } 74 75 static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, 76 uint32_t value) 77 { 78 if (virtio_access_is_big_endian(vdev)) { 79 stl_be_phys(&address_space_memory, pa, value); 80 } else { 81 stl_le_phys(&address_space_memory, pa, value); 82 } 83 } 84 85 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) 86 { 87 if (virtio_access_is_big_endian(vdev)) { 88 stw_be_p(ptr, v); 89 } else { 90 stw_le_p(ptr, v); 91 } 92 } 93 94 static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) 95 { 96 if (virtio_access_is_big_endian(vdev)) { 97 stl_be_p(ptr, v); 98 } else { 99 stl_le_p(ptr, v); 100 } 101 } 102 103 static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) 104 { 105 if (virtio_access_is_big_endian(vdev)) { 106 stq_be_p(ptr, v); 107 } else { 108 stq_le_p(ptr, v); 109 } 110 } 111 112 static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) 113 { 114 if (virtio_access_is_big_endian(vdev)) { 115 return lduw_be_p(ptr); 116 } else { 117 return lduw_le_p(ptr); 118 } 119 } 120 121 static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) 122 { 123 if (virtio_access_is_big_endian(vdev)) { 124 return ldl_be_p(ptr); 125 } else { 126 return ldl_le_p(ptr); 127 } 128 } 129 130 static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) 131 { 132 if (virtio_access_is_big_endian(vdev)) { 133 return ldq_be_p(ptr); 134 } else { 135 return ldq_le_p(ptr); 136 } 137 } 138 139 static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 140 { 141 #ifdef HOST_WORDS_BIGENDIAN 142 return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 143 #else 144 return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 145 #endif 146 } 147 148 static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 149 { 150 *s = virtio_tswap16(vdev, *s); 151 } 152 153 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 154 { 155 #ifdef HOST_WORDS_BIGENDIAN 156 return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 157 #else 158 return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 159 #endif 160 } 161 162 static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 163 { 164 *s = virtio_tswap32(vdev, *s); 165 } 166 167 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 168 { 169 #ifdef HOST_WORDS_BIGENDIAN 170 return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 171 #else 172 return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 173 #endif 174 } 175 176 static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 177 { 178 *s = virtio_tswap64(vdev, *s); 179 } 180 #endif /* QEMU_VIRTIO_ACCESS_H */ 181