xref: /linux/drivers/vhost/vhost.h (revision cc5e710759470bc7f3c61d11fd54586f15fdbdf4)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
23a4d5c94SMichael S. Tsirkin #ifndef _VHOST_H
33a4d5c94SMichael S. Tsirkin #define _VHOST_H
43a4d5c94SMichael S. Tsirkin 
53a4d5c94SMichael S. Tsirkin #include <linux/eventfd.h>
63a4d5c94SMichael S. Tsirkin #include <linux/vhost.h>
73a4d5c94SMichael S. Tsirkin #include <linux/mm.h>
83a4d5c94SMichael S. Tsirkin #include <linux/mutex.h>
93a4d5c94SMichael S. Tsirkin #include <linux/poll.h>
103a4d5c94SMichael S. Tsirkin #include <linux/file.h>
113a4d5c94SMichael S. Tsirkin #include <linux/uio.h>
123a4d5c94SMichael S. Tsirkin #include <linux/virtio_config.h>
133a4d5c94SMichael S. Tsirkin #include <linux/virtio_ring.h>
1460063497SArun Sharma #include <linux/atomic.h>
153a4d5c94SMichael S. Tsirkin 
16c23f3445STejun Heo struct vhost_work;
17c23f3445STejun Heo typedef void (*vhost_work_fn_t)(struct vhost_work *work);
18c23f3445STejun Heo 
1904b96e55SJason Wang #define VHOST_WORK_QUEUED 1
20c23f3445STejun Heo struct vhost_work {
2104b96e55SJason Wang 	struct llist_node	  node;
22c23f3445STejun Heo 	vhost_work_fn_t		  fn;
2304b96e55SJason Wang 	unsigned long		  flags;
24c23f3445STejun Heo };
25c23f3445STejun Heo 
263a4d5c94SMichael S. Tsirkin /* Poll a file (eventfd or socket) */
273a4d5c94SMichael S. Tsirkin /* Note: there's nothing vhost specific about this structure. */
283a4d5c94SMichael S. Tsirkin struct vhost_poll {
293a4d5c94SMichael S. Tsirkin 	poll_table                table;
303a4d5c94SMichael S. Tsirkin 	wait_queue_head_t        *wqh;
31ac6424b9SIngo Molnar 	wait_queue_entry_t              wait;
32c23f3445STejun Heo 	struct vhost_work	  work;
3358e3b602SAl Viro 	__poll_t		  mask;
34c23f3445STejun Heo 	struct vhost_dev	 *dev;
353a4d5c94SMichael S. Tsirkin };
363a4d5c94SMichael S. Tsirkin 
37163049aeSStefan Hajnoczi void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn);
38163049aeSStefan Hajnoczi void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work);
39526d3e7fSJason Wang bool vhost_has_work(struct vhost_dev *dev);
40163049aeSStefan Hajnoczi 
41c23f3445STejun Heo void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
4258e3b602SAl Viro 		     __poll_t mask, struct vhost_dev *dev);
432b8b328bSJason Wang int vhost_poll_start(struct vhost_poll *poll, struct file *file);
443a4d5c94SMichael S. Tsirkin void vhost_poll_stop(struct vhost_poll *poll);
453a4d5c94SMichael S. Tsirkin void vhost_poll_flush(struct vhost_poll *poll);
463a4d5c94SMichael S. Tsirkin void vhost_poll_queue(struct vhost_poll *poll);
476ac1afbfSAsias He void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work);
4826b36604SSonny Rao long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
493a4d5c94SMichael S. Tsirkin 
503a4d5c94SMichael S. Tsirkin struct vhost_log {
513a4d5c94SMichael S. Tsirkin 	u64 addr;
523a4d5c94SMichael S. Tsirkin 	u64 len;
533a4d5c94SMichael S. Tsirkin };
543a4d5c94SMichael S. Tsirkin 
55a9709d68SJason Wang #define START(node) ((node)->start)
56a9709d68SJason Wang #define LAST(node) ((node)->last)
57a9709d68SJason Wang 
58a9709d68SJason Wang struct vhost_umem_node {
59a9709d68SJason Wang 	struct rb_node rb;
60a9709d68SJason Wang 	struct list_head link;
61a9709d68SJason Wang 	__u64 start;
62a9709d68SJason Wang 	__u64 last;
63a9709d68SJason Wang 	__u64 size;
64a9709d68SJason Wang 	__u64 userspace_addr;
656b1e6cc7SJason Wang 	__u32 perm;
666b1e6cc7SJason Wang 	__u32 flags_padding;
67a9709d68SJason Wang 	__u64 __subtree_last;
68a9709d68SJason Wang };
69a9709d68SJason Wang 
70a9709d68SJason Wang struct vhost_umem {
71f808c13fSDavidlohr Bueso 	struct rb_root_cached umem_tree;
72a9709d68SJason Wang 	struct list_head umem_list;
736b1e6cc7SJason Wang 	int numem;
74a9709d68SJason Wang };
75a9709d68SJason Wang 
76f8894913SJason Wang enum vhost_uaddr_type {
77f8894913SJason Wang 	VHOST_ADDR_DESC = 0,
78f8894913SJason Wang 	VHOST_ADDR_AVAIL = 1,
79f8894913SJason Wang 	VHOST_ADDR_USED = 2,
80f8894913SJason Wang 	VHOST_NUM_ADDRS = 3,
81f8894913SJason Wang };
82f8894913SJason Wang 
833a4d5c94SMichael S. Tsirkin /* The virtqueue structure describes a queue attached to a device. */
843a4d5c94SMichael S. Tsirkin struct vhost_virtqueue {
853a4d5c94SMichael S. Tsirkin 	struct vhost_dev *dev;
863a4d5c94SMichael S. Tsirkin 
873a4d5c94SMichael S. Tsirkin 	/* The actual ring of buffers. */
883a4d5c94SMichael S. Tsirkin 	struct mutex mutex;
893a4d5c94SMichael S. Tsirkin 	unsigned int num;
903a4d5c94SMichael S. Tsirkin 	struct vring_desc __user *desc;
913a4d5c94SMichael S. Tsirkin 	struct vring_avail __user *avail;
923a4d5c94SMichael S. Tsirkin 	struct vring_used __user *used;
93f8894913SJason Wang 	const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS];
943a4d5c94SMichael S. Tsirkin 	struct file *kick;
953a4d5c94SMichael S. Tsirkin 	struct eventfd_ctx *call_ctx;
963a4d5c94SMichael S. Tsirkin 	struct eventfd_ctx *error_ctx;
973a4d5c94SMichael S. Tsirkin 	struct eventfd_ctx *log_ctx;
983a4d5c94SMichael S. Tsirkin 
993a4d5c94SMichael S. Tsirkin 	struct vhost_poll poll;
1003a4d5c94SMichael S. Tsirkin 
1013a4d5c94SMichael S. Tsirkin 	/* The routine to call when the Guest pings us, or timeout. */
102c23f3445STejun Heo 	vhost_work_fn_t handle_kick;
1033a4d5c94SMichael S. Tsirkin 
1043a4d5c94SMichael S. Tsirkin 	/* Last available index we saw. */
1053a4d5c94SMichael S. Tsirkin 	u16 last_avail_idx;
1063a4d5c94SMichael S. Tsirkin 
1073a4d5c94SMichael S. Tsirkin 	/* Caches available index value from user. */
1083a4d5c94SMichael S. Tsirkin 	u16 avail_idx;
1093a4d5c94SMichael S. Tsirkin 
1103a4d5c94SMichael S. Tsirkin 	/* Last index we used. */
1113a4d5c94SMichael S. Tsirkin 	u16 last_used_idx;
1123a4d5c94SMichael S. Tsirkin 
1133a4d5c94SMichael S. Tsirkin 	/* Used flags */
1143a4d5c94SMichael S. Tsirkin 	u16 used_flags;
1153a4d5c94SMichael S. Tsirkin 
1168ea8cf89SMichael S. Tsirkin 	/* Last used index value we have signalled on */
1178ea8cf89SMichael S. Tsirkin 	u16 signalled_used;
1188ea8cf89SMichael S. Tsirkin 
1198ea8cf89SMichael S. Tsirkin 	/* Last used index value we have signalled on */
1208ea8cf89SMichael S. Tsirkin 	bool signalled_used_valid;
1218ea8cf89SMichael S. Tsirkin 
1223a4d5c94SMichael S. Tsirkin 	/* Log writes to used structure. */
1233a4d5c94SMichael S. Tsirkin 	bool log_used;
1243a4d5c94SMichael S. Tsirkin 	u64 log_addr;
1253a4d5c94SMichael S. Tsirkin 
126e0e9b406SJason Wang 	struct iovec iov[UIO_MAXIOV];
1276b1e6cc7SJason Wang 	struct iovec iotlb_iov[64];
128e0e9b406SJason Wang 	struct iovec *indirect;
129e0e9b406SJason Wang 	struct vring_used_elem *heads;
13022fa90c7SAsias He 	/* Protected by virtqueue mutex. */
131a9709d68SJason Wang 	struct vhost_umem *umem;
1326b1e6cc7SJason Wang 	struct vhost_umem *iotlb;
13322fa90c7SAsias He 	void *private_data;
134bd82752aSMichael S. Tsirkin 	u64 acked_features;
135429711aeSJason Wang 	u64 acked_backend_features;
1363a4d5c94SMichael S. Tsirkin 	/* Log write descriptors */
1373a4d5c94SMichael S. Tsirkin 	void __user *log_base;
138e0e9b406SJason Wang 	struct vhost_log *log;
1392751c988SGreg Kurz 
1402751c988SGreg Kurz 	/* Ring endianness. Defaults to legacy native endianness.
1412751c988SGreg Kurz 	 * Set to true when starting a modern virtio device. */
1422751c988SGreg Kurz 	bool is_le;
1432751c988SGreg Kurz #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
1442751c988SGreg Kurz 	/* Ring endianness requested by userspace for cross-endian support. */
1452751c988SGreg Kurz 	bool user_be;
1462751c988SGreg Kurz #endif
14703088137SJason Wang 	u32 busyloop_timeout;
1483a4d5c94SMichael S. Tsirkin };
1493a4d5c94SMichael S. Tsirkin 
1506b1e6cc7SJason Wang struct vhost_msg_node {
151429711aeSJason Wang   union {
1526b1e6cc7SJason Wang 	  struct vhost_msg msg;
153429711aeSJason Wang 	  struct vhost_msg_v2 msg_v2;
154429711aeSJason Wang   };
1556b1e6cc7SJason Wang   struct vhost_virtqueue *vq;
1566b1e6cc7SJason Wang   struct list_head node;
1576b1e6cc7SJason Wang };
1586b1e6cc7SJason Wang 
1593a4d5c94SMichael S. Tsirkin struct vhost_dev {
1603a4d5c94SMichael S. Tsirkin 	struct mm_struct *mm;
1613a4d5c94SMichael S. Tsirkin 	struct mutex mutex;
1623ab2e420SAsias He 	struct vhost_virtqueue **vqs;
1633a4d5c94SMichael S. Tsirkin 	int nvqs;
1643a4d5c94SMichael S. Tsirkin 	struct eventfd_ctx *log_ctx;
16504b96e55SJason Wang 	struct llist_head work_list;
166c23f3445STejun Heo 	struct task_struct *worker;
167a9709d68SJason Wang 	struct vhost_umem *umem;
1686b1e6cc7SJason Wang 	struct vhost_umem *iotlb;
1696b1e6cc7SJason Wang 	spinlock_t iotlb_lock;
1706b1e6cc7SJason Wang 	struct list_head read_list;
1716b1e6cc7SJason Wang 	struct list_head pending_list;
1726b1e6cc7SJason Wang 	wait_queue_head_t wait;
1733a4d5c94SMichael S. Tsirkin };
1743a4d5c94SMichael S. Tsirkin 
17559566b6eSZhi Yong Wu void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
17654db63c2SAsias He long vhost_dev_set_owner(struct vhost_dev *dev);
17705c05351SMichael S. Tsirkin bool vhost_dev_has_owner(struct vhost_dev *dev);
1783a4d5c94SMichael S. Tsirkin long vhost_dev_check_owner(struct vhost_dev *);
179a9709d68SJason Wang struct vhost_umem *vhost_dev_reset_owner_prepare(void);
180a9709d68SJason Wang void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_umem *);
181f6f93f75S夷则(Caspar) void vhost_dev_cleanup(struct vhost_dev *);
182b211616dSMichael S. Tsirkin void vhost_dev_stop(struct vhost_dev *);
183935cdee7SMichael S. Tsirkin long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
18426b36604SSonny Rao long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
185ddd3d408SStefan Hajnoczi bool vhost_vq_access_ok(struct vhost_virtqueue *vq);
186ddd3d408SStefan Hajnoczi bool vhost_log_access_ok(struct vhost_dev *);
1873a4d5c94SMichael S. Tsirkin 
18847283befSMichael S. Tsirkin int vhost_get_vq_desc(struct vhost_virtqueue *,
1893a4d5c94SMichael S. Tsirkin 		      struct iovec iov[], unsigned int iov_count,
1903a4d5c94SMichael S. Tsirkin 		      unsigned int *out_num, unsigned int *in_num,
1913a4d5c94SMichael S. Tsirkin 		      struct vhost_log *log, unsigned int *log_num);
1928dd014adSDavid Stevens void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
1933a4d5c94SMichael S. Tsirkin 
19480f7d030SGreg Kurz int vhost_vq_init_access(struct vhost_virtqueue *);
1953a4d5c94SMichael S. Tsirkin int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
1968dd014adSDavid Stevens int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
1978dd014adSDavid Stevens 		     unsigned count);
1983a4d5c94SMichael S. Tsirkin void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *,
1998dd014adSDavid Stevens 			       unsigned int id, int len);
2008dd014adSDavid Stevens void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *,
2018dd014adSDavid Stevens 			       struct vring_used_elem *heads, unsigned count);
2028dd014adSDavid Stevens void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
2038ea8cf89SMichael S. Tsirkin void vhost_disable_notify(struct vhost_dev *, struct vhost_virtqueue *);
204d4a60603SJason Wang bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
2058ea8cf89SMichael S. Tsirkin bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
2063a4d5c94SMichael S. Tsirkin 
2073a4d5c94SMichael S. Tsirkin int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
208*cc5e7107SJason Wang 		    unsigned int log_num, u64 len,
209*cc5e7107SJason Wang 		    struct iovec *iov, int count);
2106b1e6cc7SJason Wang int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
2116b1e6cc7SJason Wang 
2126b1e6cc7SJason Wang struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
2136b1e6cc7SJason Wang void vhost_enqueue_msg(struct vhost_dev *dev,
2146b1e6cc7SJason Wang 		       struct list_head *head,
2156b1e6cc7SJason Wang 		       struct vhost_msg_node *node);
2166b1e6cc7SJason Wang struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev,
2176b1e6cc7SJason Wang 					 struct list_head *head);
218afc9a42bSAl Viro __poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev,
2196b1e6cc7SJason Wang 			    poll_table *wait);
2206b1e6cc7SJason Wang ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to,
2216b1e6cc7SJason Wang 			    int noblock);
2226b1e6cc7SJason Wang ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
2236b1e6cc7SJason Wang 			     struct iov_iter *from);
2246b1e6cc7SJason Wang int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled);
2253a4d5c94SMichael S. Tsirkin 
2263a4d5c94SMichael S. Tsirkin #define vq_err(vq, fmt, ...) do {                                  \
2273a4d5c94SMichael S. Tsirkin 		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \
2283a4d5c94SMichael S. Tsirkin 		if ((vq)->error_ctx)                               \
2293a4d5c94SMichael S. Tsirkin 				eventfd_signal((vq)->error_ctx, 1);\
2303a4d5c94SMichael S. Tsirkin 	} while (0)
2313a4d5c94SMichael S. Tsirkin 
2323a4d5c94SMichael S. Tsirkin enum {
2338ea8cf89SMichael S. Tsirkin 	VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) |
2348ea8cf89SMichael S. Tsirkin 			 (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
2358ea8cf89SMichael S. Tsirkin 			 (1ULL << VIRTIO_RING_F_EVENT_IDX) |
2364e9fa50cSMichael S. Tsirkin 			 (1ULL << VHOST_F_LOG_ALL) |
2374e9fa50cSMichael S. Tsirkin 			 (1ULL << VIRTIO_F_ANY_LAYOUT) |
2384e9fa50cSMichael S. Tsirkin 			 (1ULL << VIRTIO_F_VERSION_1)
2393a4d5c94SMichael S. Tsirkin };
2403a4d5c94SMichael S. Tsirkin 
241bd82752aSMichael S. Tsirkin static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
2423a4d5c94SMichael S. Tsirkin {
243bd82752aSMichael S. Tsirkin 	return vq->acked_features & (1ULL << bit);
2443a4d5c94SMichael S. Tsirkin }
245e05fd12bSMichael S. Tsirkin 
246429711aeSJason Wang static inline bool vhost_backend_has_feature(struct vhost_virtqueue *vq, int bit)
247429711aeSJason Wang {
248429711aeSJason Wang 	return vq->acked_backend_features & (1ULL << bit);
249429711aeSJason Wang }
250429711aeSJason Wang 
251e407f39aSMichael S. Tsirkin #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
252ab27c07fSGreg Kurz static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
253ab27c07fSGreg Kurz {
2542751c988SGreg Kurz 	return vq->is_le;
255ab27c07fSGreg Kurz }
256e407f39aSMichael S. Tsirkin #else
257e407f39aSMichael S. Tsirkin static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
258e407f39aSMichael S. Tsirkin {
259e407f39aSMichael S. Tsirkin 	return virtio_legacy_is_little_endian() || vq->is_le;
260e407f39aSMichael S. Tsirkin }
261e407f39aSMichael S. Tsirkin #endif
262ab27c07fSGreg Kurz 
263e05fd12bSMichael S. Tsirkin /* Memory accessors */
264e05fd12bSMichael S. Tsirkin static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
265e05fd12bSMichael S. Tsirkin {
266ab27c07fSGreg Kurz 	return __virtio16_to_cpu(vhost_is_little_endian(vq), val);
267e05fd12bSMichael S. Tsirkin }
268e05fd12bSMichael S. Tsirkin 
269e05fd12bSMichael S. Tsirkin static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val)
270e05fd12bSMichael S. Tsirkin {
271ab27c07fSGreg Kurz 	return __cpu_to_virtio16(vhost_is_little_endian(vq), val);
272e05fd12bSMichael S. Tsirkin }
273e05fd12bSMichael S. Tsirkin 
274e05fd12bSMichael S. Tsirkin static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val)
275e05fd12bSMichael S. Tsirkin {
276ab27c07fSGreg Kurz 	return __virtio32_to_cpu(vhost_is_little_endian(vq), val);
277e05fd12bSMichael S. Tsirkin }
278e05fd12bSMichael S. Tsirkin 
279e05fd12bSMichael S. Tsirkin static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val)
280e05fd12bSMichael S. Tsirkin {
281ab27c07fSGreg Kurz 	return __cpu_to_virtio32(vhost_is_little_endian(vq), val);
282e05fd12bSMichael S. Tsirkin }
283e05fd12bSMichael S. Tsirkin 
284e05fd12bSMichael S. Tsirkin static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val)
285e05fd12bSMichael S. Tsirkin {
286ab27c07fSGreg Kurz 	return __virtio64_to_cpu(vhost_is_little_endian(vq), val);
287e05fd12bSMichael S. Tsirkin }
288e05fd12bSMichael S. Tsirkin 
289e05fd12bSMichael S. Tsirkin static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val)
290e05fd12bSMichael S. Tsirkin {
291ab27c07fSGreg Kurz 	return __cpu_to_virtio64(vhost_is_little_endian(vq), val);
292e05fd12bSMichael S. Tsirkin }
2933a4d5c94SMichael S. Tsirkin #endif
294