| 1 |
|
| 2 | #ifndef _VHOST_H
|
| 3 | #define _VHOST_H
|
| 4 |
|
| 5 | #include <linux/eventfd.h>
|
| 6 | #include <linux/vhost.h>
|
| 7 | #include <linux/mm.h>
|
| 8 | #include <linux/mutex.h>
|
| 9 | #include <linux/poll.h>
|
| 10 | #include <linux/file.h>
|
| 11 | #include <linux/uio.h>
|
| 12 | #include <linux/virtio_config.h>
|
| 13 | #include <linux/virtio_ring.h>
|
| 14 | #include <linux/atomic.h>
|
| 15 | #include <linux/vhost_iotlb.h>
|
| 16 | #include <linux/irqbypass.h>
|
| 17 | #include <linux/unroll.h>
|
| 18 |
|
| 19 | struct vhost_work;
|
| 20 | struct vhost_task;
|
| 21 | typedef void (*vhost_work_fn_t)(struct vhost_work *work);
|
| 22 |
|
| 23 | #define VHOST_WORK_QUEUED 1
|
| 24 | struct vhost_work {
|
| 25 | struct llist_node node;
|
| 26 | vhost_work_fn_t fn;
|
| 27 | unsigned long flags;
|
| 28 | };
|
| 29 |
|
| 30 | struct vhost_worker;
|
| 31 | struct vhost_dev;
|
| 32 | struct vhost_msg_node;
|
| 33 |
|
| 34 | struct vhost_worker_ops {
|
| 35 | int (*create)(struct vhost_worker *worker, struct vhost_dev *dev,
|
| 36 | const char *name);
|
| 37 | void (*stop)(struct vhost_worker *worker);
|
| 38 | void (*wakeup)(struct vhost_worker *worker);
|
| 39 | };
|
| 40 |
|
| 41 | struct vhost_worker {
|
| 42 | struct task_struct *kthread_task;
|
| 43 | struct vhost_task *vtsk;
|
| 44 | struct vhost_dev *dev;
|
| 45 |
|
| 46 | struct mutex mutex;
|
| 47 | struct llist_head work_list;
|
| 48 | struct kcov_common_handle_id kcov_handle;
|
| 49 | u32 id;
|
| 50 | int attachment_cnt;
|
| 51 | bool killed;
|
| 52 | const struct vhost_worker_ops *ops;
|
| 53 | };
|
| 54 |
|
| 55 |
|
| 56 |
|
| 57 | struct vhost_poll {
|
| 58 | poll_table table;
|
| 59 | wait_queue_head_t *wqh;
|
| 60 | wait_queue_entry_t wait;
|
| 61 | struct vhost_work work;
|
| 62 | __poll_t mask;
|
| 63 | struct vhost_dev *dev;
|
| 64 | struct vhost_virtqueue *vq;
|
| 65 | };
|
| 66 |
|
| 67 | void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
|
| 68 | __poll_t mask, struct vhost_dev *dev,
|
| 69 | struct vhost_virtqueue *vq);
|
| 70 | int vhost_poll_start(struct vhost_poll *poll, struct file *file);
|
| 71 | void vhost_poll_stop(struct vhost_poll *poll);
|
| 72 | void vhost_poll_queue(struct vhost_poll *poll);
|
| 73 |
|
| 74 | void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn);
|
| 75 | void vhost_dev_flush(struct vhost_dev *dev);
|
| 76 |
|
| 77 | struct vhost_log {
|
| 78 | u64 addr;
|
| 79 | u64 len;
|
| 80 | };
|
| 81 |
|
| 82 | enum vhost_uaddr_type {
|
| 83 | VHOST_ADDR_DESC = 0,
|
| 84 | VHOST_ADDR_AVAIL = 1,
|
| 85 | VHOST_ADDR_USED = 2,
|
| 86 | VHOST_NUM_ADDRS = 3,
|
| 87 | };
|
| 88 |
|
| 89 | struct vhost_vring_call {
|
| 90 | struct eventfd_ctx *ctx;
|
| 91 | struct irq_bypass_producer producer;
|
| 92 | };
|
| 93 |
|
| 94 |
|
| 95 | struct vhost_virtqueue {
|
| 96 | struct vhost_dev *dev;
|
| 97 | struct vhost_worker __rcu *worker;
|
| 98 |
|
| 99 |
|
| 100 | struct mutex mutex;
|
| 101 | unsigned int num;
|
| 102 | vring_desc_t __user *desc;
|
| 103 | vring_avail_t __user *avail;
|
| 104 | vring_used_t __user *used;
|
| 105 | const struct vhost_iotlb_map *meta_iotlb[VHOST_NUM_ADDRS];
|
| 106 | struct file *kick;
|
| 107 | struct vhost_vring_call call_ctx;
|
| 108 | struct eventfd_ctx *error_ctx;
|
| 109 | struct eventfd_ctx *log_ctx;
|
| 110 |
|
| 111 | struct vhost_poll poll;
|
| 112 |
|
| 113 |
|
| 114 | vhost_work_fn_t handle_kick;
|
| 115 |
|
| 116 | |
| 117 | * Values are limited to 0x7fff, and the high bit is used as
|
| 118 | * a wrap counter when using VIRTIO_F_RING_PACKED.
|
| 119 | u16 last_avail_idx;
|
| 120 |
|
| 121 | u16 next_avail_head;
|
| 122 |
|
| 123 |
|
| 124 | u16 avail_idx;
|
| 125 |
|
| 126 | |
| 127 | * Values are limited to 0x7fff, and the high bit is used as
|
| 128 | * a wrap counter when using VIRTIO_F_RING_PACKED.
|
| 129 | u16 last_used_idx;
|
| 130 |
|
| 131 |
|
| 132 | u16 used_flags;
|
| 133 |
|
| 134 |
|
| 135 | u16 signalled_used;
|
| 136 |
|
| 137 |
|
| 138 | bool signalled_used_valid;
|
| 139 |
|
| 140 |
|
| 141 | bool log_used;
|
| 142 | u64 log_addr;
|
| 143 |
|
| 144 | struct iovec iov[UIO_MAXIOV];
|
| 145 | struct iovec iotlb_iov[64];
|
| 146 | struct iovec *indirect;
|
| 147 | struct vring_used_elem *heads;
|
| 148 | u16 *nheads;
|
| 149 |
|
| 150 | struct vhost_iotlb *umem;
|
| 151 | struct vhost_iotlb *iotlb;
|
| 152 |
|
| 153 | struct vhost_msg_node *iotlb_miss;
|
| 154 | void *private_data;
|
| 155 | VIRTIO_DECLARE_FEATURES(acked_features);
|
| 156 | u64 acked_backend_features;
|
| 157 |
|
| 158 | void __user *log_base;
|
| 159 | struct vhost_log *log;
|
| 160 | struct iovec log_iov[64];
|
| 161 |
|
| 162 | |
| 163 | * Set to true when starting a modern virtio device.
|
| 164 | bool is_le;
|
| 165 | #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
|
| 166 |
|
| 167 | bool user_be;
|
| 168 | #endif
|
| 169 | u32 busyloop_timeout;
|
| 170 | };
|
| 171 |
|
| 172 | struct vhost_msg_node {
|
| 173 | union {
|
| 174 | struct vhost_msg msg;
|
| 175 | struct vhost_msg_v2 msg_v2;
|
| 176 | };
|
| 177 | struct vhost_virtqueue *vq;
|
| 178 | struct list_head node;
|
| 179 | };
|
| 180 |
|
| 181 | struct vhost_dev {
|
| 182 | struct mm_struct *mm;
|
| 183 | struct mutex mutex;
|
| 184 | struct vhost_virtqueue **vqs;
|
| 185 | int nvqs;
|
| 186 | struct eventfd_ctx *log_ctx;
|
| 187 | struct vhost_iotlb *umem;
|
| 188 | struct vhost_iotlb *iotlb;
|
| 189 | spinlock_t iotlb_lock;
|
| 190 | struct list_head read_list;
|
| 191 | struct list_head pending_list;
|
| 192 | wait_queue_head_t wait;
|
| 193 | int iov_limit;
|
| 194 | int weight;
|
| 195 | int byte_weight;
|
| 196 | struct xarray worker_xa;
|
| 197 | bool use_worker;
|
| 198 | |
| 199 | * If fork_owner is true we use vhost_tasks to create
|
| 200 | * the worker so all settings/limits like cgroups, NPROC,
|
| 201 | * scheduler, etc are inherited from the owner. If false,
|
| 202 | * we use kthreads and only attach to the same cgroups
|
| 203 | * as the owner for compat with older kernels.
|
| 204 | * here we use true as default value.
|
| 205 | * The default value is set by fork_from_owner_default
|
| 206 |
|
| 207 | bool fork_owner;
|
| 208 | int (*msg_handler)(struct vhost_dev *dev, u32 asid,
|
| 209 | struct vhost_iotlb_msg *msg);
|
| 210 | };
|
| 211 |
|
| 212 | bool vhost_exceeds_weight(struct vhost_virtqueue *vq, int pkts, int total_len);
|
| 213 | void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
|
| 214 | int nvqs, int iov_limit, int weight, int byte_weight,
|
| 215 | bool use_worker,
|
| 216 | int (*msg_handler)(struct vhost_dev *dev, u32 asid,
|
| 217 | struct vhost_iotlb_msg *msg));
|
| 218 | long vhost_dev_set_owner(struct vhost_dev *dev);
|
| 219 | bool vhost_dev_has_owner(struct vhost_dev *dev);
|
| 220 | long vhost_dev_check_owner(struct vhost_dev *);
|
| 221 | struct vhost_iotlb *vhost_dev_reset_owner_prepare(void);
|
| 222 | void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_iotlb *iotlb);
|
| 223 | void vhost_dev_cleanup(struct vhost_dev *);
|
| 224 | void vhost_dev_stop(struct vhost_dev *);
|
| 225 | long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
|
| 226 | long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
|
| 227 | long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl,
|
| 228 | void __user *argp);
|
| 229 | bool vhost_vq_access_ok(struct vhost_virtqueue *vq);
|
| 230 | bool vhost_log_access_ok(struct vhost_dev *);
|
| 231 | void vhost_clear_msg(struct vhost_dev *dev);
|
| 232 |
|
| 233 | int vhost_get_vq_desc(struct vhost_virtqueue *,
|
| 234 | struct iovec iov[], unsigned int iov_size,
|
| 235 | unsigned int *out_num, unsigned int *in_num,
|
| 236 | struct vhost_log *log, unsigned int *log_num);
|
| 237 |
|
| 238 | int vhost_get_vq_desc_n(struct vhost_virtqueue *vq,
|
| 239 | struct iovec iov[], unsigned int iov_size,
|
| 240 | unsigned int *out_num, unsigned int *in_num,
|
| 241 | struct vhost_log *log, unsigned int *log_num,
|
| 242 | unsigned int *ndesc);
|
| 243 |
|
| 244 | void vhost_discard_vq_desc(struct vhost_virtqueue *, int nbuf,
|
| 245 | unsigned int ndesc);
|
| 246 |
|
| 247 | bool vhost_vq_work_queue(struct vhost_virtqueue *vq, struct vhost_work *work);
|
| 248 | bool vhost_vq_has_work(struct vhost_virtqueue *vq);
|
| 249 | bool vhost_vq_is_setup(struct vhost_virtqueue *vq);
|
| 250 | int vhost_vq_init_access(struct vhost_virtqueue *);
|
| 251 | int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
|
| 252 | int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
|
| 253 | u16 *nheads, unsigned count);
|
| 254 | void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *,
|
| 255 | unsigned int id, int len);
|
| 256 | void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *,
|
| 257 | struct vring_used_elem *heads, u16 *nheads,
|
| 258 | unsigned count);
|
| 259 | void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
|
| 260 | void vhost_disable_notify(struct vhost_dev *, struct vhost_virtqueue *);
|
| 261 | bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
|
| 262 | bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
|
| 263 |
|
| 264 | int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
|
| 265 | unsigned int log_num, u64 len,
|
| 266 | struct iovec *iov, int count);
|
| 267 | int vq_meta_prefetch(struct vhost_virtqueue *vq);
|
| 268 |
|
| 269 | struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
|
| 270 | void vhost_enqueue_msg(struct vhost_dev *dev,
|
| 271 | struct list_head *head,
|
| 272 | struct vhost_msg_node *node);
|
| 273 | struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev,
|
| 274 | struct list_head *head);
|
| 275 | void vhost_set_backend_features(struct vhost_dev *dev, u64 features);
|
| 276 |
|
| 277 | __poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev,
|
| 278 | poll_table *wait);
|
| 279 | ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to,
|
| 280 | int noblock);
|
| 281 | ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
|
| 282 | struct iov_iter *from);
|
| 283 | void vhost_clear_device_iotlb(struct vhost_dev *d);
|
| 284 | int vhost_init_device_iotlb(struct vhost_dev *d);
|
| 285 |
|
| 286 | void vhost_iotlb_map_free(struct vhost_iotlb *iotlb,
|
| 287 | struct vhost_iotlb_map *map);
|
| 288 |
|
| 289 | #define vq_err(vq, fmt, ...) do { \
|
| 290 | pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
|
| 291 | if ((vq)->error_ctx) \
|
| 292 | eventfd_signal((vq)->error_ctx);\
|
| 293 | } while (0)
|
| 294 |
|
| 295 | #define VHOST_FEATURES \
|
| 296 | VIRTIO_F_NOTIFY_ON_EMPTY, \
|
| 297 | VIRTIO_RING_F_INDIRECT_DESC, \
|
| 298 | VIRTIO_RING_F_EVENT_IDX, \
|
| 299 | VHOST_F_LOG_ALL, \
|
| 300 | VIRTIO_F_ANY_LAYOUT, \
|
| 301 | VIRTIO_F_VERSION_1
|
| 302 |
|
| 303 | static inline u64 vhost_features_u64(const int *features, int size, int idx)
|
| 304 | {
|
| 305 | u64 res = 0;
|
| 306 |
|
| 307 | unrolled_count(VIRTIO_FEATURES_BITS)
|
| 308 | for (int i = 0; i < size; ++i) {
|
| 309 | int bit = features[i];
|
| 310 |
|
| 311 | if (virtio_features_chk_bit(bit) && VIRTIO_U64(bit) == idx)
|
| 312 | res |= VIRTIO_BIT(bit);
|
| 313 | }
|
| 314 | return res;
|
| 315 | }
|
| 316 |
|
| 317 | #define VHOST_FEATURES_U64(features, idx) \
|
| 318 | vhost_features_u64(features, ARRAY_SIZE(features), idx)
|
| 319 |
|
| 320 | #define DEFINE_VHOST_FEATURES_ARRAY_ENTRY(idx, features) \
|
| 321 | [idx] = VHOST_FEATURES_U64(features, idx),
|
| 322 |
|
| 323 | #define DEFINE_VHOST_FEATURES_ARRAY(array, features) \
|
| 324 | u64 array[VIRTIO_FEATURES_U64S] = { \
|
| 325 | UNROLL(VIRTIO_FEATURES_U64S, \
|
| 326 | DEFINE_VHOST_FEATURES_ARRAY_ENTRY, features) \
|
| 327 | }
|
| 328 |
|
| 329 | |
| 330 | * vhost_vq_set_backend - Set backend.
|
| 331 | *
|
| 332 | * @vq Virtqueue.
|
| 333 | * @private_data The private data.
|
| 334 | *
|
| 335 | * Context: Need to call with vq->mutex acquired.
|
| 336 |
|
| 337 | static inline void vhost_vq_set_backend(struct vhost_virtqueue *vq,
|
| 338 | void *private_data)
|
| 339 | {
|
| 340 | vq->private_data = private_data;
|
| 341 | }
|
| 342 |
|
| 343 | |
| 344 | * vhost_vq_get_backend - Get backend.
|
| 345 | *
|
| 346 | * @vq Virtqueue.
|
| 347 | *
|
| 348 | * Context: Need to call with vq->mutex acquired.
|
| 349 | * Return: Private data previously set with vhost_vq_set_backend.
|
| 350 |
|
| 351 | static inline void *vhost_vq_get_backend(struct vhost_virtqueue *vq)
|
| 352 | {
|
| 353 | return vq->private_data;
|
| 354 | }
|
| 355 |
|
| 356 | static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
|
| 357 | {
|
| 358 | return virtio_features_test_bit(vq->acked_features_array, bit);
|
| 359 | }
|
| 360 |
|
| 361 | static inline bool vhost_backend_has_feature(struct vhost_virtqueue *vq, int bit)
|
| 362 | {
|
| 363 | return vq->acked_backend_features & (1ULL << bit);
|
| 364 | }
|
| 365 |
|
| 366 | #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
|
| 367 | static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
|
| 368 | {
|
| 369 | return vq->is_le;
|
| 370 | }
|
| 371 | #else
|
| 372 | static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
|
| 373 | {
|
| 374 | return virtio_legacy_is_little_endian() || vq->is_le;
|
| 375 | }
|
| 376 | #endif
|
| 377 |
|
| 378 |
|
| 379 | static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
|
| 380 | {
|
| 381 | return __virtio16_to_cpu(vhost_is_little_endian(vq), val);
|
| 382 | }
|
| 383 |
|
| 384 | static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val)
|
| 385 | {
|
| 386 | return __cpu_to_virtio16(vhost_is_little_endian(vq), val);
|
| 387 | }
|
| 388 |
|
| 389 | static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val)
|
| 390 | {
|
| 391 | return __virtio32_to_cpu(vhost_is_little_endian(vq), val);
|
| 392 | }
|
| 393 |
|
| 394 | static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val)
|
| 395 | {
|
| 396 | return __cpu_to_virtio32(vhost_is_little_endian(vq), val);
|
| 397 | }
|
| 398 |
|
| 399 | static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val)
|
| 400 | {
|
| 401 | return __virtio64_to_cpu(vhost_is_little_endian(vq), val);
|
| 402 | }
|
| 403 |
|
| 404 | static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val)
|
| 405 | {
|
| 406 | return __cpu_to_virtio64(vhost_is_little_endian(vq), val);
|
| 407 | }
|
| 408 | #endif
|