| 1 |
|
| 2 | |
| 3 | * Linux host-side vring helpers; for when the kernel needs to access
|
| 4 | * someone else's vring.
|
| 5 | *
|
| 6 | * Copyright IBM Corporation, 2013.
|
| 7 | * Parts taken from drivers/vhost/vhost.c Copyright 2009 Red Hat, Inc.
|
| 8 | *
|
| 9 | * Written by: Rusty Russell <[email protected]>
|
| 10 |
|
| 11 | #ifndef _LINUX_VRINGH_H
|
| 12 | #define _LINUX_VRINGH_H
|
| 13 | #include <uapi/linux/virtio_ring.h>
|
| 14 | #include <linux/virtio_byteorder.h>
|
| 15 | #include <linux/uio.h>
|
| 16 | #include <linux/slab.h>
|
| 17 | #include <linux/spinlock.h>
|
| 18 | #if IS_REACHABLE(CONFIG_VHOST_IOTLB)
|
| 19 | #include <linux/dma-direction.h>
|
| 20 | #include <linux/vhost_iotlb.h>
|
| 21 | #endif
|
| 22 | #include <asm/barrier.h>
|
| 23 |
|
| 24 |
|
| 25 | struct vringh {
|
| 26 |
|
| 27 | bool little_endian;
|
| 28 |
|
| 29 |
|
| 30 | bool event_indices;
|
| 31 |
|
| 32 |
|
| 33 | bool weak_barriers;
|
| 34 |
|
| 35 |
|
| 36 | bool use_va;
|
| 37 |
|
| 38 |
|
| 39 | u16 last_avail_idx;
|
| 40 |
|
| 41 |
|
| 42 | u16 last_used_idx;
|
| 43 |
|
| 44 |
|
| 45 | u32 completed;
|
| 46 |
|
| 47 |
|
| 48 | struct vring vring;
|
| 49 |
|
| 50 |
|
| 51 | struct vhost_iotlb *iotlb;
|
| 52 |
|
| 53 |
|
| 54 | spinlock_t *iotlb_lock;
|
| 55 |
|
| 56 |
|
| 57 | void (*notify)(struct vringh *);
|
| 58 | };
|
| 59 |
|
| 60 | struct virtio_device;
|
| 61 | typedef void vrh_callback_t(struct virtio_device *, struct vringh *);
|
| 62 |
|
| 63 | |
| 64 | * struct vringh_config_ops - ops for creating a host vring from a virtio driver
|
| 65 | * @find_vrhs: find the host vrings and instantiate them
|
| 66 | * vdev: the virtio_device
|
| 67 | * nhvrs: the number of host vrings to find
|
| 68 | * hvrs: on success, includes new host vrings
|
| 69 | * callbacks: array of driver callbacks, for each host vring
|
| 70 | * include a NULL entry for vqs that do not need a callback
|
| 71 | * Returns 0 on success or error status
|
| 72 | * @del_vrhs: free the host vrings found by find_vrhs().
|
| 73 |
|
| 74 | struct vringh_config_ops {
|
| 75 | int (*find_vrhs)(struct virtio_device *vdev, unsigned nhvrs,
|
| 76 | struct vringh *vrhs[], vrh_callback_t *callbacks[]);
|
| 77 | void (*del_vrhs)(struct virtio_device *vdev);
|
| 78 | };
|
| 79 |
|
| 80 |
|
| 81 | struct vringh_range {
|
| 82 | u64 start, end_incl;
|
| 83 | u64 offset;
|
| 84 | };
|
| 85 |
|
| 86 | |
| 87 | * struct vringh_iov - iovec mangler.
|
| 88 | * @iov: array of iovecs to operate on
|
| 89 | * @consumed: number of bytes consumed within iov[i]
|
| 90 | * @i: index of current iovec
|
| 91 | * @used: number of iovecs present in @iov
|
| 92 | * @max_num: maximum number of iovecs.
|
| 93 | * corresponds to allocated memory of @iov
|
| 94 | *
|
| 95 | * Mangles iovec in place, and restores it.
|
| 96 | * Remaining data is iov + i, of used - i elements.
|
| 97 |
|
| 98 | struct vringh_iov {
|
| 99 | struct iovec *iov;
|
| 100 | size_t consumed;
|
| 101 | unsigned i, used, max_num;
|
| 102 | };
|
| 103 |
|
| 104 | |
| 105 | * struct vringh_kiov - kvec mangler.
|
| 106 | * @iov: array of iovecs to operate on
|
| 107 | * @consumed: number of bytes consumed within iov[i]
|
| 108 | * @i: index of current iovec
|
| 109 | * @used: number of iovecs present in @iov
|
| 110 | * @max_num: maximum number of iovecs.
|
| 111 | * corresponds to allocated memory of @iov
|
| 112 | *
|
| 113 | * Mangles kvec in place, and restores it.
|
| 114 | * Remaining data is iov + i, of used - i elements.
|
| 115 |
|
| 116 | struct vringh_kiov {
|
| 117 | struct kvec *iov;
|
| 118 | size_t consumed;
|
| 119 | unsigned i, used, max_num;
|
| 120 | };
|
| 121 |
|
| 122 |
|
| 123 | #define VRINGH_IOV_ALLOCATED 0x8000000
|
| 124 |
|
| 125 |
|
| 126 | int vringh_init_user(struct vringh *vrh, u64 features,
|
| 127 | unsigned int num, bool weak_barriers,
|
| 128 | vring_desc_t __user *desc,
|
| 129 | vring_avail_t __user *avail,
|
| 130 | vring_used_t __user *used);
|
| 131 |
|
| 132 | static inline void vringh_iov_init(struct vringh_iov *iov,
|
| 133 | struct iovec *iovec, unsigned num)
|
| 134 | {
|
| 135 | iov->used = iov->i = 0;
|
| 136 | iov->consumed = 0;
|
| 137 | iov->max_num = num;
|
| 138 | iov->iov = iovec;
|
| 139 | }
|
| 140 |
|
| 141 | static inline void vringh_iov_reset(struct vringh_iov *iov)
|
| 142 | {
|
| 143 | iov->iov[iov->i].iov_len += iov->consumed;
|
| 144 | iov->iov[iov->i].iov_base -= iov->consumed;
|
| 145 | iov->consumed = 0;
|
| 146 | iov->i = 0;
|
| 147 | }
|
| 148 |
|
| 149 | static inline void vringh_iov_cleanup(struct vringh_iov *iov)
|
| 150 | {
|
| 151 | if (iov->max_num & VRINGH_IOV_ALLOCATED)
|
| 152 | kfree(iov->iov);
|
| 153 | iov->max_num = iov->used = iov->i = iov->consumed = 0;
|
| 154 | iov->iov = NULL;
|
| 155 | }
|
| 156 |
|
| 157 |
|
| 158 | int vringh_getdesc_user(struct vringh *vrh,
|
| 159 | struct vringh_iov *riov,
|
| 160 | struct vringh_iov *wiov,
|
| 161 | bool (*getrange)(struct vringh *vrh,
|
| 162 | u64 addr, struct vringh_range *r),
|
| 163 | u16 *head);
|
| 164 |
|
| 165 |
|
| 166 | ssize_t vringh_iov_pull_user(struct vringh_iov *riov, void *dst, size_t len);
|
| 167 |
|
| 168 |
|
| 169 | ssize_t vringh_iov_push_user(struct vringh_iov *wiov,
|
| 170 | const void *src, size_t len);
|
| 171 |
|
| 172 |
|
| 173 | int vringh_complete_user(struct vringh *vrh, u16 head, u32 len);
|
| 174 | int vringh_complete_multi_user(struct vringh *vrh,
|
| 175 | const struct vring_used_elem used[],
|
| 176 | unsigned num_used);
|
| 177 |
|
| 178 |
|
| 179 | int vringh_need_notify_user(struct vringh *vrh);
|
| 180 |
|
| 181 | bool vringh_notify_enable_user(struct vringh *vrh);
|
| 182 | void vringh_notify_disable_user(struct vringh *vrh);
|
| 183 |
|
| 184 |
|
| 185 | int vringh_init_kern(struct vringh *vrh, u64 features,
|
| 186 | unsigned int num, bool weak_barriers,
|
| 187 | struct vring_desc *desc,
|
| 188 | struct vring_avail *avail,
|
| 189 | struct vring_used *used);
|
| 190 |
|
| 191 | static inline void vringh_kiov_init(struct vringh_kiov *kiov,
|
| 192 | struct kvec *kvec, unsigned num)
|
| 193 | {
|
| 194 | kiov->used = kiov->i = 0;
|
| 195 | kiov->consumed = 0;
|
| 196 | kiov->max_num = num;
|
| 197 | kiov->iov = kvec;
|
| 198 | }
|
| 199 |
|
| 200 | static inline void vringh_kiov_reset(struct vringh_kiov *kiov)
|
| 201 | {
|
| 202 | kiov->iov[kiov->i].iov_len += kiov->consumed;
|
| 203 | kiov->iov[kiov->i].iov_base -= kiov->consumed;
|
| 204 | kiov->consumed = 0;
|
| 205 | kiov->i = 0;
|
| 206 | }
|
| 207 |
|
| 208 | static inline void vringh_kiov_cleanup(struct vringh_kiov *kiov)
|
| 209 | {
|
| 210 | if (kiov->max_num & VRINGH_IOV_ALLOCATED)
|
| 211 | kfree(kiov->iov);
|
| 212 | kiov->max_num = kiov->used = kiov->i = kiov->consumed = 0;
|
| 213 | kiov->iov = NULL;
|
| 214 | }
|
| 215 |
|
| 216 | static inline size_t vringh_kiov_length(struct vringh_kiov *kiov)
|
| 217 | {
|
| 218 | size_t len = 0;
|
| 219 | int i;
|
| 220 |
|
| 221 | for (i = kiov->i; i < kiov->used; i++)
|
| 222 | len += kiov->iov[i].iov_len;
|
| 223 |
|
| 224 | return len;
|
| 225 | }
|
| 226 |
|
| 227 | void vringh_kiov_advance(struct vringh_kiov *kiov, size_t len);
|
| 228 |
|
| 229 | int vringh_getdesc_kern(struct vringh *vrh,
|
| 230 | struct vringh_kiov *riov,
|
| 231 | struct vringh_kiov *wiov,
|
| 232 | u16 *head,
|
| 233 | gfp_t gfp);
|
| 234 |
|
| 235 | int vringh_complete_kern(struct vringh *vrh, u16 head, u32 len);
|
| 236 |
|
| 237 | bool vringh_notify_enable_kern(struct vringh *vrh);
|
| 238 | void vringh_notify_disable_kern(struct vringh *vrh);
|
| 239 |
|
| 240 | int vringh_need_notify_kern(struct vringh *vrh);
|
| 241 |
|
| 242 |
|
| 243 | static inline void vringh_notify(struct vringh *vrh)
|
| 244 | {
|
| 245 | if (vrh->notify)
|
| 246 | vrh->notify(vrh);
|
| 247 | }
|
| 248 |
|
| 249 | static inline bool vringh_is_little_endian(const struct vringh *vrh)
|
| 250 | {
|
| 251 | return vrh->little_endian ||
|
| 252 | virtio_legacy_is_little_endian();
|
| 253 | }
|
| 254 |
|
| 255 | static inline u16 vringh16_to_cpu(const struct vringh *vrh, __virtio16 val)
|
| 256 | {
|
| 257 | return __virtio16_to_cpu(vringh_is_little_endian(vrh), val);
|
| 258 | }
|
| 259 |
|
| 260 | static inline __virtio16 cpu_to_vringh16(const struct vringh *vrh, u16 val)
|
| 261 | {
|
| 262 | return __cpu_to_virtio16(vringh_is_little_endian(vrh), val);
|
| 263 | }
|
| 264 |
|
| 265 | static inline u32 vringh32_to_cpu(const struct vringh *vrh, __virtio32 val)
|
| 266 | {
|
| 267 | return __virtio32_to_cpu(vringh_is_little_endian(vrh), val);
|
| 268 | }
|
| 269 |
|
| 270 | static inline __virtio32 cpu_to_vringh32(const struct vringh *vrh, u32 val)
|
| 271 | {
|
| 272 | return __cpu_to_virtio32(vringh_is_little_endian(vrh), val);
|
| 273 | }
|
| 274 |
|
| 275 | static inline u64 vringh64_to_cpu(const struct vringh *vrh, __virtio64 val)
|
| 276 | {
|
| 277 | return __virtio64_to_cpu(vringh_is_little_endian(vrh), val);
|
| 278 | }
|
| 279 |
|
| 280 | static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val)
|
| 281 | {
|
| 282 | return __cpu_to_virtio64(vringh_is_little_endian(vrh), val);
|
| 283 | }
|
| 284 |
|
| 285 | #if IS_REACHABLE(CONFIG_VHOST_IOTLB)
|
| 286 |
|
| 287 | void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb,
|
| 288 | spinlock_t *iotlb_lock);
|
| 289 |
|
| 290 | int vringh_init_iotlb(struct vringh *vrh, u64 features,
|
| 291 | unsigned int num, bool weak_barriers,
|
| 292 | struct vring_desc *desc,
|
| 293 | struct vring_avail *avail,
|
| 294 | struct vring_used *used);
|
| 295 |
|
| 296 | int vringh_init_iotlb_va(struct vringh *vrh, u64 features,
|
| 297 | unsigned int num, bool weak_barriers,
|
| 298 | struct vring_desc *desc,
|
| 299 | struct vring_avail *avail,
|
| 300 | struct vring_used *used);
|
| 301 |
|
| 302 | int vringh_getdesc_iotlb(struct vringh *vrh,
|
| 303 | struct vringh_kiov *riov,
|
| 304 | struct vringh_kiov *wiov,
|
| 305 | u16 *head,
|
| 306 | gfp_t gfp);
|
| 307 |
|
| 308 | ssize_t vringh_iov_pull_iotlb(struct vringh *vrh,
|
| 309 | struct vringh_kiov *riov,
|
| 310 | void *dst, size_t len);
|
| 311 | ssize_t vringh_iov_push_iotlb(struct vringh *vrh,
|
| 312 | struct vringh_kiov *wiov,
|
| 313 | const void *src, size_t len);
|
| 314 |
|
| 315 | int vringh_complete_iotlb(struct vringh *vrh, u16 head, u32 len);
|
| 316 |
|
| 317 | int vringh_need_notify_iotlb(struct vringh *vrh);
|
| 318 |
|
| 319 | #endif
|
| 320 |
|
| 321 | #endif
|