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 */ 150f5d1d2aSGreg Kurz #ifndef _QEMU_VIRTIO_ACCESS_H 160f5d1d2aSGreg Kurz #define _QEMU_VIRTIO_ACCESS_H 170f5d1d2aSGreg Kurz #include "hw/virtio/virtio.h" 180f5d1d2aSGreg Kurz #include "exec/address-spaces.h" 190f5d1d2aSGreg Kurz 200f5d1d2aSGreg Kurz static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) 210f5d1d2aSGreg Kurz { 22*95129d6fSCornelia Huck if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { 233c185597SCornelia Huck /* Devices conforming to VIRTIO 1.0 or later are always LE. */ 243c185597SCornelia Huck return false; 253c185597SCornelia Huck } 260f5d1d2aSGreg Kurz #if defined(TARGET_IS_BIENDIAN) 270f5d1d2aSGreg Kurz return virtio_is_big_endian(vdev); 280f5d1d2aSGreg Kurz #elif defined(TARGET_WORDS_BIGENDIAN) 290f5d1d2aSGreg Kurz return true; 300f5d1d2aSGreg Kurz #else 310f5d1d2aSGreg Kurz return false; 320f5d1d2aSGreg Kurz #endif 330f5d1d2aSGreg Kurz } 340f5d1d2aSGreg Kurz 3541d283bdSGreg Kurz static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev) 3641d283bdSGreg Kurz { 3741d283bdSGreg Kurz #ifdef TARGET_IS_BIENDIAN 3841d283bdSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 3941d283bdSGreg Kurz return !virtio_is_big_endian(vdev); 4041d283bdSGreg Kurz #else 4141d283bdSGreg Kurz return virtio_is_big_endian(vdev); 4241d283bdSGreg Kurz #endif 4341d283bdSGreg Kurz #else 4441d283bdSGreg Kurz return false; 4541d283bdSGreg Kurz #endif 4641d283bdSGreg Kurz } 4741d283bdSGreg Kurz 480f5d1d2aSGreg Kurz static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) 490f5d1d2aSGreg Kurz { 500f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 510f5d1d2aSGreg Kurz return lduw_be_phys(&address_space_memory, pa); 520f5d1d2aSGreg Kurz } 530f5d1d2aSGreg Kurz return lduw_le_phys(&address_space_memory, pa); 540f5d1d2aSGreg Kurz } 550f5d1d2aSGreg Kurz 560f5d1d2aSGreg Kurz static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) 570f5d1d2aSGreg Kurz { 580f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 590f5d1d2aSGreg Kurz return ldl_be_phys(&address_space_memory, pa); 600f5d1d2aSGreg Kurz } 610f5d1d2aSGreg Kurz return ldl_le_phys(&address_space_memory, pa); 620f5d1d2aSGreg Kurz } 630f5d1d2aSGreg Kurz 640f5d1d2aSGreg Kurz static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) 650f5d1d2aSGreg Kurz { 660f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 670f5d1d2aSGreg Kurz return ldq_be_phys(&address_space_memory, pa); 680f5d1d2aSGreg Kurz } 690f5d1d2aSGreg Kurz return ldq_le_phys(&address_space_memory, pa); 700f5d1d2aSGreg Kurz } 710f5d1d2aSGreg Kurz 720f5d1d2aSGreg Kurz static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, 730f5d1d2aSGreg Kurz uint16_t value) 740f5d1d2aSGreg Kurz { 750f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 760f5d1d2aSGreg Kurz stw_be_phys(&address_space_memory, pa, value); 770f5d1d2aSGreg Kurz } else { 780f5d1d2aSGreg Kurz stw_le_phys(&address_space_memory, pa, value); 790f5d1d2aSGreg Kurz } 800f5d1d2aSGreg Kurz } 810f5d1d2aSGreg Kurz 820f5d1d2aSGreg Kurz static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, 830f5d1d2aSGreg Kurz uint32_t value) 840f5d1d2aSGreg Kurz { 850f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 860f5d1d2aSGreg Kurz stl_be_phys(&address_space_memory, pa, value); 870f5d1d2aSGreg Kurz } else { 880f5d1d2aSGreg Kurz stl_le_phys(&address_space_memory, pa, value); 890f5d1d2aSGreg Kurz } 900f5d1d2aSGreg Kurz } 910f5d1d2aSGreg Kurz 920f5d1d2aSGreg Kurz static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) 930f5d1d2aSGreg Kurz { 940f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 950f5d1d2aSGreg Kurz stw_be_p(ptr, v); 960f5d1d2aSGreg Kurz } else { 970f5d1d2aSGreg Kurz stw_le_p(ptr, v); 980f5d1d2aSGreg Kurz } 990f5d1d2aSGreg Kurz } 1000f5d1d2aSGreg Kurz 1010f5d1d2aSGreg Kurz static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) 1020f5d1d2aSGreg Kurz { 1030f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1040f5d1d2aSGreg Kurz stl_be_p(ptr, v); 1050f5d1d2aSGreg Kurz } else { 1060f5d1d2aSGreg Kurz stl_le_p(ptr, v); 1070f5d1d2aSGreg Kurz } 1080f5d1d2aSGreg Kurz } 1090f5d1d2aSGreg Kurz 1100f5d1d2aSGreg Kurz static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) 1110f5d1d2aSGreg Kurz { 1120f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1130f5d1d2aSGreg Kurz stq_be_p(ptr, v); 1140f5d1d2aSGreg Kurz } else { 1150f5d1d2aSGreg Kurz stq_le_p(ptr, v); 1160f5d1d2aSGreg Kurz } 1170f5d1d2aSGreg Kurz } 1180f5d1d2aSGreg Kurz 1190f5d1d2aSGreg Kurz static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) 1200f5d1d2aSGreg Kurz { 1210f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1220f5d1d2aSGreg Kurz return lduw_be_p(ptr); 1230f5d1d2aSGreg Kurz } else { 1240f5d1d2aSGreg Kurz return lduw_le_p(ptr); 1250f5d1d2aSGreg Kurz } 1260f5d1d2aSGreg Kurz } 1270f5d1d2aSGreg Kurz 1280f5d1d2aSGreg Kurz static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) 1290f5d1d2aSGreg Kurz { 1300f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1310f5d1d2aSGreg Kurz return ldl_be_p(ptr); 1320f5d1d2aSGreg Kurz } else { 1330f5d1d2aSGreg Kurz return ldl_le_p(ptr); 1340f5d1d2aSGreg Kurz } 1350f5d1d2aSGreg Kurz } 1360f5d1d2aSGreg Kurz 1370f5d1d2aSGreg Kurz static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) 1380f5d1d2aSGreg Kurz { 1390f5d1d2aSGreg Kurz if (virtio_access_is_big_endian(vdev)) { 1400f5d1d2aSGreg Kurz return ldq_be_p(ptr); 1410f5d1d2aSGreg Kurz } else { 1420f5d1d2aSGreg Kurz return ldq_le_p(ptr); 1430f5d1d2aSGreg Kurz } 1440f5d1d2aSGreg Kurz } 1450f5d1d2aSGreg Kurz 146feb93f36SJason Wang static inline bool virtio_needs_swap(VirtIODevice *vdev) 147feb93f36SJason Wang { 148feb93f36SJason Wang #ifdef HOST_WORDS_BIGENDIAN 149feb93f36SJason Wang return virtio_access_is_big_endian(vdev) ? false : true; 150feb93f36SJason Wang #else 151feb93f36SJason Wang return virtio_access_is_big_endian(vdev) ? true : false; 152feb93f36SJason Wang #endif 153feb93f36SJason Wang } 154feb93f36SJason Wang 1550f5d1d2aSGreg Kurz static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) 1560f5d1d2aSGreg Kurz { 1570f5d1d2aSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 1580f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? s : bswap16(s); 1590f5d1d2aSGreg Kurz #else 1600f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; 1610f5d1d2aSGreg Kurz #endif 1620f5d1d2aSGreg Kurz } 1630f5d1d2aSGreg Kurz 1640f5d1d2aSGreg Kurz static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) 1650f5d1d2aSGreg Kurz { 1660f5d1d2aSGreg Kurz *s = virtio_tswap16(vdev, *s); 1670f5d1d2aSGreg Kurz } 1680f5d1d2aSGreg Kurz 1690f5d1d2aSGreg Kurz static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) 1700f5d1d2aSGreg Kurz { 1710f5d1d2aSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 1720f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? s : bswap32(s); 1730f5d1d2aSGreg Kurz #else 1740f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; 1750f5d1d2aSGreg Kurz #endif 1760f5d1d2aSGreg Kurz } 1770f5d1d2aSGreg Kurz 1780f5d1d2aSGreg Kurz static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) 1790f5d1d2aSGreg Kurz { 1800f5d1d2aSGreg Kurz *s = virtio_tswap32(vdev, *s); 1810f5d1d2aSGreg Kurz } 1820f5d1d2aSGreg Kurz 1830f5d1d2aSGreg Kurz static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) 1840f5d1d2aSGreg Kurz { 1850f5d1d2aSGreg Kurz #ifdef HOST_WORDS_BIGENDIAN 1860f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? s : bswap64(s); 1870f5d1d2aSGreg Kurz #else 1880f5d1d2aSGreg Kurz return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; 1890f5d1d2aSGreg Kurz #endif 1900f5d1d2aSGreg Kurz } 1910f5d1d2aSGreg Kurz 1920f5d1d2aSGreg Kurz static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) 1930f5d1d2aSGreg Kurz { 1940f5d1d2aSGreg Kurz *s = virtio_tswap64(vdev, *s); 1950f5d1d2aSGreg Kurz } 1960f5d1d2aSGreg Kurz #endif /* _QEMU_VIRTIO_ACCESS_H */ 197