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); 48*26b36604SSonny 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; 1353a4d5c94SMichael S. Tsirkin /* Log write descriptors */ 1363a4d5c94SMichael S. Tsirkin void __user *log_base; 137e0e9b406SJason Wang struct vhost_log *log; 1382751c988SGreg Kurz 1392751c988SGreg Kurz /* Ring endianness. Defaults to legacy native endianness. 1402751c988SGreg Kurz * Set to true when starting a modern virtio device. */ 1412751c988SGreg Kurz bool is_le; 1422751c988SGreg Kurz #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY 1432751c988SGreg Kurz /* Ring endianness requested by userspace for cross-endian support. */ 1442751c988SGreg Kurz bool user_be; 1452751c988SGreg Kurz #endif 14603088137SJason Wang u32 busyloop_timeout; 1473a4d5c94SMichael S. Tsirkin }; 1483a4d5c94SMichael S. Tsirkin 1496b1e6cc7SJason Wang struct vhost_msg_node { 1506b1e6cc7SJason Wang struct vhost_msg msg; 1516b1e6cc7SJason Wang struct vhost_virtqueue *vq; 1526b1e6cc7SJason Wang struct list_head node; 1536b1e6cc7SJason Wang }; 1546b1e6cc7SJason Wang 1553a4d5c94SMichael S. Tsirkin struct vhost_dev { 1563a4d5c94SMichael S. Tsirkin struct mm_struct *mm; 1573a4d5c94SMichael S. Tsirkin struct mutex mutex; 1583ab2e420SAsias He struct vhost_virtqueue **vqs; 1593a4d5c94SMichael S. Tsirkin int nvqs; 1603a4d5c94SMichael S. Tsirkin struct eventfd_ctx *log_ctx; 16104b96e55SJason Wang struct llist_head work_list; 162c23f3445STejun Heo struct task_struct *worker; 163a9709d68SJason Wang struct vhost_umem *umem; 1646b1e6cc7SJason Wang struct vhost_umem *iotlb; 1656b1e6cc7SJason Wang spinlock_t iotlb_lock; 1666b1e6cc7SJason Wang struct list_head read_list; 1676b1e6cc7SJason Wang struct list_head pending_list; 1686b1e6cc7SJason Wang wait_queue_head_t wait; 1693a4d5c94SMichael S. Tsirkin }; 1703a4d5c94SMichael S. Tsirkin 17159566b6eSZhi Yong Wu void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs); 17254db63c2SAsias He long vhost_dev_set_owner(struct vhost_dev *dev); 17305c05351SMichael S. Tsirkin bool vhost_dev_has_owner(struct vhost_dev *dev); 1743a4d5c94SMichael S. Tsirkin long vhost_dev_check_owner(struct vhost_dev *); 175a9709d68SJason Wang struct vhost_umem *vhost_dev_reset_owner_prepare(void); 176a9709d68SJason Wang void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_umem *); 177f6f93f75S夷则(Caspar) void vhost_dev_cleanup(struct vhost_dev *); 178b211616dSMichael S. Tsirkin void vhost_dev_stop(struct vhost_dev *); 179935cdee7SMichael S. Tsirkin long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp); 180*26b36604SSonny Rao long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); 1813a4d5c94SMichael S. Tsirkin int vhost_vq_access_ok(struct vhost_virtqueue *vq); 1823a4d5c94SMichael S. Tsirkin int vhost_log_access_ok(struct vhost_dev *); 1833a4d5c94SMichael S. Tsirkin 18447283befSMichael S. Tsirkin int vhost_get_vq_desc(struct vhost_virtqueue *, 1853a4d5c94SMichael S. Tsirkin struct iovec iov[], unsigned int iov_count, 1863a4d5c94SMichael S. Tsirkin unsigned int *out_num, unsigned int *in_num, 1873a4d5c94SMichael S. Tsirkin struct vhost_log *log, unsigned int *log_num); 1888dd014adSDavid Stevens void vhost_discard_vq_desc(struct vhost_virtqueue *, int n); 1893a4d5c94SMichael S. Tsirkin 19080f7d030SGreg Kurz int vhost_vq_init_access(struct vhost_virtqueue *); 1913a4d5c94SMichael S. Tsirkin int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); 1928dd014adSDavid Stevens int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads, 1938dd014adSDavid Stevens unsigned count); 1943a4d5c94SMichael S. Tsirkin void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *, 1958dd014adSDavid Stevens unsigned int id, int len); 1968dd014adSDavid Stevens void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *, 1978dd014adSDavid Stevens struct vring_used_elem *heads, unsigned count); 1988dd014adSDavid Stevens void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *); 1998ea8cf89SMichael S. Tsirkin void vhost_disable_notify(struct vhost_dev *, struct vhost_virtqueue *); 200d4a60603SJason Wang bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *); 2018ea8cf89SMichael S. Tsirkin bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *); 2023a4d5c94SMichael S. Tsirkin 2033a4d5c94SMichael S. Tsirkin int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, 2043a4d5c94SMichael S. Tsirkin unsigned int log_num, u64 len); 2056b1e6cc7SJason Wang int vq_iotlb_prefetch(struct vhost_virtqueue *vq); 2066b1e6cc7SJason Wang 2076b1e6cc7SJason Wang struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type); 2086b1e6cc7SJason Wang void vhost_enqueue_msg(struct vhost_dev *dev, 2096b1e6cc7SJason Wang struct list_head *head, 2106b1e6cc7SJason Wang struct vhost_msg_node *node); 2116b1e6cc7SJason Wang struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev, 2126b1e6cc7SJason Wang struct list_head *head); 213afc9a42bSAl Viro __poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev, 2146b1e6cc7SJason Wang poll_table *wait); 2156b1e6cc7SJason Wang ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to, 2166b1e6cc7SJason Wang int noblock); 2176b1e6cc7SJason Wang ssize_t vhost_chr_write_iter(struct vhost_dev *dev, 2186b1e6cc7SJason Wang struct iov_iter *from); 2196b1e6cc7SJason Wang int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled); 2203a4d5c94SMichael S. Tsirkin 2213a4d5c94SMichael S. Tsirkin #define vq_err(vq, fmt, ...) do { \ 2223a4d5c94SMichael S. Tsirkin pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ 2233a4d5c94SMichael S. Tsirkin if ((vq)->error_ctx) \ 2243a4d5c94SMichael S. Tsirkin eventfd_signal((vq)->error_ctx, 1);\ 2253a4d5c94SMichael S. Tsirkin } while (0) 2263a4d5c94SMichael S. Tsirkin 2273a4d5c94SMichael S. Tsirkin enum { 2288ea8cf89SMichael S. Tsirkin VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | 2298ea8cf89SMichael S. Tsirkin (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | 2308ea8cf89SMichael S. Tsirkin (1ULL << VIRTIO_RING_F_EVENT_IDX) | 2314e9fa50cSMichael S. Tsirkin (1ULL << VHOST_F_LOG_ALL) | 2324e9fa50cSMichael S. Tsirkin (1ULL << VIRTIO_F_ANY_LAYOUT) | 2334e9fa50cSMichael S. Tsirkin (1ULL << VIRTIO_F_VERSION_1) 2343a4d5c94SMichael S. Tsirkin }; 2353a4d5c94SMichael S. Tsirkin 236bd82752aSMichael S. Tsirkin static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit) 2373a4d5c94SMichael S. Tsirkin { 238bd82752aSMichael S. Tsirkin return vq->acked_features & (1ULL << bit); 2393a4d5c94SMichael S. Tsirkin } 240e05fd12bSMichael S. Tsirkin 241e407f39aSMichael S. Tsirkin #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY 242ab27c07fSGreg Kurz static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq) 243ab27c07fSGreg Kurz { 2442751c988SGreg Kurz return vq->is_le; 245ab27c07fSGreg Kurz } 246e407f39aSMichael S. Tsirkin #else 247e407f39aSMichael S. Tsirkin static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq) 248e407f39aSMichael S. Tsirkin { 249e407f39aSMichael S. Tsirkin return virtio_legacy_is_little_endian() || vq->is_le; 250e407f39aSMichael S. Tsirkin } 251e407f39aSMichael S. Tsirkin #endif 252ab27c07fSGreg Kurz 253e05fd12bSMichael S. Tsirkin /* Memory accessors */ 254e05fd12bSMichael S. Tsirkin static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val) 255e05fd12bSMichael S. Tsirkin { 256ab27c07fSGreg Kurz return __virtio16_to_cpu(vhost_is_little_endian(vq), val); 257e05fd12bSMichael S. Tsirkin } 258e05fd12bSMichael S. Tsirkin 259e05fd12bSMichael S. Tsirkin static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val) 260e05fd12bSMichael S. Tsirkin { 261ab27c07fSGreg Kurz return __cpu_to_virtio16(vhost_is_little_endian(vq), val); 262e05fd12bSMichael S. Tsirkin } 263e05fd12bSMichael S. Tsirkin 264e05fd12bSMichael S. Tsirkin static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val) 265e05fd12bSMichael S. Tsirkin { 266ab27c07fSGreg Kurz return __virtio32_to_cpu(vhost_is_little_endian(vq), val); 267e05fd12bSMichael S. Tsirkin } 268e05fd12bSMichael S. Tsirkin 269e05fd12bSMichael S. Tsirkin static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val) 270e05fd12bSMichael S. Tsirkin { 271ab27c07fSGreg Kurz return __cpu_to_virtio32(vhost_is_little_endian(vq), val); 272e05fd12bSMichael S. Tsirkin } 273e05fd12bSMichael S. Tsirkin 274e05fd12bSMichael S. Tsirkin static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val) 275e05fd12bSMichael S. Tsirkin { 276ab27c07fSGreg Kurz return __virtio64_to_cpu(vhost_is_little_endian(vq), val); 277e05fd12bSMichael S. Tsirkin } 278e05fd12bSMichael S. Tsirkin 279e05fd12bSMichael S. Tsirkin static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val) 280e05fd12bSMichael S. Tsirkin { 281ab27c07fSGreg Kurz return __cpu_to_virtio64(vhost_is_little_endian(vq), val); 282e05fd12bSMichael S. Tsirkin } 2833a4d5c94SMichael S. Tsirkin #endif 284