10f5d1d2aSGreg Kurz /* 20f5d1d2aSGreg Kurz * Virtio Accessor Support: In case your target can change endian. 30f5d1d2aSGreg Kurz * 40f5d1d2aSGreg Kurz * Copyright IBM, Corp. 2013 50f5d1d2aSGreg Kurz * 60f5d1d2aSGreg Kurz * Authors: 70f5d1d2aSGreg Kurz * Rusty Russell <rusty@au.ibm.com> 80f5d1d2aSGreg Kurz * 90f5d1d2aSGreg Kurz * This program is free software; you can redistribute it and/or modify 100f5d1d2aSGreg Kurz * it under the terms of the GNU General Public License as published by 110f5d1d2aSGreg Kurz * the Free Software Foundation, either version 2 of the License, or 120f5d1d2aSGreg Kurz * (at your option) any later version. 130f5d1d2aSGreg Kurz * 140f5d1d2aSGreg Kurz */ 152a6a4076SMarkus Armbruster 162a6a4076SMarkus Armbruster #ifndef QEMU_VIRTIO_ACCESS_H 172a6a4076SMarkus Armbruster #define QEMU_VIRTIO_ACCESS_H 182a6a4076SMarkus Armbruster 19ec150c7eSMarkus Armbruster #include "exec/hwaddr.h" 200f5d1d2aSGreg Kurz #include "hw/virtio/virtio.h" 218607f5c3SJason Wang #include "hw/virtio/virtio-bus.h" 220f5d1d2aSGreg Kurz 23c02d7030SGreg Kurz #if defined(TARGET_PPC64) || defined(TARGET_ARM) 24c02d7030SGreg Kurz #define LEGACY_VIRTIO_IS_BIENDIAN 1 25c02d7030SGreg Kurz #endif 26c02d7030SGreg Kurz 270f5d1d2aSGreg Kurz static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) 280f5d1d2aSGreg Kurz { 29c02d7030SGreg Kurz #if defined(LEGACY_VIRTIO_IS_BIENDIAN) 30e5157e31SGreg Kurz return virtio_is_big_endian(vdev); 31*ee3eb3a7SMarc-André Lureau #elif TARGET_BIG_ENDIAN 3295129d6fSCornelia Huck if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { 333c185597SCornelia Huck /* Devices conforming to VIRTIO 1.0 or later are always LE. */ 343c185597SCornelia Huck return false; 353c185597SCornelia Huck } 360f5d1d2aSGreg Kurz return true; 370f5d1d2aSGreg Kurz #else 380f5d1d2aSGreg Kurz return false; 390f5d1d2aSGreg Kurz #endif 400f5d1d2aSGreg Kurz } 410f5d1d2aSGreg Kurz 420f5d1d2aSGreg Kurz static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) 430f5d1d2aSGreg Kurz { 448607f5c3SJason Wang AddressSpace *dma_as = vdev->dma_as; 458607f5c3SJason Wang 460f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 478607f5c3SJason Wang return lduw_be_phys(dma_as, pa); 480f5d1d2aSGreg Kurz } 498607f5c3SJason Wang return lduw_le_phys(dma_as, pa); 500f5d1d2aSGreg Kurz } 510f5d1d2aSGreg Kurz 520f5d1d2aSGreg Kurz static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) 530f5d1d2aSGreg Kurz { 548607f5c3SJason Wang AddressSpace *dma_as = vdev->dma_as; 558607f5c3SJason Wang 560f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 578607f5c3SJason Wang return ldl_be_phys(dma_as, pa); 580f5d1d2aSGreg Kurz } 598607f5c3SJason Wang return ldl_le_phys(dma_as, pa); 600f5d1d2aSGreg Kurz } 610f5d1d2aSGreg Kurz 620f5d1d2aSGreg Kurz static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) 630f5d1d2aSGreg Kurz { 648607f5c3SJason Wang AddressSpace *dma_as = vdev->dma_as; 658607f5c3SJason Wang 660f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 678607f5c3SJason Wang return ldq_be_phys(dma_as, pa); 680f5d1d2aSGreg Kurz } 698607f5c3SJason Wang return ldq_le_phys(dma_as, pa); 700f5d1d2aSGreg Kurz } 710f5d1d2aSGreg Kurz 720f5d1d2aSGreg Kurz static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, 730f5d1d2aSGreg Kurz uint16_t value) 740f5d1d2aSGreg Kurz { 758607f5c3SJason Wang AddressSpace *dma_as = vdev->dma_as; 768607f5c3SJason Wang 770f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 788607f5c3SJason Wang stw_be_phys(dma_as, pa, value); 790f5d1d2aSGreg Kurz } else { 808607f5c3SJason Wang stw_le_phys(dma_as, pa, value); 810f5d1d2aSGreg Kurz } 820f5d1d2aSGreg Kurz } 830f5d1d2aSGreg Kurz 840f5d1d2aSGreg Kurz static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, 850f5d1d2aSGreg Kurz uint32_t value) 860f5d1d2aSGreg Kurz { 878607f5c3SJason Wang AddressSpace *dma_as = vdev->dma_as; 888607f5c3SJason Wang 890f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 908607f5c3SJason Wang stl_be_phys(dma_as, pa, value); 910f5d1d2aSGreg Kurz } else { 928607f5c3SJason Wang stl_le_phys(dma_as, pa, value); 930f5d1d2aSGreg Kurz } 940f5d1d2aSGreg Kurz } 950f5d1d2aSGreg Kurz 960f5d1d2aSGreg Kurz static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) 970f5d1d2aSGreg Kurz { 980f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 990f5d1d2aSGreg Kurz stw_be_p(ptr, v); 1000f5d1d2aSGreg Kurz } else { 1010f5d1d2aSGreg Kurz stw_le_p(ptr, v); 1020f5d1d2aSGreg Kurz } 1030f5d1d2aSGreg Kurz } 1040f5d1d2aSGreg Kurz 1050f5d1d2aSGreg Kurz static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) 1060f5d1d2aSGreg Kurz { 1070f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1080f5d1d2aSGreg Kurz stl_be_p(ptr, v); 1090f5d1d2aSGreg Kurz } else { 1100f5d1d2aSGreg Kurz stl_le_p(ptr, v); 1110f5d1d2aSGreg Kurz } 1120f5d1d2aSGreg Kurz } 1130f5d1d2aSGreg Kurz 1140f5d1d2aSGreg Kurz static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) 1150f5d1d2aSGreg Kurz { 1160f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1170f5d1d2aSGreg Kurz stq_be_p(ptr, v); 1180f5d1d2aSGreg Kurz } else { 1190f5d1d2aSGreg Kurz stq_le_p(ptr, v); 1200f5d1d2aSGreg Kurz } 1210f5d1d2aSGreg Kurz } 1220f5d1d2aSGreg Kurz 1230f5d1d2aSGreg Kurz static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) 1240f5d1d2aSGreg Kurz { 1250f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1260f5d1d2aSGreg Kurz return lduw_be_p(ptr); 1270f5d1d2aSGreg Kurz } else { 1280f5d1d2aSGreg Kurz return lduw_le_p(ptr); 1290f5d1d2aSGreg Kurz } 1300f5d1d2aSGreg Kurz } 1310f5d1d2aSGreg Kurz 1320f5d1d2aSGreg Kurz static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) 1330f5d1d2aSGreg Kurz { 1340f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1350f5d1d2aSGreg Kurz return ldl_be_p(ptr); 1360f5d1d2aSGreg Kurz } else { 1370f5d1d2aSGreg Kurz return ldl_le_p(ptr); 1380f5d1d2aSGreg Kurz } 1390f5d1d2aSGreg Kurz } 1400f5d1d2aSGreg Kurz 1410f5d1d2aSGreg Kurz static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) 1420f5d1d2aSGreg Kurz { 1430f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1440f5d1d2aSGreg Kurz return ldq_be_p(ptr); 1450f5d1d2aSGreg Kurz } else { 1460f5d1d2aSGreg Kurz return ldq_le_p(ptr); 1470f5d1d2aSGreg Kurz } 1480f5d1d2aSGreg Kurz } 1490f5d1d2aSGreg Kurz 1500f5d1d2aSGreg Kurz static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 1510f5d1d2aSGreg Kurz { 152e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 1530f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 1540f5d1d2aSGreg Kurz #else 1550f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 1560f5d1d2aSGreg Kurz #endif 1570f5d1d2aSGreg Kurz } 1580f5d1d2aSGreg Kurz 159e6a830d6SPaolo Bonzini static inline uint16_t virtio_lduw_phys_cached(VirtIODevice *vdev, 160e6a830d6SPaolo Bonzini MemoryRegionCache *cache, 161e6a830d6SPaolo Bonzini hwaddr pa) 162e6a830d6SPaolo Bonzini { 163e6a830d6SPaolo Bonzini if (virtio_access_is_big_endian(vdev)) { 164e6a830d6SPaolo Bonzini return lduw_be_phys_cached(cache, pa); 165e6a830d6SPaolo Bonzini } 166e6a830d6SPaolo Bonzini return lduw_le_phys_cached(cache, pa); 167e6a830d6SPaolo Bonzini } 168e6a830d6SPaolo Bonzini 169e6a830d6SPaolo Bonzini static inline uint32_t virtio_ldl_phys_cached(VirtIODevice *vdev, 170e6a830d6SPaolo Bonzini MemoryRegionCache *cache, 171e6a830d6SPaolo Bonzini hwaddr pa) 172e6a830d6SPaolo Bonzini { 173e6a830d6SPaolo Bonzini if (virtio_access_is_big_endian(vdev)) { 174e6a830d6SPaolo Bonzini return ldl_be_phys_cached(cache, pa); 175e6a830d6SPaolo Bonzini } 176e6a830d6SPaolo Bonzini return ldl_le_phys_cached(cache, pa); 177e6a830d6SPaolo Bonzini } 178e6a830d6SPaolo Bonzini 179e6a830d6SPaolo Bonzini static inline uint64_t virtio_ldq_phys_cached(VirtIODevice *vdev, 180e6a830d6SPaolo Bonzini MemoryRegionCache *cache, 181e6a830d6SPaolo Bonzini hwaddr pa) 182e6a830d6SPaolo Bonzini { 183e6a830d6SPaolo Bonzini if (virtio_access_is_big_endian(vdev)) { 184e6a830d6SPaolo Bonzini return ldq_be_phys_cached(cache, pa); 185e6a830d6SPaolo Bonzini } 186e6a830d6SPaolo Bonzini return ldq_le_phys_cached(cache, pa); 187e6a830d6SPaolo Bonzini } 188e6a830d6SPaolo Bonzini 189e6a830d6SPaolo Bonzini static inline void virtio_stw_phys_cached(VirtIODevice *vdev, 190e6a830d6SPaolo Bonzini MemoryRegionCache *cache, 191e6a830d6SPaolo Bonzini hwaddr pa, uint16_t value) 192e6a830d6SPaolo Bonzini { 193e6a830d6SPaolo Bonzini if (virtio_access_is_big_endian(vdev)) { 194e6a830d6SPaolo Bonzini stw_be_phys_cached(cache, pa, value); 195e6a830d6SPaolo Bonzini } else { 196e6a830d6SPaolo Bonzini stw_le_phys_cached(cache, pa, value); 197e6a830d6SPaolo Bonzini } 198e6a830d6SPaolo Bonzini } 199e6a830d6SPaolo Bonzini 200e6a830d6SPaolo Bonzini static inline void virtio_stl_phys_cached(VirtIODevice *vdev, 201e6a830d6SPaolo Bonzini MemoryRegionCache *cache, 202e6a830d6SPaolo Bonzini hwaddr pa, uint32_t value) 203e6a830d6SPaolo Bonzini { 204e6a830d6SPaolo Bonzini if (virtio_access_is_big_endian(vdev)) { 205e6a830d6SPaolo Bonzini stl_be_phys_cached(cache, pa, value); 206e6a830d6SPaolo Bonzini } else { 207e6a830d6SPaolo Bonzini stl_le_phys_cached(cache, pa, value); 208e6a830d6SPaolo Bonzini } 209e6a830d6SPaolo Bonzini } 210e6a830d6SPaolo Bonzini 2110f5d1d2aSGreg Kurz static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 2120f5d1d2aSGreg Kurz { 2130f5d1d2aSGreg Kurz *s = virtio_tswap16(vdev, *s); 2140f5d1d2aSGreg Kurz } 2150f5d1d2aSGreg Kurz 2160f5d1d2aSGreg Kurz static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 2170f5d1d2aSGreg Kurz { 218e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 2190f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 2200f5d1d2aSGreg Kurz #else 2210f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 2220f5d1d2aSGreg Kurz #endif 2230f5d1d2aSGreg Kurz } 2240f5d1d2aSGreg Kurz 2250f5d1d2aSGreg Kurz static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 2260f5d1d2aSGreg Kurz { 2270f5d1d2aSGreg Kurz *s = virtio_tswap32(vdev, *s); 2280f5d1d2aSGreg Kurz } 2290f5d1d2aSGreg Kurz 2300f5d1d2aSGreg Kurz static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 2310f5d1d2aSGreg Kurz { 232e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN 2330f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 2340f5d1d2aSGreg Kurz #else 2350f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 2360f5d1d2aSGreg Kurz #endif 2370f5d1d2aSGreg Kurz } 2380f5d1d2aSGreg Kurz 2390f5d1d2aSGreg Kurz static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 2400f5d1d2aSGreg Kurz { 2410f5d1d2aSGreg Kurz *s = virtio_tswap64(vdev, *s); 2420f5d1d2aSGreg Kurz } 2432a6a4076SMarkus Armbruster #endif /* QEMU_VIRTIO_ACCESS_H */ 244