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