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 * Note: This API is not supported for ivshmem-v2, as
88 * the R/W and R/O areas may not be mapped contiguously.
89 * For ivshmem-v2, use the ivshmem_get_rw_mem_section,
90 * ivshmem_get_output_mem_section and ivshmem_get_state
91 * APIs to access the shared memory.
92 *
93 * @param dev Pointer to the device structure for the driver instance
94 * @param memmap A pointer to fill in with the memory address
95 *
96 * @return the size of the memory mapped, or 0
97 */
98 __syscall size_t ivshmem_get_mem(const struct device *dev,
99 uintptr_t *memmap);
100
z_impl_ivshmem_get_mem(const struct device * dev,uintptr_t * memmap)101 static inline size_t z_impl_ivshmem_get_mem(const struct device *dev,
102 uintptr_t *memmap)
103 {
104 const struct ivshmem_driver_api *api =
105 (const struct ivshmem_driver_api *)dev->api;
106
107 return api->get_mem(dev, memmap);
108 }
109
110 /**
111 * @brief Get our VM ID
112 *
113 * @param dev Pointer to the device structure for the driver instance
114 *
115 * @return our VM ID or 0 if we are not running on doorbell version
116 */
117 __syscall uint32_t ivshmem_get_id(const struct device *dev);
118
z_impl_ivshmem_get_id(const struct device * dev)119 static inline uint32_t z_impl_ivshmem_get_id(const struct device *dev)
120 {
121 const struct ivshmem_driver_api *api =
122 (const struct ivshmem_driver_api *)dev->api;
123
124 return api->get_id(dev);
125 }
126
127 /**
128 * @brief Get the number of interrupt vectors we can use
129 *
130 * @param dev Pointer to the device structure for the driver instance
131 *
132 * @return the number of available interrupt vectors
133 */
134 __syscall uint16_t ivshmem_get_vectors(const struct device *dev);
135
z_impl_ivshmem_get_vectors(const struct device * dev)136 static inline uint16_t z_impl_ivshmem_get_vectors(const struct device *dev)
137 {
138 const struct ivshmem_driver_api *api =
139 (const struct ivshmem_driver_api *)dev->api;
140
141 return api->get_vectors(dev);
142 }
143
144 /**
145 * @brief Interrupt another VM
146 *
147 * @param dev Pointer to the device structure for the driver instance
148 * @param peer_id The VM ID to interrupt
149 * @param vector The interrupt vector to use
150 *
151 * @return 0 on success, a negative errno otherwise
152 */
153 __syscall int ivshmem_int_peer(const struct device *dev,
154 uint32_t peer_id, uint16_t vector);
155
z_impl_ivshmem_int_peer(const struct device * dev,uint32_t peer_id,uint16_t vector)156 static inline int z_impl_ivshmem_int_peer(const struct device *dev,
157 uint32_t peer_id, uint16_t vector)
158 {
159 const struct ivshmem_driver_api *api =
160 (const struct ivshmem_driver_api *)dev->api;
161
162 return api->int_peer(dev, peer_id, vector);
163 }
164
165 /**
166 * @brief Register a vector notification (interrupt) handler
167 *
168 * @param dev Pointer to the device structure for the driver instance
169 * @param signal A pointer to a valid and ready to be signaled
170 * struct k_poll_signal. Or NULL to unregister any handler
171 * registered for the given vector.
172 * @param vector The interrupt vector to get notification from
173 *
174 * Note: The returned status, if positive, to a raised signal is the vector
175 * that generated the signal. This lets the possibility to the user
176 * to have one signal for all vectors, or one per-vector.
177 *
178 * @return 0 on success, a negative errno otherwise
179 */
180 __syscall int ivshmem_register_handler(const struct device *dev,
181 struct k_poll_signal *signal,
182 uint16_t vector);
183
z_impl_ivshmem_register_handler(const struct device * dev,struct k_poll_signal * signal,uint16_t vector)184 static inline int z_impl_ivshmem_register_handler(const struct device *dev,
185 struct k_poll_signal *signal,
186 uint16_t vector)
187 {
188 const struct ivshmem_driver_api *api =
189 (const struct ivshmem_driver_api *)dev->api;
190
191 return api->register_handler(dev, signal, vector);
192 }
193
194 #ifdef CONFIG_IVSHMEM_V2
195
196 /**
197 * @brief Get the ivshmem read/write section (ivshmem-v2 only)
198 *
199 * @param dev Pointer to the device structure for the driver instance
200 * @param memmap A pointer to fill in with the memory address
201 *
202 * @return the size of the memory mapped, or 0
203 */
204 __syscall size_t ivshmem_get_rw_mem_section(const struct device *dev,
205 uintptr_t *memmap);
206
z_impl_ivshmem_get_rw_mem_section(const struct device * dev,uintptr_t * memmap)207 static inline size_t z_impl_ivshmem_get_rw_mem_section(const struct device *dev,
208 uintptr_t *memmap)
209 {
210 const struct ivshmem_driver_api *api =
211 (const struct ivshmem_driver_api *)dev->api;
212
213 return api->get_rw_mem_section(dev, memmap);
214 }
215
216 /**
217 * @brief Get the ivshmem output section for a peer (ivshmem-v2 only)
218 *
219 * @param dev Pointer to the device structure for the driver instance
220 * @param peer_id The VM ID whose output memory section to get
221 * @param memmap A pointer to fill in with the memory address
222 *
223 * @return the size of the memory mapped, or 0
224 */
225 __syscall size_t ivshmem_get_output_mem_section(const struct device *dev,
226 uint32_t peer_id,
227 uintptr_t *memmap);
228
z_impl_ivshmem_get_output_mem_section(const struct device * dev,uint32_t peer_id,uintptr_t * memmap)229 static inline size_t z_impl_ivshmem_get_output_mem_section(const struct device *dev,
230 uint32_t peer_id,
231 uintptr_t *memmap)
232 {
233 const struct ivshmem_driver_api *api =
234 (const struct ivshmem_driver_api *)dev->api;
235
236 return api->get_output_mem_section(dev, peer_id, memmap);
237 }
238
239 /**
240 * @brief Get the state value of a peer (ivshmem-v2 only)
241 *
242 * @param dev Pointer to the device structure for the driver instance
243 * @param peer_id The VM ID whose state to get
244 *
245 * @return the state value of the peer
246 */
247 __syscall uint32_t ivshmem_get_state(const struct device *dev,
248 uint32_t peer_id);
249
z_impl_ivshmem_get_state(const struct device * dev,uint32_t peer_id)250 static inline uint32_t z_impl_ivshmem_get_state(const struct device *dev,
251 uint32_t peer_id)
252 {
253 const struct ivshmem_driver_api *api =
254 (const struct ivshmem_driver_api *)dev->api;
255
256 return api->get_state(dev, peer_id);
257 }
258
259 /**
260 * @brief Set our state (ivshmem-v2 only)
261 *
262 * @param dev Pointer to the device structure for the driver instance
263 * @param state The state value to set
264 *
265 * @return 0 on success, a negative errno otherwise
266 */
267 __syscall int ivshmem_set_state(const struct device *dev,
268 uint32_t state);
269
z_impl_ivshmem_set_state(const struct device * dev,uint32_t state)270 static inline int z_impl_ivshmem_set_state(const struct device *dev,
271 uint32_t state)
272 {
273 const struct ivshmem_driver_api *api =
274 (const struct ivshmem_driver_api *)dev->api;
275
276 return api->set_state(dev, state);
277 }
278
279 /**
280 * @brief Get the maximum number of peers supported (ivshmem-v2 only)
281 *
282 * @param dev Pointer to the device structure for the driver instance
283 *
284 * @return the maximum number of peers supported, or 0
285 */
286 __syscall uint32_t ivshmem_get_max_peers(const struct device *dev);
287
z_impl_ivshmem_get_max_peers(const struct device * dev)288 static inline uint32_t z_impl_ivshmem_get_max_peers(const struct device *dev)
289 {
290 const struct ivshmem_driver_api *api =
291 (const struct ivshmem_driver_api *)dev->api;
292
293 return api->get_max_peers(dev);
294 }
295
296 /**
297 * @brief Get the protocol used by this ivshmem instance (ivshmem-v2 only)
298 *
299 * @param dev Pointer to the device structure for the driver instance
300 *
301 * @return the protocol
302 */
303 __syscall uint16_t ivshmem_get_protocol(const struct device *dev);
304
z_impl_ivshmem_get_protocol(const struct device * dev)305 static inline uint16_t z_impl_ivshmem_get_protocol(const struct device *dev)
306 {
307 const struct ivshmem_driver_api *api =
308 (const struct ivshmem_driver_api *)dev->api;
309
310 return api->get_protocol(dev);
311 }
312
313 /**
314 * @brief Set the interrupt enablement for our VM (ivshmem-v2 only)
315 *
316 * @param dev Pointer to the device structure for the driver instance
317 * @param enable True to enable interrupts, false to disable
318 *
319 * @return 0 on success, a negative errno otherwise
320 */
321 __syscall int ivshmem_enable_interrupts(const struct device *dev,
322 bool enable);
323
z_impl_ivshmem_enable_interrupts(const struct device * dev,bool enable)324 static inline int z_impl_ivshmem_enable_interrupts(const struct device *dev,
325 bool enable)
326 {
327 const struct ivshmem_driver_api *api =
328 (const struct ivshmem_driver_api *)dev->api;
329
330 return api->enable_interrupts(dev, enable);
331 }
332
333 #endif /* CONFIG_IVSHMEM_V2 */
334
335 #ifdef __cplusplus
336 }
337 #endif
338
339 /**
340 * @}
341 */
342
343 #include <zephyr/syscalls/ivshmem.h>
344
345 #endif /* ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_ */
346