xref: /openbmc/qemu/include/hw/virtio/virtio-access.h (revision b917da4c)
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 #ifndef _QEMU_VIRTIO_ACCESS_H
16 #define _QEMU_VIRTIO_ACCESS_H
17 #include "hw/virtio/virtio.h"
18 #include "exec/address-spaces.h"
19 
20 static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
21 {
22 #if defined(TARGET_IS_BIENDIAN)
23     return virtio_is_big_endian(vdev);
24 #elif defined(TARGET_WORDS_BIGENDIAN)
25     if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
26         /* Devices conforming to VIRTIO 1.0 or later are always LE. */
27         return false;
28     }
29     return true;
30 #else
31     return false;
32 #endif
33 }
34 
35 static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
36 {
37     if (virtio_access_is_big_endian(vdev)) {
38         return lduw_be_phys(&address_space_memory, pa);
39     }
40     return lduw_le_phys(&address_space_memory, pa);
41 }
42 
43 static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
44 {
45     if (virtio_access_is_big_endian(vdev)) {
46         return ldl_be_phys(&address_space_memory, pa);
47     }
48     return ldl_le_phys(&address_space_memory, pa);
49 }
50 
51 static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
52 {
53     if (virtio_access_is_big_endian(vdev)) {
54         return ldq_be_phys(&address_space_memory, pa);
55     }
56     return ldq_le_phys(&address_space_memory, pa);
57 }
58 
59 static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
60                                    uint16_t value)
61 {
62     if (virtio_access_is_big_endian(vdev)) {
63         stw_be_phys(&address_space_memory, pa, value);
64     } else {
65         stw_le_phys(&address_space_memory, pa, value);
66     }
67 }
68 
69 static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
70                                    uint32_t value)
71 {
72     if (virtio_access_is_big_endian(vdev)) {
73         stl_be_phys(&address_space_memory, pa, value);
74     } else {
75         stl_le_phys(&address_space_memory, pa, value);
76     }
77 }
78 
79 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
80 {
81     if (virtio_access_is_big_endian(vdev)) {
82         stw_be_p(ptr, v);
83     } else {
84         stw_le_p(ptr, v);
85     }
86 }
87 
88 static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
89 {
90     if (virtio_access_is_big_endian(vdev)) {
91         stl_be_p(ptr, v);
92     } else {
93         stl_le_p(ptr, v);
94     }
95 }
96 
97 static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
98 {
99     if (virtio_access_is_big_endian(vdev)) {
100         stq_be_p(ptr, v);
101     } else {
102         stq_le_p(ptr, v);
103     }
104 }
105 
106 static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
107 {
108     if (virtio_access_is_big_endian(vdev)) {
109         return lduw_be_p(ptr);
110     } else {
111         return lduw_le_p(ptr);
112     }
113 }
114 
115 static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
116 {
117     if (virtio_access_is_big_endian(vdev)) {
118         return ldl_be_p(ptr);
119     } else {
120         return ldl_le_p(ptr);
121     }
122 }
123 
124 static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
125 {
126     if (virtio_access_is_big_endian(vdev)) {
127         return ldq_be_p(ptr);
128     } else {
129         return ldq_le_p(ptr);
130     }
131 }
132 
133 static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
134 {
135 #ifdef HOST_WORDS_BIGENDIAN
136     return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
137 #else
138     return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
139 #endif
140 }
141 
142 static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
143 {
144     *s = virtio_tswap16(vdev, *s);
145 }
146 
147 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
148 {
149 #ifdef HOST_WORDS_BIGENDIAN
150     return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
151 #else
152     return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
153 #endif
154 }
155 
156 static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
157 {
158     *s = virtio_tswap32(vdev, *s);
159 }
160 
161 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
162 {
163 #ifdef HOST_WORDS_BIGENDIAN
164     return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
165 #else
166     return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
167 #endif
168 }
169 
170 static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s)
171 {
172     *s = virtio_tswap64(vdev, *s);
173 }
174 #endif /* _QEMU_VIRTIO_ACCESS_H */
175