| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 1 | #ifndef _VHOST_H | 
|  | 2 | #define _VHOST_H | 
|  | 3 |  | 
|  | 4 | #include <linux/eventfd.h> | 
|  | 5 | #include <linux/vhost.h> | 
|  | 6 | #include <linux/mm.h> | 
|  | 7 | #include <linux/mutex.h> | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 8 | #include <linux/poll.h> | 
|  | 9 | #include <linux/file.h> | 
|  | 10 | #include <linux/skbuff.h> | 
|  | 11 | #include <linux/uio.h> | 
|  | 12 | #include <linux/virtio_config.h> | 
|  | 13 | #include <linux/virtio_ring.h> | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 14 | #include <asm/atomic.h> | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 15 |  | 
|  | 16 | struct vhost_device; | 
|  | 17 |  | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 18 | struct vhost_work; | 
|  | 19 | typedef void (*vhost_work_fn_t)(struct vhost_work *work); | 
|  | 20 |  | 
|  | 21 | struct vhost_work { | 
|  | 22 | struct list_head	  node; | 
|  | 23 | vhost_work_fn_t		  fn; | 
|  | 24 | wait_queue_head_t	  done; | 
|  | 25 | int			  flushing; | 
|  | 26 | unsigned		  queue_seq; | 
|  | 27 | unsigned		  done_seq; | 
|  | 28 | }; | 
|  | 29 |  | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 30 | /* Poll a file (eventfd or socket) */ | 
|  | 31 | /* Note: there's nothing vhost specific about this structure. */ | 
|  | 32 | struct vhost_poll { | 
|  | 33 | poll_table                table; | 
|  | 34 | wait_queue_head_t        *wqh; | 
|  | 35 | wait_queue_t              wait; | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 36 | struct vhost_work	  work; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 37 | unsigned long		  mask; | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 38 | struct vhost_dev	 *dev; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 39 | }; | 
|  | 40 |  | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 41 | void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, | 
|  | 42 | unsigned long mask, struct vhost_dev *dev); | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 43 | void vhost_poll_start(struct vhost_poll *poll, struct file *file); | 
|  | 44 | void vhost_poll_stop(struct vhost_poll *poll); | 
|  | 45 | void vhost_poll_flush(struct vhost_poll *poll); | 
|  | 46 | void vhost_poll_queue(struct vhost_poll *poll); | 
|  | 47 |  | 
|  | 48 | struct vhost_log { | 
|  | 49 | u64 addr; | 
|  | 50 | u64 len; | 
|  | 51 | }; | 
|  | 52 |  | 
|  | 53 | /* The virtqueue structure describes a queue attached to a device. */ | 
|  | 54 | struct vhost_virtqueue { | 
|  | 55 | struct vhost_dev *dev; | 
|  | 56 |  | 
|  | 57 | /* The actual ring of buffers. */ | 
|  | 58 | struct mutex mutex; | 
|  | 59 | unsigned int num; | 
|  | 60 | struct vring_desc __user *desc; | 
|  | 61 | struct vring_avail __user *avail; | 
|  | 62 | struct vring_used __user *used; | 
|  | 63 | struct file *kick; | 
|  | 64 | struct file *call; | 
|  | 65 | struct file *error; | 
|  | 66 | struct eventfd_ctx *call_ctx; | 
|  | 67 | struct eventfd_ctx *error_ctx; | 
|  | 68 | struct eventfd_ctx *log_ctx; | 
|  | 69 |  | 
|  | 70 | struct vhost_poll poll; | 
|  | 71 |  | 
|  | 72 | /* The routine to call when the Guest pings us, or timeout. */ | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 73 | vhost_work_fn_t handle_kick; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 74 |  | 
|  | 75 | /* Last available index we saw. */ | 
|  | 76 | u16 last_avail_idx; | 
|  | 77 |  | 
|  | 78 | /* Caches available index value from user. */ | 
|  | 79 | u16 avail_idx; | 
|  | 80 |  | 
|  | 81 | /* Last index we used. */ | 
|  | 82 | u16 last_used_idx; | 
|  | 83 |  | 
|  | 84 | /* Used flags */ | 
|  | 85 | u16 used_flags; | 
|  | 86 |  | 
|  | 87 | /* Log writes to used structure. */ | 
|  | 88 | bool log_used; | 
|  | 89 | u64 log_addr; | 
|  | 90 |  | 
| Jason Wang | e0e9b40 | 2010-09-14 23:53:05 +0800 | [diff] [blame] | 91 | struct iovec iov[UIO_MAXIOV]; | 
|  | 92 | /* hdr is used to store the virtio header. | 
|  | 93 | * Since each iovec has >= 1 byte length, we never need more than | 
|  | 94 | * header length entries to store the header. */ | 
|  | 95 | struct iovec hdr[sizeof(struct virtio_net_hdr_mrg_rxbuf)]; | 
|  | 96 | struct iovec *indirect; | 
| David Stevens | 8dd014a | 2010-07-27 18:52:21 +0300 | [diff] [blame] | 97 | size_t vhost_hlen; | 
|  | 98 | size_t sock_hlen; | 
| Jason Wang | e0e9b40 | 2010-09-14 23:53:05 +0800 | [diff] [blame] | 99 | struct vring_used_elem *heads; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 100 | /* We use a kind of RCU to access private pointer. | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 101 | * All readers access it from worker, which makes it possible to | 
|  | 102 | * flush the vhost_work instead of synchronize_rcu. Therefore readers do | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 103 | * not need to call rcu_read_lock/rcu_read_unlock: the beginning of | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 104 | * vhost_work execution acts instead of rcu_read_lock() and the end of | 
| Jason Wang | a290aec | 2010-11-29 13:48:40 +0800 | [diff] [blame] | 105 | * vhost_work execution acts instead of rcu_read_unlock(). | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 106 | * Writers use virtqueue mutex. */ | 
| Arnd Bergmann | 28457ee | 2010-03-09 19:24:45 +0100 | [diff] [blame] | 107 | void __rcu *private_data; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 108 | /* Log write descriptors */ | 
|  | 109 | void __user *log_base; | 
| Jason Wang | e0e9b40 | 2010-09-14 23:53:05 +0800 | [diff] [blame] | 110 | struct vhost_log *log; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 111 | }; | 
|  | 112 |  | 
|  | 113 | struct vhost_dev { | 
|  | 114 | /* Readers use RCU to access memory table pointer | 
|  | 115 | * log base pointer and features. | 
|  | 116 | * Writers use mutex below.*/ | 
| Arnd Bergmann | 28457ee | 2010-03-09 19:24:45 +0100 | [diff] [blame] | 117 | struct vhost_memory __rcu *memory; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 118 | struct mm_struct *mm; | 
|  | 119 | struct mutex mutex; | 
|  | 120 | unsigned acked_features; | 
|  | 121 | struct vhost_virtqueue *vqs; | 
|  | 122 | int nvqs; | 
|  | 123 | struct file *log_file; | 
|  | 124 | struct eventfd_ctx *log_ctx; | 
| Tejun Heo | c23f344 | 2010-06-02 20:40:00 +0200 | [diff] [blame] | 125 | spinlock_t work_lock; | 
|  | 126 | struct list_head work_list; | 
|  | 127 | struct task_struct *worker; | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 128 | }; | 
|  | 129 |  | 
|  | 130 | long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs); | 
|  | 131 | long vhost_dev_check_owner(struct vhost_dev *); | 
|  | 132 | long vhost_dev_reset_owner(struct vhost_dev *); | 
|  | 133 | void vhost_dev_cleanup(struct vhost_dev *); | 
|  | 134 | long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg); | 
|  | 135 | int vhost_vq_access_ok(struct vhost_virtqueue *vq); | 
|  | 136 | int vhost_log_access_ok(struct vhost_dev *); | 
|  | 137 |  | 
| Michael S. Tsirkin | d5675bd | 2010-06-24 16:59:59 +0300 | [diff] [blame] | 138 | int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, | 
|  | 139 | struct iovec iov[], unsigned int iov_count, | 
|  | 140 | unsigned int *out_num, unsigned int *in_num, | 
|  | 141 | struct vhost_log *log, unsigned int *log_num); | 
| David Stevens | 8dd014a | 2010-07-27 18:52:21 +0300 | [diff] [blame] | 142 | void vhost_discard_vq_desc(struct vhost_virtqueue *, int n); | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 143 |  | 
|  | 144 | int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); | 
| David Stevens | 8dd014a | 2010-07-27 18:52:21 +0300 | [diff] [blame] | 145 | int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads, | 
|  | 146 | unsigned count); | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 147 | void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *, | 
| David Stevens | 8dd014a | 2010-07-27 18:52:21 +0300 | [diff] [blame] | 148 | unsigned int id, int len); | 
|  | 149 | void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *, | 
|  | 150 | struct vring_used_elem *heads, unsigned count); | 
|  | 151 | void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *); | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 152 | void vhost_disable_notify(struct vhost_virtqueue *); | 
|  | 153 | bool vhost_enable_notify(struct vhost_virtqueue *); | 
|  | 154 |  | 
|  | 155 | int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, | 
|  | 156 | unsigned int log_num, u64 len); | 
|  | 157 |  | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 158 | #define vq_err(vq, fmt, ...) do {                                  \ | 
|  | 159 | pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \ | 
|  | 160 | if ((vq)->error_ctx)                               \ | 
|  | 161 | eventfd_signal((vq)->error_ctx, 1);\ | 
|  | 162 | } while (0) | 
|  | 163 |  | 
|  | 164 | enum { | 
|  | 165 | VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | | 
|  | 166 | (1 << VIRTIO_RING_F_INDIRECT_DESC) | | 
|  | 167 | (1 << VHOST_F_LOG_ALL) | | 
| David Stevens | 8dd014a | 2010-07-27 18:52:21 +0300 | [diff] [blame] | 168 | (1 << VHOST_NET_F_VIRTIO_NET_HDR) | | 
|  | 169 | (1 << VIRTIO_NET_F_MRG_RXBUF), | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 170 | }; | 
|  | 171 |  | 
|  | 172 | static inline int vhost_has_feature(struct vhost_dev *dev, int bit) | 
|  | 173 | { | 
| Arnd Bergmann | 28457ee | 2010-03-09 19:24:45 +0100 | [diff] [blame] | 174 | unsigned acked_features; | 
|  | 175 |  | 
| Michael S. Tsirkin | 5e18247 | 2011-01-18 13:04:43 +0200 | [diff] [blame] | 176 | /* TODO: check that we are running from vhost_worker or dev mutex is | 
|  | 177 | * held? */ | 
|  | 178 | acked_features = rcu_dereference_index_check(dev->acked_features, 1); | 
| Michael S. Tsirkin | 3a4d5c9 | 2010-01-14 06:17:27 +0000 | [diff] [blame] | 179 | return acked_features & (1 << bit); | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | #endif |