1 /*
2 * Copyright (c) 2020 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_
9
10 /**
11 * @brief Inter-VM Shared Memory (ivshmem) reference API
12 * @defgroup ivshmem Inter-VM Shared Memory (ivshmem) reference API
13 * @ingroup io_interfaces
14 * @{
15 */
16
17 #include <zephyr/types.h>
18 #include <stddef.h>
19 #include <zephyr/device.h>
20 #include <zephyr/kernel.h>
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 #define IVSHMEM_V2_PROTO_UNDEFINED 0x0000
27 #define IVSHMEM_V2_PROTO_NET 0x0001
28
29 typedef size_t (*ivshmem_get_mem_f)(const struct device *dev,
30 uintptr_t *memmap);
31
32 typedef uint32_t (*ivshmem_get_id_f)(const struct device *dev);
33
34 typedef uint16_t (*ivshmem_get_vectors_f)(const struct device *dev);
35
36 typedef int (*ivshmem_int_peer_f)(const struct device *dev,
37 uint32_t peer_id, uint16_t vector);
38
39 typedef int (*ivshmem_register_handler_f)(const struct device *dev,
40 struct k_poll_signal *signal,
41 uint16_t vector);
42
43 #ifdef CONFIG_IVSHMEM_V2
44
45 typedef size_t (*ivshmem_get_rw_mem_section_f)(const struct device *dev,
46 uintptr_t *memmap);
47
48 typedef size_t (*ivshmem_get_output_mem_section_f)(const struct device *dev,
49 uint32_t peer_id,
50 uintptr_t *memmap);
51
52 typedef uint32_t (*ivshmem_get_state_f)(const struct device *dev,
53 uint32_t peer_id);
54
55 typedef int (*ivshmem_set_state_f)(const struct device *dev,
56 uint32_t state);
57
58 typedef uint32_t (*ivshmem_get_max_peers_f)(const struct device *dev);
59
60 typedef uint16_t (*ivshmem_get_protocol_f)(const struct device *dev);
61
62 typedef int (*ivshmem_enable_interrupts_f)(const struct device *dev,
63 bool enable);
64
65 #endif /* CONFIG_IVSHMEM_V2 */
66
67 __subsystem struct ivshmem_driver_api {
68 ivshmem_get_mem_f get_mem;
69 ivshmem_get_id_f get_id;
70 ivshmem_get_vectors_f get_vectors;
71 ivshmem_int_peer_f int_peer;
72 ivshmem_register_handler_f register_handler;
73 #ifdef CONFIG_IVSHMEM_V2
74 ivshmem_get_rw_mem_section_f get_rw_mem_section;
75 ivshmem_get_output_mem_section_f get_output_mem_section;
76 ivshmem_get_state_f get_state;
77 ivshmem_set_state_f set_state;
78 ivshmem_get_max_peers_f get_max_peers;
79 ivshmem_get_protocol_f get_protocol;
80 ivshmem_enable_interrupts_f enable_interrupts;
81 #endif
82 };
83
84 /**
85 * @brief Get the inter-VM shared memory
86 *
87 * @param dev Pointer to the device structure for the driver instance
88 * @param memmap A pointer to fill in with the memory address
89 *
90 * @return the size of the memory mapped, or 0
91 */
92 __syscall size_t ivshmem_get_mem(const struct device *dev,
93 uintptr_t *memmap);
94
z_impl_ivshmem_get_mem(const struct device * dev,uintptr_t * memmap)95 static inline size_t z_impl_ivshmem_get_mem(const struct device *dev,
96 uintptr_t *memmap)
97 {
98 const struct ivshmem_driver_api *api =
99 (const struct ivshmem_driver_api *)dev->api;
100
101 return api->get_mem(dev, memmap);
102 }
103
104 /**
105 * @brief Get our VM ID
106 *
107 * @param dev Pointer to the device structure for the driver instance
108 *
109 * @return our VM ID or 0 if we are not running on doorbell version
110 */
111 __syscall uint32_t ivshmem_get_id(const struct device *dev);
112
z_impl_ivshmem_get_id(const struct device * dev)113 static inline uint32_t z_impl_ivshmem_get_id(const struct device *dev)
114 {
115 const struct ivshmem_driver_api *api =
116 (const struct ivshmem_driver_api *)dev->api;
117
118 return api->get_id(dev);
119 }
120
121 /**
122 * @brief Get the number of interrupt vectors we can use
123 *
124 * @param dev Pointer to the device structure for the driver instance
125 *
126 * @return the number of available interrupt vectors
127 */
128 __syscall uint16_t ivshmem_get_vectors(const struct device *dev);
129
z_impl_ivshmem_get_vectors(const struct device * dev)130 static inline uint16_t z_impl_ivshmem_get_vectors(const struct device *dev)
131 {
132 const struct ivshmem_driver_api *api =
133 (const struct ivshmem_driver_api *)dev->api;
134
135 return api->get_vectors(dev);
136 }
137
138 /**
139 * @brief Interrupt another VM
140 *
141 * @param dev Pointer to the device structure for the driver instance
142 * @param peer_id The VM ID to interrupt
143 * @param vector The interrupt vector to use
144 *
145 * @return 0 on success, a negative errno otherwise
146 */
147 __syscall int ivshmem_int_peer(const struct device *dev,
148 uint32_t peer_id, uint16_t vector);
149
z_impl_ivshmem_int_peer(const struct device * dev,uint32_t peer_id,uint16_t vector)150 static inline int z_impl_ivshmem_int_peer(const struct device *dev,
151 uint32_t peer_id, uint16_t vector)
152 {
153 const struct ivshmem_driver_api *api =
154 (const struct ivshmem_driver_api *)dev->api;
155
156 return api->int_peer(dev, peer_id, vector);
157 }
158
159 /**
160 * @brief Register a vector notification (interrupt) handler
161 *
162 * @param dev Pointer to the device structure for the driver instance
163 * @param signal A pointer to a valid and ready to be signaled
164 * struct k_poll_signal. Or NULL to unregister any handler
165 * registered for the given vector.
166 * @param vector The interrupt vector to get notification from
167 *
168 * Note: The returned status, if positive, to a raised signal is the vector
169 * that generated the signal. This lets the possibility to the user
170 * to have one signal for all vectors, or one per-vector.
171 *
172 * @return 0 on success, a negative errno otherwise
173 */
174 __syscall int ivshmem_register_handler(const struct device *dev,
175 struct k_poll_signal *signal,
176 uint16_t vector);
177
z_impl_ivshmem_register_handler(const struct device * dev,struct k_poll_signal * signal,uint16_t vector)178 static inline int z_impl_ivshmem_register_handler(const struct device *dev,
179 struct k_poll_signal *signal,
180 uint16_t vector)
181 {
182 const struct ivshmem_driver_api *api =
183 (const struct ivshmem_driver_api *)dev->api;
184
185 return api->register_handler(dev, signal, vector);
186 }
187
188 #ifdef CONFIG_IVSHMEM_V2
189
190 /**
191 * @brief Get the ivshmem read/write section (ivshmem-v2 only)
192 *
193 * @param dev Pointer to the device structure for the driver instance
194 * @param memmap A pointer to fill in with the memory address
195 *
196 * @return the size of the memory mapped, or 0
197 */
198 __syscall size_t ivshmem_get_rw_mem_section(const struct device *dev,
199 uintptr_t *memmap);
200
z_impl_ivshmem_get_rw_mem_section(const struct device * dev,uintptr_t * memmap)201 static inline size_t z_impl_ivshmem_get_rw_mem_section(const struct device *dev,
202 uintptr_t *memmap)
203 {
204 const struct ivshmem_driver_api *api =
205 (const struct ivshmem_driver_api *)dev->api;
206
207 return api->get_rw_mem_section(dev, memmap);
208 }
209
210 /**
211 * @brief Get the ivshmem output section for a peer (ivshmem-v2 only)
212 *
213 * @param dev Pointer to the device structure for the driver instance
214 * @param peer_id The VM ID whose output memory section to get
215 * @param memmap A pointer to fill in with the memory address
216 *
217 * @return the size of the memory mapped, or 0
218 */
219 __syscall size_t ivshmem_get_output_mem_section(const struct device *dev,
220 uint32_t peer_id,
221 uintptr_t *memmap);
222
z_impl_ivshmem_get_output_mem_section(const struct device * dev,uint32_t peer_id,uintptr_t * memmap)223 static inline size_t z_impl_ivshmem_get_output_mem_section(const struct device *dev,
224 uint32_t peer_id,
225 uintptr_t *memmap)
226 {
227 const struct ivshmem_driver_api *api =
228 (const struct ivshmem_driver_api *)dev->api;
229
230 return api->get_output_mem_section(dev, peer_id, memmap);
231 }
232
233 /**
234 * @brief Get the state value of a peer (ivshmem-v2 only)
235 *
236 * @param dev Pointer to the device structure for the driver instance
237 * @param peer_id The VM ID whose state to get
238 *
239 * @return the state value of the peer
240 */
241 __syscall uint32_t ivshmem_get_state(const struct device *dev,
242 uint32_t peer_id);
243
z_impl_ivshmem_get_state(const struct device * dev,uint32_t peer_id)244 static inline uint32_t z_impl_ivshmem_get_state(const struct device *dev,
245 uint32_t peer_id)
246 {
247 const struct ivshmem_driver_api *api =
248 (const struct ivshmem_driver_api *)dev->api;
249
250 return api->get_state(dev, peer_id);
251 }
252
253 /**
254 * @brief Set our state (ivshmem-v2 only)
255 *
256 * @param dev Pointer to the device structure for the driver instance
257 * @param state The state value to set
258 *
259 * @return 0 on success, a negative errno otherwise
260 */
261 __syscall int ivshmem_set_state(const struct device *dev,
262 uint32_t state);
263
z_impl_ivshmem_set_state(const struct device * dev,uint32_t state)264 static inline int z_impl_ivshmem_set_state(const struct device *dev,
265 uint32_t state)
266 {
267 const struct ivshmem_driver_api *api =
268 (const struct ivshmem_driver_api *)dev->api;
269
270 return api->set_state(dev, state);
271 }
272
273 /**
274 * @brief Get the maximum number of peers supported (ivshmem-v2 only)
275 *
276 * @param dev Pointer to the device structure for the driver instance
277 *
278 * @return the maximum number of peers supported, or 0
279 */
280 __syscall uint32_t ivshmem_get_max_peers(const struct device *dev);
281
z_impl_ivshmem_get_max_peers(const struct device * dev)282 static inline uint32_t z_impl_ivshmem_get_max_peers(const struct device *dev)
283 {
284 const struct ivshmem_driver_api *api =
285 (const struct ivshmem_driver_api *)dev->api;
286
287 return api->get_max_peers(dev);
288 }
289
290 /**
291 * @brief Get the protocol used by this ivshmem instance (ivshmem-v2 only)
292 *
293 * @param dev Pointer to the device structure for the driver instance
294 *
295 * @return the protocol
296 */
297 __syscall uint16_t ivshmem_get_protocol(const struct device *dev);
298
z_impl_ivshmem_get_protocol(const struct device * dev)299 static inline uint16_t z_impl_ivshmem_get_protocol(const struct device *dev)
300 {
301 const struct ivshmem_driver_api *api =
302 (const struct ivshmem_driver_api *)dev->api;
303
304 return api->get_protocol(dev);
305 }
306
307 /**
308 * @brief Set the interrupt enablement for our VM (ivshmem-v2 only)
309 *
310 * @param dev Pointer to the device structure for the driver instance
311 * @param enable True to enable interrupts, false to disable
312 *
313 * @return 0 on success, a negative errno otherwise
314 */
315 __syscall int ivshmem_enable_interrupts(const struct device *dev,
316 bool enable);
317
z_impl_ivshmem_enable_interrupts(const struct device * dev,bool enable)318 static inline int z_impl_ivshmem_enable_interrupts(const struct device *dev,
319 bool enable)
320 {
321 const struct ivshmem_driver_api *api =
322 (const struct ivshmem_driver_api *)dev->api;
323
324 return api->enable_interrupts(dev, enable);
325 }
326
327 #endif /* CONFIG_IVSHMEM_V2 */
328
329 #ifdef __cplusplus
330 }
331 #endif
332
333 /**
334 * @}
335 */
336
337 #include <syscalls/ivshmem.h>
338
339 #endif /* ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_ */
340