xref: /qemu/include/hw/virtio/virtio-access.h (revision 95129d6fc9ead97155627a4ca0cfd37282883658)
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