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 "exec/hwaddr.h" |
20 | #include "hw/virtio/virtio.h" |
21 | #include "hw/virtio/virtio-bus.h" |
22 | |
23 | #if defined(TARGET_PPC64) || defined(TARGET_ARM) |
24 | #define LEGACY_VIRTIO_IS_BIENDIAN 1 |
25 | #endif |
26 | |
27 | static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) |
28 | { |
29 | #if defined(LEGACY_VIRTIO_IS_BIENDIAN) |
30 | return virtio_is_big_endian(vdev); |
31 | #elif defined(TARGET_WORDS_BIGENDIAN) |
32 | if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { |
33 | /* Devices conforming to VIRTIO 1.0 or later are always LE. */ |
34 | return false; |
35 | } |
36 | return true; |
37 | #else |
38 | return false; |
39 | #endif |
40 | } |
41 | |
42 | static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) |
43 | { |
44 | AddressSpace *dma_as = vdev->dma_as; |
45 | |
46 | if (virtio_access_is_big_endian(vdev)) { |
47 | return lduw_be_phys(dma_as, pa); |
48 | } |
49 | return lduw_le_phys(dma_as, pa); |
50 | } |
51 | |
52 | static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) |
53 | { |
54 | AddressSpace *dma_as = vdev->dma_as; |
55 | |
56 | if (virtio_access_is_big_endian(vdev)) { |
57 | return ldl_be_phys(dma_as, pa); |
58 | } |
59 | return ldl_le_phys(dma_as, pa); |
60 | } |
61 | |
62 | static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) |
63 | { |
64 | AddressSpace *dma_as = vdev->dma_as; |
65 | |
66 | if (virtio_access_is_big_endian(vdev)) { |
67 | return ldq_be_phys(dma_as, pa); |
68 | } |
69 | return ldq_le_phys(dma_as, pa); |
70 | } |
71 | |
72 | static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, |
73 | uint16_t value) |
74 | { |
75 | AddressSpace *dma_as = vdev->dma_as; |
76 | |
77 | if (virtio_access_is_big_endian(vdev)) { |
78 | stw_be_phys(dma_as, pa, value); |
79 | } else { |
80 | stw_le_phys(dma_as, pa, value); |
81 | } |
82 | } |
83 | |
84 | static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, |
85 | uint32_t value) |
86 | { |
87 | AddressSpace *dma_as = vdev->dma_as; |
88 | |
89 | if (virtio_access_is_big_endian(vdev)) { |
90 | stl_be_phys(dma_as, pa, value); |
91 | } else { |
92 | stl_le_phys(dma_as, pa, value); |
93 | } |
94 | } |
95 | |
96 | static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) |
97 | { |
98 | if (virtio_access_is_big_endian(vdev)) { |
99 | stw_be_p(ptr, v); |
100 | } else { |
101 | stw_le_p(ptr, v); |
102 | } |
103 | } |
104 | |
105 | static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) |
106 | { |
107 | if (virtio_access_is_big_endian(vdev)) { |
108 | stl_be_p(ptr, v); |
109 | } else { |
110 | stl_le_p(ptr, v); |
111 | } |
112 | } |
113 | |
114 | static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) |
115 | { |
116 | if (virtio_access_is_big_endian(vdev)) { |
117 | stq_be_p(ptr, v); |
118 | } else { |
119 | stq_le_p(ptr, v); |
120 | } |
121 | } |
122 | |
123 | static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) |
124 | { |
125 | if (virtio_access_is_big_endian(vdev)) { |
126 | return lduw_be_p(ptr); |
127 | } else { |
128 | return lduw_le_p(ptr); |
129 | } |
130 | } |
131 | |
132 | static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) |
133 | { |
134 | if (virtio_access_is_big_endian(vdev)) { |
135 | return ldl_be_p(ptr); |
136 | } else { |
137 | return ldl_le_p(ptr); |
138 | } |
139 | } |
140 | |
141 | static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) |
142 | { |
143 | if (virtio_access_is_big_endian(vdev)) { |
144 | return ldq_be_p(ptr); |
145 | } else { |
146 | return ldq_le_p(ptr); |
147 | } |
148 | } |
149 | |
150 | static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) |
151 | { |
152 | #ifdef HOST_WORDS_BIGENDIAN |
153 | return virtio_access_is_big_endian(vdev) ? s : bswap16(s); |
154 | #else |
155 | return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; |
156 | #endif |
157 | } |
158 | |
159 | static inline uint16_t virtio_lduw_phys_cached(VirtIODevice *vdev, |
160 | MemoryRegionCache *cache, |
161 | hwaddr pa) |
162 | { |
163 | if (virtio_access_is_big_endian(vdev)) { |
164 | return lduw_be_phys_cached(cache, pa); |
165 | } |
166 | return lduw_le_phys_cached(cache, pa); |
167 | } |
168 | |
169 | static inline uint32_t virtio_ldl_phys_cached(VirtIODevice *vdev, |
170 | MemoryRegionCache *cache, |
171 | hwaddr pa) |
172 | { |
173 | if (virtio_access_is_big_endian(vdev)) { |
174 | return ldl_be_phys_cached(cache, pa); |
175 | } |
176 | return ldl_le_phys_cached(cache, pa); |
177 | } |
178 | |
179 | static inline uint64_t virtio_ldq_phys_cached(VirtIODevice *vdev, |
180 | MemoryRegionCache *cache, |
181 | hwaddr pa) |
182 | { |
183 | if (virtio_access_is_big_endian(vdev)) { |
184 | return ldq_be_phys_cached(cache, pa); |
185 | } |
186 | return ldq_le_phys_cached(cache, pa); |
187 | } |
188 | |
189 | static inline void virtio_stw_phys_cached(VirtIODevice *vdev, |
190 | MemoryRegionCache *cache, |
191 | hwaddr pa, uint16_t value) |
192 | { |
193 | if (virtio_access_is_big_endian(vdev)) { |
194 | stw_be_phys_cached(cache, pa, value); |
195 | } else { |
196 | stw_le_phys_cached(cache, pa, value); |
197 | } |
198 | } |
199 | |
200 | static inline void virtio_stl_phys_cached(VirtIODevice *vdev, |
201 | MemoryRegionCache *cache, |
202 | hwaddr pa, uint32_t value) |
203 | { |
204 | if (virtio_access_is_big_endian(vdev)) { |
205 | stl_be_phys_cached(cache, pa, value); |
206 | } else { |
207 | stl_le_phys_cached(cache, pa, value); |
208 | } |
209 | } |
210 | |
211 | static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) |
212 | { |
213 | *s = virtio_tswap16(vdev, *s); |
214 | } |
215 | |
216 | static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) |
217 | { |
218 | #ifdef HOST_WORDS_BIGENDIAN |
219 | return virtio_access_is_big_endian(vdev) ? s : bswap32(s); |
220 | #else |
221 | return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; |
222 | #endif |
223 | } |
224 | |
225 | static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) |
226 | { |
227 | *s = virtio_tswap32(vdev, *s); |
228 | } |
229 | |
230 | static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) |
231 | { |
232 | #ifdef HOST_WORDS_BIGENDIAN |
233 | return virtio_access_is_big_endian(vdev) ? s : bswap64(s); |
234 | #else |
235 | return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; |
236 | #endif |
237 | } |
238 | |
239 | static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) |
240 | { |
241 | *s = virtio_tswap64(vdev, *s); |
242 | } |
243 | #endif /* QEMU_VIRTIO_ACCESS_H */ |
244 | |