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