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