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 ivshmem reference API
12  * @defgroup ivshmem ivshmem reference API
13  * @{
14  */
15 
16 #include <zephyr/types.h>
17 #include <stddef.h>
18 #include <device.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 typedef size_t (*ivshmem_get_mem_f)(const struct device *dev,
25 				    uintptr_t *memmap);
26 
27 typedef uint32_t (*ivshmem_get_id_f)(const struct device *dev);
28 
29 typedef uint16_t (*ivshmem_get_vectors_f)(const struct device *dev);
30 
31 typedef int (*ivshmem_int_peer_f)(const struct device *dev,
32 				  uint32_t peer_id, uint16_t vector);
33 
34 typedef int (*ivshmem_register_handler_f)(const struct device *dev,
35 					  struct k_poll_signal *signal,
36 					  uint16_t vector);
37 
38 __subsystem struct ivshmem_driver_api {
39 	ivshmem_get_mem_f get_mem;
40 	ivshmem_get_id_f get_id;
41 	ivshmem_get_vectors_f get_vectors;
42 	ivshmem_int_peer_f int_peer;
43 	ivshmem_register_handler_f register_handler;
44 };
45 
46 /**
47  * @brief Get the inter-VM shared memory
48  *
49  * @param dev Pointer to the device structure for the driver instance
50  * @param memmap A pointer to fill in with the  memory address
51  *
52  * @return the size of the memory mapped, or 0
53  */
54 __syscall size_t ivshmem_get_mem(const struct device *dev,
55 				 uintptr_t *memmap);
56 
z_impl_ivshmem_get_mem(const struct device * dev,uintptr_t * memmap)57 static inline size_t z_impl_ivshmem_get_mem(const struct device *dev,
58 					    uintptr_t *memmap)
59 {
60 	const struct ivshmem_driver_api *api =
61 		(const struct ivshmem_driver_api *)dev->api;
62 
63 	return api->get_mem(dev, memmap);
64 }
65 
66 /**
67  * @brief Get our VM ID
68  *
69  * @param dev Pointer to the device structure for the driver instance
70  *
71  * @return our VM ID or 0 if we are not running on doorbell version
72  */
73 __syscall uint32_t ivshmem_get_id(const struct device *dev);
74 
z_impl_ivshmem_get_id(const struct device * dev)75 static inline uint32_t z_impl_ivshmem_get_id(const struct device *dev)
76 {
77 	const struct ivshmem_driver_api *api =
78 		(const struct ivshmem_driver_api *)dev->api;
79 
80 	return api->get_id(dev);
81 }
82 
83 /**
84  * @brief Get the number of interrupt vectors we can use
85  *
86  * @param dev Pointer to the device structure for the driver instance
87  *
88  * @return the number of available interrupt vectors
89  */
90 __syscall uint16_t ivshmem_get_vectors(const struct device *dev);
91 
z_impl_ivshmem_get_vectors(const struct device * dev)92 static inline uint16_t z_impl_ivshmem_get_vectors(const struct device *dev)
93 {
94 	const struct ivshmem_driver_api *api =
95 		(const struct ivshmem_driver_api *)dev->api;
96 
97 	return api->get_vectors(dev);
98 }
99 
100 /**
101  * @brief Interrupt another VM
102  *
103  * @param dev Pointer to the device structure for the driver instance
104  * @param peer_id The VM ID to interrupt
105  * @param vector The interrupt vector to use
106  *
107  * @return 0 on success, a negative errno otherwise
108  */
109 __syscall int ivshmem_int_peer(const struct device *dev,
110 			       uint32_t peer_id, uint16_t vector);
111 
z_impl_ivshmem_int_peer(const struct device * dev,uint32_t peer_id,uint16_t vector)112 static inline int z_impl_ivshmem_int_peer(const struct device *dev,
113 					  uint32_t peer_id, uint16_t vector)
114 {
115 	const struct ivshmem_driver_api *api =
116 		(const struct ivshmem_driver_api *)dev->api;
117 
118 	return api->int_peer(dev, peer_id, vector);
119 }
120 
121 /**
122  * @brief Register a vector notification (interrupt) handler
123  *
124  * @param dev Pointer to the device structure for the driver instance
125  * @param signal A pointer to a valid and ready to be signaled
126  *        struct k_poll_signal. Or NULL to unregister any handler
127  *        registered for the given vector.
128  * @param vector The interrupt vector to get notification from
129  *
130  * Note: The returned status, if positive, to a raised signal is the vector
131  *       that generated the signal. This lets the possibility to the user
132  *       to have one signal for all vectors, or one per-vector.
133  *
134  * @return 0 on success, a negative errno otherwise
135  */
136 __syscall int ivshmem_register_handler(const struct device *dev,
137 				       struct k_poll_signal *signal,
138 				       uint16_t vector);
139 
z_impl_ivshmem_register_handler(const struct device * dev,struct k_poll_signal * signal,uint16_t vector)140 static inline int z_impl_ivshmem_register_handler(const struct device *dev,
141 						  struct k_poll_signal *signal,
142 						  uint16_t vector)
143 {
144 	const struct ivshmem_driver_api *api =
145 		(const struct ivshmem_driver_api *)dev->api;
146 
147 	return api->register_handler(dev, signal, vector);
148 }
149 
150 #ifdef __cplusplus
151 }
152 #endif
153 
154 /**
155  * @}
156  */
157 
158 #include <syscalls/ivshmem.h>
159 
160 #endif /* ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_ */
161