162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Helpers for the host side of a virtio ring. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Since these may be in userspace, we use (inline) accessors. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/compiler.h> 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/vringh.h> 1062306a36Sopenharmony_ci#include <linux/virtio_ring.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/ratelimit.h> 1362306a36Sopenharmony_ci#include <linux/uaccess.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/export.h> 1662306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_VHOST_IOTLB) 1762306a36Sopenharmony_ci#include <linux/bvec.h> 1862306a36Sopenharmony_ci#include <linux/highmem.h> 1962306a36Sopenharmony_ci#include <linux/vhost_iotlb.h> 2062306a36Sopenharmony_ci#endif 2162306a36Sopenharmony_ci#include <uapi/linux/virtio_config.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic __printf(1,2) __cold void vringh_bad(const char *fmt, ...) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci static DEFINE_RATELIMIT_STATE(vringh_rs, 2662306a36Sopenharmony_ci DEFAULT_RATELIMIT_INTERVAL, 2762306a36Sopenharmony_ci DEFAULT_RATELIMIT_BURST); 2862306a36Sopenharmony_ci if (__ratelimit(&vringh_rs)) { 2962306a36Sopenharmony_ci va_list ap; 3062306a36Sopenharmony_ci va_start(ap, fmt); 3162306a36Sopenharmony_ci printk(KERN_NOTICE "vringh:"); 3262306a36Sopenharmony_ci vprintk(fmt, ap); 3362306a36Sopenharmony_ci va_end(ap); 3462306a36Sopenharmony_ci } 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* Returns vring->num if empty, -ve on error. */ 3862306a36Sopenharmony_cistatic inline int __vringh_get_head(const struct vringh *vrh, 3962306a36Sopenharmony_ci int (*getu16)(const struct vringh *vrh, 4062306a36Sopenharmony_ci u16 *val, const __virtio16 *p), 4162306a36Sopenharmony_ci u16 *last_avail_idx) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci u16 avail_idx, i, head; 4462306a36Sopenharmony_ci int err; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci err = getu16(vrh, &avail_idx, &vrh->vring.avail->idx); 4762306a36Sopenharmony_ci if (err) { 4862306a36Sopenharmony_ci vringh_bad("Failed to access avail idx at %p", 4962306a36Sopenharmony_ci &vrh->vring.avail->idx); 5062306a36Sopenharmony_ci return err; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (*last_avail_idx == avail_idx) 5462306a36Sopenharmony_ci return vrh->vring.num; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* Only get avail ring entries after they have been exposed by guest. */ 5762306a36Sopenharmony_ci virtio_rmb(vrh->weak_barriers); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci i = *last_avail_idx & (vrh->vring.num - 1); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci err = getu16(vrh, &head, &vrh->vring.avail->ring[i]); 6262306a36Sopenharmony_ci if (err) { 6362306a36Sopenharmony_ci vringh_bad("Failed to read head: idx %d address %p", 6462306a36Sopenharmony_ci *last_avail_idx, &vrh->vring.avail->ring[i]); 6562306a36Sopenharmony_ci return err; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (head >= vrh->vring.num) { 6962306a36Sopenharmony_ci vringh_bad("Guest says index %u > %u is available", 7062306a36Sopenharmony_ci head, vrh->vring.num); 7162306a36Sopenharmony_ci return -EINVAL; 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci (*last_avail_idx)++; 7562306a36Sopenharmony_ci return head; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/** 7962306a36Sopenharmony_ci * vringh_kiov_advance - skip bytes from vring_kiov 8062306a36Sopenharmony_ci * @iov: an iov passed to vringh_getdesc_*() (updated as we consume) 8162306a36Sopenharmony_ci * @len: the maximum length to advance 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_civoid vringh_kiov_advance(struct vringh_kiov *iov, size_t len) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci while (len && iov->i < iov->used) { 8662306a36Sopenharmony_ci size_t partlen = min(iov->iov[iov->i].iov_len, len); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci iov->consumed += partlen; 8962306a36Sopenharmony_ci iov->iov[iov->i].iov_len -= partlen; 9062306a36Sopenharmony_ci iov->iov[iov->i].iov_base += partlen; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (!iov->iov[iov->i].iov_len) { 9362306a36Sopenharmony_ci /* Fix up old iov element then increment. */ 9462306a36Sopenharmony_ci iov->iov[iov->i].iov_len = iov->consumed; 9562306a36Sopenharmony_ci iov->iov[iov->i].iov_base -= iov->consumed; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci iov->consumed = 0; 9862306a36Sopenharmony_ci iov->i++; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci len -= partlen; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_kiov_advance); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* Copy some bytes to/from the iovec. Returns num copied. */ 10762306a36Sopenharmony_cistatic inline ssize_t vringh_iov_xfer(struct vringh *vrh, 10862306a36Sopenharmony_ci struct vringh_kiov *iov, 10962306a36Sopenharmony_ci void *ptr, size_t len, 11062306a36Sopenharmony_ci int (*xfer)(const struct vringh *vrh, 11162306a36Sopenharmony_ci void *addr, void *ptr, 11262306a36Sopenharmony_ci size_t len)) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci int err, done = 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci while (len && iov->i < iov->used) { 11762306a36Sopenharmony_ci size_t partlen; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci partlen = min(iov->iov[iov->i].iov_len, len); 12062306a36Sopenharmony_ci err = xfer(vrh, iov->iov[iov->i].iov_base, ptr, partlen); 12162306a36Sopenharmony_ci if (err) 12262306a36Sopenharmony_ci return err; 12362306a36Sopenharmony_ci done += partlen; 12462306a36Sopenharmony_ci len -= partlen; 12562306a36Sopenharmony_ci ptr += partlen; 12662306a36Sopenharmony_ci iov->consumed += partlen; 12762306a36Sopenharmony_ci iov->iov[iov->i].iov_len -= partlen; 12862306a36Sopenharmony_ci iov->iov[iov->i].iov_base += partlen; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (!iov->iov[iov->i].iov_len) { 13162306a36Sopenharmony_ci /* Fix up old iov element then increment. */ 13262306a36Sopenharmony_ci iov->iov[iov->i].iov_len = iov->consumed; 13362306a36Sopenharmony_ci iov->iov[iov->i].iov_base -= iov->consumed; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci iov->consumed = 0; 13662306a36Sopenharmony_ci iov->i++; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci return done; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/* May reduce *len if range is shorter. */ 14362306a36Sopenharmony_cistatic inline bool range_check(struct vringh *vrh, u64 addr, size_t *len, 14462306a36Sopenharmony_ci struct vringh_range *range, 14562306a36Sopenharmony_ci bool (*getrange)(struct vringh *, 14662306a36Sopenharmony_ci u64, struct vringh_range *)) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci if (addr < range->start || addr > range->end_incl) { 14962306a36Sopenharmony_ci if (!getrange(vrh, addr, range)) 15062306a36Sopenharmony_ci return false; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci BUG_ON(addr < range->start || addr > range->end_incl); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* To end of memory? */ 15562306a36Sopenharmony_ci if (unlikely(addr + *len == 0)) { 15662306a36Sopenharmony_ci if (range->end_incl == -1ULL) 15762306a36Sopenharmony_ci return true; 15862306a36Sopenharmony_ci goto truncate; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Otherwise, don't wrap. */ 16262306a36Sopenharmony_ci if (addr + *len < addr) { 16362306a36Sopenharmony_ci vringh_bad("Wrapping descriptor %zu@0x%llx", 16462306a36Sopenharmony_ci *len, (unsigned long long)addr); 16562306a36Sopenharmony_ci return false; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (unlikely(addr + *len - 1 > range->end_incl)) 16962306a36Sopenharmony_ci goto truncate; 17062306a36Sopenharmony_ci return true; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_citruncate: 17362306a36Sopenharmony_ci *len = range->end_incl + 1 - addr; 17462306a36Sopenharmony_ci return true; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic inline bool no_range_check(struct vringh *vrh, u64 addr, size_t *len, 17862306a36Sopenharmony_ci struct vringh_range *range, 17962306a36Sopenharmony_ci bool (*getrange)(struct vringh *, 18062306a36Sopenharmony_ci u64, struct vringh_range *)) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci return true; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* No reason for this code to be inline. */ 18662306a36Sopenharmony_cistatic int move_to_indirect(const struct vringh *vrh, 18762306a36Sopenharmony_ci int *up_next, u16 *i, void *addr, 18862306a36Sopenharmony_ci const struct vring_desc *desc, 18962306a36Sopenharmony_ci struct vring_desc **descs, int *desc_max) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci u32 len; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* Indirect tables can't have indirect. */ 19462306a36Sopenharmony_ci if (*up_next != -1) { 19562306a36Sopenharmony_ci vringh_bad("Multilevel indirect %u->%u", *up_next, *i); 19662306a36Sopenharmony_ci return -EINVAL; 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci len = vringh32_to_cpu(vrh, desc->len); 20062306a36Sopenharmony_ci if (unlikely(len % sizeof(struct vring_desc))) { 20162306a36Sopenharmony_ci vringh_bad("Strange indirect len %u", desc->len); 20262306a36Sopenharmony_ci return -EINVAL; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* We will check this when we follow it! */ 20662306a36Sopenharmony_ci if (desc->flags & cpu_to_vringh16(vrh, VRING_DESC_F_NEXT)) 20762306a36Sopenharmony_ci *up_next = vringh16_to_cpu(vrh, desc->next); 20862306a36Sopenharmony_ci else 20962306a36Sopenharmony_ci *up_next = -2; 21062306a36Sopenharmony_ci *descs = addr; 21162306a36Sopenharmony_ci *desc_max = len / sizeof(struct vring_desc); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* Now, start at the first indirect. */ 21462306a36Sopenharmony_ci *i = 0; 21562306a36Sopenharmony_ci return 0; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic int resize_iovec(struct vringh_kiov *iov, gfp_t gfp) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct kvec *new; 22162306a36Sopenharmony_ci unsigned int flag, new_num = (iov->max_num & ~VRINGH_IOV_ALLOCATED) * 2; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (new_num < 8) 22462306a36Sopenharmony_ci new_num = 8; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci flag = (iov->max_num & VRINGH_IOV_ALLOCATED); 22762306a36Sopenharmony_ci if (flag) 22862306a36Sopenharmony_ci new = krealloc_array(iov->iov, new_num, 22962306a36Sopenharmony_ci sizeof(struct iovec), gfp); 23062306a36Sopenharmony_ci else { 23162306a36Sopenharmony_ci new = kmalloc_array(new_num, sizeof(struct iovec), gfp); 23262306a36Sopenharmony_ci if (new) { 23362306a36Sopenharmony_ci memcpy(new, iov->iov, 23462306a36Sopenharmony_ci iov->max_num * sizeof(struct iovec)); 23562306a36Sopenharmony_ci flag = VRINGH_IOV_ALLOCATED; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci if (!new) 23962306a36Sopenharmony_ci return -ENOMEM; 24062306a36Sopenharmony_ci iov->iov = new; 24162306a36Sopenharmony_ci iov->max_num = (new_num | flag); 24262306a36Sopenharmony_ci return 0; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic u16 __cold return_from_indirect(const struct vringh *vrh, int *up_next, 24662306a36Sopenharmony_ci struct vring_desc **descs, int *desc_max) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci u16 i = *up_next; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci *up_next = -1; 25162306a36Sopenharmony_ci *descs = vrh->vring.desc; 25262306a36Sopenharmony_ci *desc_max = vrh->vring.num; 25362306a36Sopenharmony_ci return i; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int slow_copy(struct vringh *vrh, void *dst, const void *src, 25762306a36Sopenharmony_ci bool (*rcheck)(struct vringh *vrh, u64 addr, size_t *len, 25862306a36Sopenharmony_ci struct vringh_range *range, 25962306a36Sopenharmony_ci bool (*getrange)(struct vringh *vrh, 26062306a36Sopenharmony_ci u64, 26162306a36Sopenharmony_ci struct vringh_range *)), 26262306a36Sopenharmony_ci bool (*getrange)(struct vringh *vrh, 26362306a36Sopenharmony_ci u64 addr, 26462306a36Sopenharmony_ci struct vringh_range *r), 26562306a36Sopenharmony_ci struct vringh_range *range, 26662306a36Sopenharmony_ci int (*copy)(const struct vringh *vrh, 26762306a36Sopenharmony_ci void *dst, const void *src, size_t len)) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci size_t part, len = sizeof(struct vring_desc); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci do { 27262306a36Sopenharmony_ci u64 addr; 27362306a36Sopenharmony_ci int err; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci part = len; 27662306a36Sopenharmony_ci addr = (u64)(unsigned long)src - range->offset; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (!rcheck(vrh, addr, &part, range, getrange)) 27962306a36Sopenharmony_ci return -EINVAL; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci err = copy(vrh, dst, src, part); 28262306a36Sopenharmony_ci if (err) 28362306a36Sopenharmony_ci return err; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci dst += part; 28662306a36Sopenharmony_ci src += part; 28762306a36Sopenharmony_ci len -= part; 28862306a36Sopenharmony_ci } while (len); 28962306a36Sopenharmony_ci return 0; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic inline int 29362306a36Sopenharmony_ci__vringh_iov(struct vringh *vrh, u16 i, 29462306a36Sopenharmony_ci struct vringh_kiov *riov, 29562306a36Sopenharmony_ci struct vringh_kiov *wiov, 29662306a36Sopenharmony_ci bool (*rcheck)(struct vringh *vrh, u64 addr, size_t *len, 29762306a36Sopenharmony_ci struct vringh_range *range, 29862306a36Sopenharmony_ci bool (*getrange)(struct vringh *, u64, 29962306a36Sopenharmony_ci struct vringh_range *)), 30062306a36Sopenharmony_ci bool (*getrange)(struct vringh *, u64, struct vringh_range *), 30162306a36Sopenharmony_ci gfp_t gfp, 30262306a36Sopenharmony_ci int (*copy)(const struct vringh *vrh, 30362306a36Sopenharmony_ci void *dst, const void *src, size_t len)) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci int err, count = 0, indirect_count = 0, up_next, desc_max; 30662306a36Sopenharmony_ci struct vring_desc desc, *descs; 30762306a36Sopenharmony_ci struct vringh_range range = { -1ULL, 0 }, slowrange; 30862306a36Sopenharmony_ci bool slow = false; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* We start traversing vring's descriptor table. */ 31162306a36Sopenharmony_ci descs = vrh->vring.desc; 31262306a36Sopenharmony_ci desc_max = vrh->vring.num; 31362306a36Sopenharmony_ci up_next = -1; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* You must want something! */ 31662306a36Sopenharmony_ci if (WARN_ON(!riov && !wiov)) 31762306a36Sopenharmony_ci return -EINVAL; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (riov) 32062306a36Sopenharmony_ci riov->i = riov->used = riov->consumed = 0; 32162306a36Sopenharmony_ci if (wiov) 32262306a36Sopenharmony_ci wiov->i = wiov->used = wiov->consumed = 0; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci for (;;) { 32562306a36Sopenharmony_ci void *addr; 32662306a36Sopenharmony_ci struct vringh_kiov *iov; 32762306a36Sopenharmony_ci size_t len; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (unlikely(slow)) 33062306a36Sopenharmony_ci err = slow_copy(vrh, &desc, &descs[i], rcheck, getrange, 33162306a36Sopenharmony_ci &slowrange, copy); 33262306a36Sopenharmony_ci else 33362306a36Sopenharmony_ci err = copy(vrh, &desc, &descs[i], sizeof(desc)); 33462306a36Sopenharmony_ci if (unlikely(err)) 33562306a36Sopenharmony_ci goto fail; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (unlikely(desc.flags & 33862306a36Sopenharmony_ci cpu_to_vringh16(vrh, VRING_DESC_F_INDIRECT))) { 33962306a36Sopenharmony_ci u64 a = vringh64_to_cpu(vrh, desc.addr); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Make sure it's OK, and get offset. */ 34262306a36Sopenharmony_ci len = vringh32_to_cpu(vrh, desc.len); 34362306a36Sopenharmony_ci if (!rcheck(vrh, a, &len, &range, getrange)) { 34462306a36Sopenharmony_ci err = -EINVAL; 34562306a36Sopenharmony_ci goto fail; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (unlikely(len != vringh32_to_cpu(vrh, desc.len))) { 34962306a36Sopenharmony_ci slow = true; 35062306a36Sopenharmony_ci /* We need to save this range to use offset */ 35162306a36Sopenharmony_ci slowrange = range; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci addr = (void *)(long)(a + range.offset); 35562306a36Sopenharmony_ci err = move_to_indirect(vrh, &up_next, &i, addr, &desc, 35662306a36Sopenharmony_ci &descs, &desc_max); 35762306a36Sopenharmony_ci if (err) 35862306a36Sopenharmony_ci goto fail; 35962306a36Sopenharmony_ci continue; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (up_next == -1) 36362306a36Sopenharmony_ci count++; 36462306a36Sopenharmony_ci else 36562306a36Sopenharmony_ci indirect_count++; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (count > vrh->vring.num || indirect_count > desc_max) { 36862306a36Sopenharmony_ci vringh_bad("Descriptor loop in %p", descs); 36962306a36Sopenharmony_ci err = -ELOOP; 37062306a36Sopenharmony_ci goto fail; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (desc.flags & cpu_to_vringh16(vrh, VRING_DESC_F_WRITE)) 37462306a36Sopenharmony_ci iov = wiov; 37562306a36Sopenharmony_ci else { 37662306a36Sopenharmony_ci iov = riov; 37762306a36Sopenharmony_ci if (unlikely(wiov && wiov->used)) { 37862306a36Sopenharmony_ci vringh_bad("Readable desc %p after writable", 37962306a36Sopenharmony_ci &descs[i]); 38062306a36Sopenharmony_ci err = -EINVAL; 38162306a36Sopenharmony_ci goto fail; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (!iov) { 38662306a36Sopenharmony_ci vringh_bad("Unexpected %s desc", 38762306a36Sopenharmony_ci !wiov ? "writable" : "readable"); 38862306a36Sopenharmony_ci err = -EPROTO; 38962306a36Sopenharmony_ci goto fail; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci again: 39362306a36Sopenharmony_ci /* Make sure it's OK, and get offset. */ 39462306a36Sopenharmony_ci len = vringh32_to_cpu(vrh, desc.len); 39562306a36Sopenharmony_ci if (!rcheck(vrh, vringh64_to_cpu(vrh, desc.addr), &len, &range, 39662306a36Sopenharmony_ci getrange)) { 39762306a36Sopenharmony_ci err = -EINVAL; 39862306a36Sopenharmony_ci goto fail; 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci addr = (void *)(unsigned long)(vringh64_to_cpu(vrh, desc.addr) + 40162306a36Sopenharmony_ci range.offset); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (unlikely(iov->used == (iov->max_num & ~VRINGH_IOV_ALLOCATED))) { 40462306a36Sopenharmony_ci err = resize_iovec(iov, gfp); 40562306a36Sopenharmony_ci if (err) 40662306a36Sopenharmony_ci goto fail; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci iov->iov[iov->used].iov_base = addr; 41062306a36Sopenharmony_ci iov->iov[iov->used].iov_len = len; 41162306a36Sopenharmony_ci iov->used++; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (unlikely(len != vringh32_to_cpu(vrh, desc.len))) { 41462306a36Sopenharmony_ci desc.len = cpu_to_vringh32(vrh, 41562306a36Sopenharmony_ci vringh32_to_cpu(vrh, desc.len) - len); 41662306a36Sopenharmony_ci desc.addr = cpu_to_vringh64(vrh, 41762306a36Sopenharmony_ci vringh64_to_cpu(vrh, desc.addr) + len); 41862306a36Sopenharmony_ci goto again; 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (desc.flags & cpu_to_vringh16(vrh, VRING_DESC_F_NEXT)) { 42262306a36Sopenharmony_ci i = vringh16_to_cpu(vrh, desc.next); 42362306a36Sopenharmony_ci } else { 42462306a36Sopenharmony_ci /* Just in case we need to finish traversing above. */ 42562306a36Sopenharmony_ci if (unlikely(up_next > 0)) { 42662306a36Sopenharmony_ci i = return_from_indirect(vrh, &up_next, 42762306a36Sopenharmony_ci &descs, &desc_max); 42862306a36Sopenharmony_ci slow = false; 42962306a36Sopenharmony_ci indirect_count = 0; 43062306a36Sopenharmony_ci } else 43162306a36Sopenharmony_ci break; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (i >= desc_max) { 43562306a36Sopenharmony_ci vringh_bad("Chained index %u > %u", i, desc_max); 43662306a36Sopenharmony_ci err = -EINVAL; 43762306a36Sopenharmony_ci goto fail; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cifail: 44462306a36Sopenharmony_ci return err; 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic inline int __vringh_complete(struct vringh *vrh, 44862306a36Sopenharmony_ci const struct vring_used_elem *used, 44962306a36Sopenharmony_ci unsigned int num_used, 45062306a36Sopenharmony_ci int (*putu16)(const struct vringh *vrh, 45162306a36Sopenharmony_ci __virtio16 *p, u16 val), 45262306a36Sopenharmony_ci int (*putused)(const struct vringh *vrh, 45362306a36Sopenharmony_ci struct vring_used_elem *dst, 45462306a36Sopenharmony_ci const struct vring_used_elem 45562306a36Sopenharmony_ci *src, unsigned num)) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci struct vring_used *used_ring; 45862306a36Sopenharmony_ci int err; 45962306a36Sopenharmony_ci u16 used_idx, off; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci used_ring = vrh->vring.used; 46262306a36Sopenharmony_ci used_idx = vrh->last_used_idx + vrh->completed; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci off = used_idx % vrh->vring.num; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* Compiler knows num_used == 1 sometimes, hence extra check */ 46762306a36Sopenharmony_ci if (num_used > 1 && unlikely(off + num_used >= vrh->vring.num)) { 46862306a36Sopenharmony_ci u16 part = vrh->vring.num - off; 46962306a36Sopenharmony_ci err = putused(vrh, &used_ring->ring[off], used, part); 47062306a36Sopenharmony_ci if (!err) 47162306a36Sopenharmony_ci err = putused(vrh, &used_ring->ring[0], used + part, 47262306a36Sopenharmony_ci num_used - part); 47362306a36Sopenharmony_ci } else 47462306a36Sopenharmony_ci err = putused(vrh, &used_ring->ring[off], used, num_used); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (err) { 47762306a36Sopenharmony_ci vringh_bad("Failed to write %u used entries %u at %p", 47862306a36Sopenharmony_ci num_used, off, &used_ring->ring[off]); 47962306a36Sopenharmony_ci return err; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* Make sure buffer is written before we update index. */ 48362306a36Sopenharmony_ci virtio_wmb(vrh->weak_barriers); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci err = putu16(vrh, &vrh->vring.used->idx, used_idx + num_used); 48662306a36Sopenharmony_ci if (err) { 48762306a36Sopenharmony_ci vringh_bad("Failed to update used index at %p", 48862306a36Sopenharmony_ci &vrh->vring.used->idx); 48962306a36Sopenharmony_ci return err; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci vrh->completed += num_used; 49362306a36Sopenharmony_ci return 0; 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic inline int __vringh_need_notify(struct vringh *vrh, 49862306a36Sopenharmony_ci int (*getu16)(const struct vringh *vrh, 49962306a36Sopenharmony_ci u16 *val, 50062306a36Sopenharmony_ci const __virtio16 *p)) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci bool notify; 50362306a36Sopenharmony_ci u16 used_event; 50462306a36Sopenharmony_ci int err; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* Flush out used index update. This is paired with the 50762306a36Sopenharmony_ci * barrier that the Guest executes when enabling 50862306a36Sopenharmony_ci * interrupts. */ 50962306a36Sopenharmony_ci virtio_mb(vrh->weak_barriers); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* Old-style, without event indices. */ 51262306a36Sopenharmony_ci if (!vrh->event_indices) { 51362306a36Sopenharmony_ci u16 flags; 51462306a36Sopenharmony_ci err = getu16(vrh, &flags, &vrh->vring.avail->flags); 51562306a36Sopenharmony_ci if (err) { 51662306a36Sopenharmony_ci vringh_bad("Failed to get flags at %p", 51762306a36Sopenharmony_ci &vrh->vring.avail->flags); 51862306a36Sopenharmony_ci return err; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci return (!(flags & VRING_AVAIL_F_NO_INTERRUPT)); 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci /* Modern: we know when other side wants to know. */ 52462306a36Sopenharmony_ci err = getu16(vrh, &used_event, &vring_used_event(&vrh->vring)); 52562306a36Sopenharmony_ci if (err) { 52662306a36Sopenharmony_ci vringh_bad("Failed to get used event idx at %p", 52762306a36Sopenharmony_ci &vring_used_event(&vrh->vring)); 52862306a36Sopenharmony_ci return err; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* Just in case we added so many that we wrap. */ 53262306a36Sopenharmony_ci if (unlikely(vrh->completed > 0xffff)) 53362306a36Sopenharmony_ci notify = true; 53462306a36Sopenharmony_ci else 53562306a36Sopenharmony_ci notify = vring_need_event(used_event, 53662306a36Sopenharmony_ci vrh->last_used_idx + vrh->completed, 53762306a36Sopenharmony_ci vrh->last_used_idx); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci vrh->last_used_idx += vrh->completed; 54062306a36Sopenharmony_ci vrh->completed = 0; 54162306a36Sopenharmony_ci return notify; 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistatic inline bool __vringh_notify_enable(struct vringh *vrh, 54562306a36Sopenharmony_ci int (*getu16)(const struct vringh *vrh, 54662306a36Sopenharmony_ci u16 *val, const __virtio16 *p), 54762306a36Sopenharmony_ci int (*putu16)(const struct vringh *vrh, 54862306a36Sopenharmony_ci __virtio16 *p, u16 val)) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci u16 avail; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (!vrh->event_indices) { 55362306a36Sopenharmony_ci /* Old-school; update flags. */ 55462306a36Sopenharmony_ci if (putu16(vrh, &vrh->vring.used->flags, 0) != 0) { 55562306a36Sopenharmony_ci vringh_bad("Clearing used flags %p", 55662306a36Sopenharmony_ci &vrh->vring.used->flags); 55762306a36Sopenharmony_ci return true; 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci } else { 56062306a36Sopenharmony_ci if (putu16(vrh, &vring_avail_event(&vrh->vring), 56162306a36Sopenharmony_ci vrh->last_avail_idx) != 0) { 56262306a36Sopenharmony_ci vringh_bad("Updating avail event index %p", 56362306a36Sopenharmony_ci &vring_avail_event(&vrh->vring)); 56462306a36Sopenharmony_ci return true; 56562306a36Sopenharmony_ci } 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* They could have slipped one in as we were doing that: make 56962306a36Sopenharmony_ci * sure it's written, then check again. */ 57062306a36Sopenharmony_ci virtio_mb(vrh->weak_barriers); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (getu16(vrh, &avail, &vrh->vring.avail->idx) != 0) { 57362306a36Sopenharmony_ci vringh_bad("Failed to check avail idx at %p", 57462306a36Sopenharmony_ci &vrh->vring.avail->idx); 57562306a36Sopenharmony_ci return true; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* This is unlikely, so we just leave notifications enabled 57962306a36Sopenharmony_ci * (if we're using event_indices, we'll only get one 58062306a36Sopenharmony_ci * notification anyway). */ 58162306a36Sopenharmony_ci return avail == vrh->last_avail_idx; 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_cistatic inline void __vringh_notify_disable(struct vringh *vrh, 58562306a36Sopenharmony_ci int (*putu16)(const struct vringh *vrh, 58662306a36Sopenharmony_ci __virtio16 *p, u16 val)) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci if (!vrh->event_indices) { 58962306a36Sopenharmony_ci /* Old-school; update flags. */ 59062306a36Sopenharmony_ci if (putu16(vrh, &vrh->vring.used->flags, 59162306a36Sopenharmony_ci VRING_USED_F_NO_NOTIFY)) { 59262306a36Sopenharmony_ci vringh_bad("Setting used flags %p", 59362306a36Sopenharmony_ci &vrh->vring.used->flags); 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci/* Userspace access helpers: in this case, addresses are really userspace. */ 59962306a36Sopenharmony_cistatic inline int getu16_user(const struct vringh *vrh, u16 *val, const __virtio16 *p) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci __virtio16 v = 0; 60262306a36Sopenharmony_ci int rc = get_user(v, (__force __virtio16 __user *)p); 60362306a36Sopenharmony_ci *val = vringh16_to_cpu(vrh, v); 60462306a36Sopenharmony_ci return rc; 60562306a36Sopenharmony_ci} 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_cistatic inline int putu16_user(const struct vringh *vrh, __virtio16 *p, u16 val) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci __virtio16 v = cpu_to_vringh16(vrh, val); 61062306a36Sopenharmony_ci return put_user(v, (__force __virtio16 __user *)p); 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic inline int copydesc_user(const struct vringh *vrh, 61462306a36Sopenharmony_ci void *dst, const void *src, size_t len) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci return copy_from_user(dst, (__force void __user *)src, len) ? 61762306a36Sopenharmony_ci -EFAULT : 0; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic inline int putused_user(const struct vringh *vrh, 62162306a36Sopenharmony_ci struct vring_used_elem *dst, 62262306a36Sopenharmony_ci const struct vring_used_elem *src, 62362306a36Sopenharmony_ci unsigned int num) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci return copy_to_user((__force void __user *)dst, src, 62662306a36Sopenharmony_ci sizeof(*dst) * num) ? -EFAULT : 0; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic inline int xfer_from_user(const struct vringh *vrh, void *src, 63062306a36Sopenharmony_ci void *dst, size_t len) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci return copy_from_user(dst, (__force void __user *)src, len) ? 63362306a36Sopenharmony_ci -EFAULT : 0; 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic inline int xfer_to_user(const struct vringh *vrh, 63762306a36Sopenharmony_ci void *dst, void *src, size_t len) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci return copy_to_user((__force void __user *)dst, src, len) ? 64062306a36Sopenharmony_ci -EFAULT : 0; 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci/** 64462306a36Sopenharmony_ci * vringh_init_user - initialize a vringh for a userspace vring. 64562306a36Sopenharmony_ci * @vrh: the vringh to initialize. 64662306a36Sopenharmony_ci * @features: the feature bits for this ring. 64762306a36Sopenharmony_ci * @num: the number of elements. 64862306a36Sopenharmony_ci * @weak_barriers: true if we only need memory barriers, not I/O. 64962306a36Sopenharmony_ci * @desc: the userspace descriptor pointer. 65062306a36Sopenharmony_ci * @avail: the userspace avail pointer. 65162306a36Sopenharmony_ci * @used: the userspace used pointer. 65262306a36Sopenharmony_ci * 65362306a36Sopenharmony_ci * Returns an error if num is invalid: you should check pointers 65462306a36Sopenharmony_ci * yourself! 65562306a36Sopenharmony_ci */ 65662306a36Sopenharmony_ciint vringh_init_user(struct vringh *vrh, u64 features, 65762306a36Sopenharmony_ci unsigned int num, bool weak_barriers, 65862306a36Sopenharmony_ci vring_desc_t __user *desc, 65962306a36Sopenharmony_ci vring_avail_t __user *avail, 66062306a36Sopenharmony_ci vring_used_t __user *used) 66162306a36Sopenharmony_ci{ 66262306a36Sopenharmony_ci /* Sane power of 2 please! */ 66362306a36Sopenharmony_ci if (!num || num > 0xffff || (num & (num - 1))) { 66462306a36Sopenharmony_ci vringh_bad("Bad ring size %u", num); 66562306a36Sopenharmony_ci return -EINVAL; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci vrh->little_endian = (features & (1ULL << VIRTIO_F_VERSION_1)); 66962306a36Sopenharmony_ci vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX)); 67062306a36Sopenharmony_ci vrh->weak_barriers = weak_barriers; 67162306a36Sopenharmony_ci vrh->completed = 0; 67262306a36Sopenharmony_ci vrh->last_avail_idx = 0; 67362306a36Sopenharmony_ci vrh->last_used_idx = 0; 67462306a36Sopenharmony_ci vrh->vring.num = num; 67562306a36Sopenharmony_ci /* vring expects kernel addresses, but only used via accessors. */ 67662306a36Sopenharmony_ci vrh->vring.desc = (__force struct vring_desc *)desc; 67762306a36Sopenharmony_ci vrh->vring.avail = (__force struct vring_avail *)avail; 67862306a36Sopenharmony_ci vrh->vring.used = (__force struct vring_used *)used; 67962306a36Sopenharmony_ci return 0; 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_init_user); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci/** 68462306a36Sopenharmony_ci * vringh_getdesc_user - get next available descriptor from userspace ring. 68562306a36Sopenharmony_ci * @vrh: the userspace vring. 68662306a36Sopenharmony_ci * @riov: where to put the readable descriptors (or NULL) 68762306a36Sopenharmony_ci * @wiov: where to put the writable descriptors (or NULL) 68862306a36Sopenharmony_ci * @getrange: function to call to check ranges. 68962306a36Sopenharmony_ci * @head: head index we received, for passing to vringh_complete_user(). 69062306a36Sopenharmony_ci * 69162306a36Sopenharmony_ci * Returns 0 if there was no descriptor, 1 if there was, or -errno. 69262306a36Sopenharmony_ci * 69362306a36Sopenharmony_ci * Note that on error return, you can tell the difference between an 69462306a36Sopenharmony_ci * invalid ring and a single invalid descriptor: in the former case, 69562306a36Sopenharmony_ci * *head will be vrh->vring.num. You may be able to ignore an invalid 69662306a36Sopenharmony_ci * descriptor, but there's not much you can do with an invalid ring. 69762306a36Sopenharmony_ci * 69862306a36Sopenharmony_ci * Note that you can reuse riov and wiov with subsequent calls. Content is 69962306a36Sopenharmony_ci * overwritten and memory reallocated if more space is needed. 70062306a36Sopenharmony_ci * When you don't have to use riov and wiov anymore, you should clean up them 70162306a36Sopenharmony_ci * calling vringh_iov_cleanup() to release the memory, even on error! 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ciint vringh_getdesc_user(struct vringh *vrh, 70462306a36Sopenharmony_ci struct vringh_iov *riov, 70562306a36Sopenharmony_ci struct vringh_iov *wiov, 70662306a36Sopenharmony_ci bool (*getrange)(struct vringh *vrh, 70762306a36Sopenharmony_ci u64 addr, struct vringh_range *r), 70862306a36Sopenharmony_ci u16 *head) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci int err; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci *head = vrh->vring.num; 71362306a36Sopenharmony_ci err = __vringh_get_head(vrh, getu16_user, &vrh->last_avail_idx); 71462306a36Sopenharmony_ci if (err < 0) 71562306a36Sopenharmony_ci return err; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* Empty... */ 71862306a36Sopenharmony_ci if (err == vrh->vring.num) 71962306a36Sopenharmony_ci return 0; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* We need the layouts to be the identical for this to work */ 72262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct vringh_kiov) != sizeof(struct vringh_iov)); 72362306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct vringh_kiov, iov) != 72462306a36Sopenharmony_ci offsetof(struct vringh_iov, iov)); 72562306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct vringh_kiov, i) != 72662306a36Sopenharmony_ci offsetof(struct vringh_iov, i)); 72762306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct vringh_kiov, used) != 72862306a36Sopenharmony_ci offsetof(struct vringh_iov, used)); 72962306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct vringh_kiov, max_num) != 73062306a36Sopenharmony_ci offsetof(struct vringh_iov, max_num)); 73162306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct iovec) != sizeof(struct kvec)); 73262306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct iovec, iov_base) != 73362306a36Sopenharmony_ci offsetof(struct kvec, iov_base)); 73462306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct iovec, iov_len) != 73562306a36Sopenharmony_ci offsetof(struct kvec, iov_len)); 73662306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(((struct iovec *)NULL)->iov_base) 73762306a36Sopenharmony_ci != sizeof(((struct kvec *)NULL)->iov_base)); 73862306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(((struct iovec *)NULL)->iov_len) 73962306a36Sopenharmony_ci != sizeof(((struct kvec *)NULL)->iov_len)); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci *head = err; 74262306a36Sopenharmony_ci err = __vringh_iov(vrh, *head, (struct vringh_kiov *)riov, 74362306a36Sopenharmony_ci (struct vringh_kiov *)wiov, 74462306a36Sopenharmony_ci range_check, getrange, GFP_KERNEL, copydesc_user); 74562306a36Sopenharmony_ci if (err) 74662306a36Sopenharmony_ci return err; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci return 1; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_getdesc_user); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci/** 75362306a36Sopenharmony_ci * vringh_iov_pull_user - copy bytes from vring_iov. 75462306a36Sopenharmony_ci * @riov: the riov as passed to vringh_getdesc_user() (updated as we consume) 75562306a36Sopenharmony_ci * @dst: the place to copy. 75662306a36Sopenharmony_ci * @len: the maximum length to copy. 75762306a36Sopenharmony_ci * 75862306a36Sopenharmony_ci * Returns the bytes copied <= len or a negative errno. 75962306a36Sopenharmony_ci */ 76062306a36Sopenharmony_cissize_t vringh_iov_pull_user(struct vringh_iov *riov, void *dst, size_t len) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci return vringh_iov_xfer(NULL, (struct vringh_kiov *)riov, 76362306a36Sopenharmony_ci dst, len, xfer_from_user); 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_iov_pull_user); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci/** 76862306a36Sopenharmony_ci * vringh_iov_push_user - copy bytes into vring_iov. 76962306a36Sopenharmony_ci * @wiov: the wiov as passed to vringh_getdesc_user() (updated as we consume) 77062306a36Sopenharmony_ci * @src: the place to copy from. 77162306a36Sopenharmony_ci * @len: the maximum length to copy. 77262306a36Sopenharmony_ci * 77362306a36Sopenharmony_ci * Returns the bytes copied <= len or a negative errno. 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_cissize_t vringh_iov_push_user(struct vringh_iov *wiov, 77662306a36Sopenharmony_ci const void *src, size_t len) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci return vringh_iov_xfer(NULL, (struct vringh_kiov *)wiov, 77962306a36Sopenharmony_ci (void *)src, len, xfer_to_user); 78062306a36Sopenharmony_ci} 78162306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_iov_push_user); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci/** 78462306a36Sopenharmony_ci * vringh_abandon_user - we've decided not to handle the descriptor(s). 78562306a36Sopenharmony_ci * @vrh: the vring. 78662306a36Sopenharmony_ci * @num: the number of descriptors to put back (ie. num 78762306a36Sopenharmony_ci * vringh_get_user() to undo). 78862306a36Sopenharmony_ci * 78962306a36Sopenharmony_ci * The next vringh_get_user() will return the old descriptor(s) again. 79062306a36Sopenharmony_ci */ 79162306a36Sopenharmony_civoid vringh_abandon_user(struct vringh *vrh, unsigned int num) 79262306a36Sopenharmony_ci{ 79362306a36Sopenharmony_ci /* We only update vring_avail_event(vr) when we want to be notified, 79462306a36Sopenharmony_ci * so we haven't changed that yet. */ 79562306a36Sopenharmony_ci vrh->last_avail_idx -= num; 79662306a36Sopenharmony_ci} 79762306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_abandon_user); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci/** 80062306a36Sopenharmony_ci * vringh_complete_user - we've finished with descriptor, publish it. 80162306a36Sopenharmony_ci * @vrh: the vring. 80262306a36Sopenharmony_ci * @head: the head as filled in by vringh_getdesc_user. 80362306a36Sopenharmony_ci * @len: the length of data we have written. 80462306a36Sopenharmony_ci * 80562306a36Sopenharmony_ci * You should check vringh_need_notify_user() after one or more calls 80662306a36Sopenharmony_ci * to this function. 80762306a36Sopenharmony_ci */ 80862306a36Sopenharmony_ciint vringh_complete_user(struct vringh *vrh, u16 head, u32 len) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci struct vring_used_elem used; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci used.id = cpu_to_vringh32(vrh, head); 81362306a36Sopenharmony_ci used.len = cpu_to_vringh32(vrh, len); 81462306a36Sopenharmony_ci return __vringh_complete(vrh, &used, 1, putu16_user, putused_user); 81562306a36Sopenharmony_ci} 81662306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_complete_user); 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci/** 81962306a36Sopenharmony_ci * vringh_complete_multi_user - we've finished with many descriptors. 82062306a36Sopenharmony_ci * @vrh: the vring. 82162306a36Sopenharmony_ci * @used: the head, length pairs. 82262306a36Sopenharmony_ci * @num_used: the number of used elements. 82362306a36Sopenharmony_ci * 82462306a36Sopenharmony_ci * You should check vringh_need_notify_user() after one or more calls 82562306a36Sopenharmony_ci * to this function. 82662306a36Sopenharmony_ci */ 82762306a36Sopenharmony_ciint vringh_complete_multi_user(struct vringh *vrh, 82862306a36Sopenharmony_ci const struct vring_used_elem used[], 82962306a36Sopenharmony_ci unsigned num_used) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci return __vringh_complete(vrh, used, num_used, 83262306a36Sopenharmony_ci putu16_user, putused_user); 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_complete_multi_user); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci/** 83762306a36Sopenharmony_ci * vringh_notify_enable_user - we want to know if something changes. 83862306a36Sopenharmony_ci * @vrh: the vring. 83962306a36Sopenharmony_ci * 84062306a36Sopenharmony_ci * This always enables notifications, but returns false if there are 84162306a36Sopenharmony_ci * now more buffers available in the vring. 84262306a36Sopenharmony_ci */ 84362306a36Sopenharmony_cibool vringh_notify_enable_user(struct vringh *vrh) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci return __vringh_notify_enable(vrh, getu16_user, putu16_user); 84662306a36Sopenharmony_ci} 84762306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_notify_enable_user); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci/** 85062306a36Sopenharmony_ci * vringh_notify_disable_user - don't tell us if something changes. 85162306a36Sopenharmony_ci * @vrh: the vring. 85262306a36Sopenharmony_ci * 85362306a36Sopenharmony_ci * This is our normal running state: we disable and then only enable when 85462306a36Sopenharmony_ci * we're going to sleep. 85562306a36Sopenharmony_ci */ 85662306a36Sopenharmony_civoid vringh_notify_disable_user(struct vringh *vrh) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci __vringh_notify_disable(vrh, putu16_user); 85962306a36Sopenharmony_ci} 86062306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_notify_disable_user); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci/** 86362306a36Sopenharmony_ci * vringh_need_notify_user - must we tell the other side about used buffers? 86462306a36Sopenharmony_ci * @vrh: the vring we've called vringh_complete_user() on. 86562306a36Sopenharmony_ci * 86662306a36Sopenharmony_ci * Returns -errno or 0 if we don't need to tell the other side, 1 if we do. 86762306a36Sopenharmony_ci */ 86862306a36Sopenharmony_ciint vringh_need_notify_user(struct vringh *vrh) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci return __vringh_need_notify(vrh, getu16_user); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_need_notify_user); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci/* Kernelspace access helpers. */ 87562306a36Sopenharmony_cistatic inline int getu16_kern(const struct vringh *vrh, 87662306a36Sopenharmony_ci u16 *val, const __virtio16 *p) 87762306a36Sopenharmony_ci{ 87862306a36Sopenharmony_ci *val = vringh16_to_cpu(vrh, READ_ONCE(*p)); 87962306a36Sopenharmony_ci return 0; 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cistatic inline int putu16_kern(const struct vringh *vrh, __virtio16 *p, u16 val) 88362306a36Sopenharmony_ci{ 88462306a36Sopenharmony_ci WRITE_ONCE(*p, cpu_to_vringh16(vrh, val)); 88562306a36Sopenharmony_ci return 0; 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic inline int copydesc_kern(const struct vringh *vrh, 88962306a36Sopenharmony_ci void *dst, const void *src, size_t len) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci memcpy(dst, src, len); 89262306a36Sopenharmony_ci return 0; 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_cistatic inline int putused_kern(const struct vringh *vrh, 89662306a36Sopenharmony_ci struct vring_used_elem *dst, 89762306a36Sopenharmony_ci const struct vring_used_elem *src, 89862306a36Sopenharmony_ci unsigned int num) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci memcpy(dst, src, num * sizeof(*dst)); 90162306a36Sopenharmony_ci return 0; 90262306a36Sopenharmony_ci} 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_cistatic inline int xfer_kern(const struct vringh *vrh, void *src, 90562306a36Sopenharmony_ci void *dst, size_t len) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci memcpy(dst, src, len); 90862306a36Sopenharmony_ci return 0; 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_cistatic inline int kern_xfer(const struct vringh *vrh, void *dst, 91262306a36Sopenharmony_ci void *src, size_t len) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci memcpy(dst, src, len); 91562306a36Sopenharmony_ci return 0; 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci/** 91962306a36Sopenharmony_ci * vringh_init_kern - initialize a vringh for a kernelspace vring. 92062306a36Sopenharmony_ci * @vrh: the vringh to initialize. 92162306a36Sopenharmony_ci * @features: the feature bits for this ring. 92262306a36Sopenharmony_ci * @num: the number of elements. 92362306a36Sopenharmony_ci * @weak_barriers: true if we only need memory barriers, not I/O. 92462306a36Sopenharmony_ci * @desc: the userspace descriptor pointer. 92562306a36Sopenharmony_ci * @avail: the userspace avail pointer. 92662306a36Sopenharmony_ci * @used: the userspace used pointer. 92762306a36Sopenharmony_ci * 92862306a36Sopenharmony_ci * Returns an error if num is invalid. 92962306a36Sopenharmony_ci */ 93062306a36Sopenharmony_ciint vringh_init_kern(struct vringh *vrh, u64 features, 93162306a36Sopenharmony_ci unsigned int num, bool weak_barriers, 93262306a36Sopenharmony_ci struct vring_desc *desc, 93362306a36Sopenharmony_ci struct vring_avail *avail, 93462306a36Sopenharmony_ci struct vring_used *used) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci /* Sane power of 2 please! */ 93762306a36Sopenharmony_ci if (!num || num > 0xffff || (num & (num - 1))) { 93862306a36Sopenharmony_ci vringh_bad("Bad ring size %u", num); 93962306a36Sopenharmony_ci return -EINVAL; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci vrh->little_endian = (features & (1ULL << VIRTIO_F_VERSION_1)); 94362306a36Sopenharmony_ci vrh->event_indices = (features & (1 << VIRTIO_RING_F_EVENT_IDX)); 94462306a36Sopenharmony_ci vrh->weak_barriers = weak_barriers; 94562306a36Sopenharmony_ci vrh->completed = 0; 94662306a36Sopenharmony_ci vrh->last_avail_idx = 0; 94762306a36Sopenharmony_ci vrh->last_used_idx = 0; 94862306a36Sopenharmony_ci vrh->vring.num = num; 94962306a36Sopenharmony_ci vrh->vring.desc = desc; 95062306a36Sopenharmony_ci vrh->vring.avail = avail; 95162306a36Sopenharmony_ci vrh->vring.used = used; 95262306a36Sopenharmony_ci return 0; 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_init_kern); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci/** 95762306a36Sopenharmony_ci * vringh_getdesc_kern - get next available descriptor from kernelspace ring. 95862306a36Sopenharmony_ci * @vrh: the kernelspace vring. 95962306a36Sopenharmony_ci * @riov: where to put the readable descriptors (or NULL) 96062306a36Sopenharmony_ci * @wiov: where to put the writable descriptors (or NULL) 96162306a36Sopenharmony_ci * @head: head index we received, for passing to vringh_complete_kern(). 96262306a36Sopenharmony_ci * @gfp: flags for allocating larger riov/wiov. 96362306a36Sopenharmony_ci * 96462306a36Sopenharmony_ci * Returns 0 if there was no descriptor, 1 if there was, or -errno. 96562306a36Sopenharmony_ci * 96662306a36Sopenharmony_ci * Note that on error return, you can tell the difference between an 96762306a36Sopenharmony_ci * invalid ring and a single invalid descriptor: in the former case, 96862306a36Sopenharmony_ci * *head will be vrh->vring.num. You may be able to ignore an invalid 96962306a36Sopenharmony_ci * descriptor, but there's not much you can do with an invalid ring. 97062306a36Sopenharmony_ci * 97162306a36Sopenharmony_ci * Note that you can reuse riov and wiov with subsequent calls. Content is 97262306a36Sopenharmony_ci * overwritten and memory reallocated if more space is needed. 97362306a36Sopenharmony_ci * When you don't have to use riov and wiov anymore, you should clean up them 97462306a36Sopenharmony_ci * calling vringh_kiov_cleanup() to release the memory, even on error! 97562306a36Sopenharmony_ci */ 97662306a36Sopenharmony_ciint vringh_getdesc_kern(struct vringh *vrh, 97762306a36Sopenharmony_ci struct vringh_kiov *riov, 97862306a36Sopenharmony_ci struct vringh_kiov *wiov, 97962306a36Sopenharmony_ci u16 *head, 98062306a36Sopenharmony_ci gfp_t gfp) 98162306a36Sopenharmony_ci{ 98262306a36Sopenharmony_ci int err; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci err = __vringh_get_head(vrh, getu16_kern, &vrh->last_avail_idx); 98562306a36Sopenharmony_ci if (err < 0) 98662306a36Sopenharmony_ci return err; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci /* Empty... */ 98962306a36Sopenharmony_ci if (err == vrh->vring.num) 99062306a36Sopenharmony_ci return 0; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci *head = err; 99362306a36Sopenharmony_ci err = __vringh_iov(vrh, *head, riov, wiov, no_range_check, NULL, 99462306a36Sopenharmony_ci gfp, copydesc_kern); 99562306a36Sopenharmony_ci if (err) 99662306a36Sopenharmony_ci return err; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci return 1; 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_getdesc_kern); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci/** 100362306a36Sopenharmony_ci * vringh_iov_pull_kern - copy bytes from vring_iov. 100462306a36Sopenharmony_ci * @riov: the riov as passed to vringh_getdesc_kern() (updated as we consume) 100562306a36Sopenharmony_ci * @dst: the place to copy. 100662306a36Sopenharmony_ci * @len: the maximum length to copy. 100762306a36Sopenharmony_ci * 100862306a36Sopenharmony_ci * Returns the bytes copied <= len or a negative errno. 100962306a36Sopenharmony_ci */ 101062306a36Sopenharmony_cissize_t vringh_iov_pull_kern(struct vringh_kiov *riov, void *dst, size_t len) 101162306a36Sopenharmony_ci{ 101262306a36Sopenharmony_ci return vringh_iov_xfer(NULL, riov, dst, len, xfer_kern); 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_iov_pull_kern); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci/** 101762306a36Sopenharmony_ci * vringh_iov_push_kern - copy bytes into vring_iov. 101862306a36Sopenharmony_ci * @wiov: the wiov as passed to vringh_getdesc_kern() (updated as we consume) 101962306a36Sopenharmony_ci * @src: the place to copy from. 102062306a36Sopenharmony_ci * @len: the maximum length to copy. 102162306a36Sopenharmony_ci * 102262306a36Sopenharmony_ci * Returns the bytes copied <= len or a negative errno. 102362306a36Sopenharmony_ci */ 102462306a36Sopenharmony_cissize_t vringh_iov_push_kern(struct vringh_kiov *wiov, 102562306a36Sopenharmony_ci const void *src, size_t len) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci return vringh_iov_xfer(NULL, wiov, (void *)src, len, kern_xfer); 102862306a36Sopenharmony_ci} 102962306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_iov_push_kern); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci/** 103262306a36Sopenharmony_ci * vringh_abandon_kern - we've decided not to handle the descriptor(s). 103362306a36Sopenharmony_ci * @vrh: the vring. 103462306a36Sopenharmony_ci * @num: the number of descriptors to put back (ie. num 103562306a36Sopenharmony_ci * vringh_get_kern() to undo). 103662306a36Sopenharmony_ci * 103762306a36Sopenharmony_ci * The next vringh_get_kern() will return the old descriptor(s) again. 103862306a36Sopenharmony_ci */ 103962306a36Sopenharmony_civoid vringh_abandon_kern(struct vringh *vrh, unsigned int num) 104062306a36Sopenharmony_ci{ 104162306a36Sopenharmony_ci /* We only update vring_avail_event(vr) when we want to be notified, 104262306a36Sopenharmony_ci * so we haven't changed that yet. */ 104362306a36Sopenharmony_ci vrh->last_avail_idx -= num; 104462306a36Sopenharmony_ci} 104562306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_abandon_kern); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci/** 104862306a36Sopenharmony_ci * vringh_complete_kern - we've finished with descriptor, publish it. 104962306a36Sopenharmony_ci * @vrh: the vring. 105062306a36Sopenharmony_ci * @head: the head as filled in by vringh_getdesc_kern. 105162306a36Sopenharmony_ci * @len: the length of data we have written. 105262306a36Sopenharmony_ci * 105362306a36Sopenharmony_ci * You should check vringh_need_notify_kern() after one or more calls 105462306a36Sopenharmony_ci * to this function. 105562306a36Sopenharmony_ci */ 105662306a36Sopenharmony_ciint vringh_complete_kern(struct vringh *vrh, u16 head, u32 len) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci struct vring_used_elem used; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci used.id = cpu_to_vringh32(vrh, head); 106162306a36Sopenharmony_ci used.len = cpu_to_vringh32(vrh, len); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci return __vringh_complete(vrh, &used, 1, putu16_kern, putused_kern); 106462306a36Sopenharmony_ci} 106562306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_complete_kern); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci/** 106862306a36Sopenharmony_ci * vringh_notify_enable_kern - we want to know if something changes. 106962306a36Sopenharmony_ci * @vrh: the vring. 107062306a36Sopenharmony_ci * 107162306a36Sopenharmony_ci * This always enables notifications, but returns false if there are 107262306a36Sopenharmony_ci * now more buffers available in the vring. 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_cibool vringh_notify_enable_kern(struct vringh *vrh) 107562306a36Sopenharmony_ci{ 107662306a36Sopenharmony_ci return __vringh_notify_enable(vrh, getu16_kern, putu16_kern); 107762306a36Sopenharmony_ci} 107862306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_notify_enable_kern); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci/** 108162306a36Sopenharmony_ci * vringh_notify_disable_kern - don't tell us if something changes. 108262306a36Sopenharmony_ci * @vrh: the vring. 108362306a36Sopenharmony_ci * 108462306a36Sopenharmony_ci * This is our normal running state: we disable and then only enable when 108562306a36Sopenharmony_ci * we're going to sleep. 108662306a36Sopenharmony_ci */ 108762306a36Sopenharmony_civoid vringh_notify_disable_kern(struct vringh *vrh) 108862306a36Sopenharmony_ci{ 108962306a36Sopenharmony_ci __vringh_notify_disable(vrh, putu16_kern); 109062306a36Sopenharmony_ci} 109162306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_notify_disable_kern); 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci/** 109462306a36Sopenharmony_ci * vringh_need_notify_kern - must we tell the other side about used buffers? 109562306a36Sopenharmony_ci * @vrh: the vring we've called vringh_complete_kern() on. 109662306a36Sopenharmony_ci * 109762306a36Sopenharmony_ci * Returns -errno or 0 if we don't need to tell the other side, 1 if we do. 109862306a36Sopenharmony_ci */ 109962306a36Sopenharmony_ciint vringh_need_notify_kern(struct vringh *vrh) 110062306a36Sopenharmony_ci{ 110162306a36Sopenharmony_ci return __vringh_need_notify(vrh, getu16_kern); 110262306a36Sopenharmony_ci} 110362306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_need_notify_kern); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_VHOST_IOTLB) 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_cistruct iotlb_vec { 110862306a36Sopenharmony_ci union { 110962306a36Sopenharmony_ci struct iovec *iovec; 111062306a36Sopenharmony_ci struct bio_vec *bvec; 111162306a36Sopenharmony_ci } iov; 111262306a36Sopenharmony_ci size_t count; 111362306a36Sopenharmony_ci}; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_cistatic int iotlb_translate(const struct vringh *vrh, 111662306a36Sopenharmony_ci u64 addr, u64 len, u64 *translated, 111762306a36Sopenharmony_ci struct iotlb_vec *ivec, u32 perm) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci struct vhost_iotlb_map *map; 112062306a36Sopenharmony_ci struct vhost_iotlb *iotlb = vrh->iotlb; 112162306a36Sopenharmony_ci int ret = 0; 112262306a36Sopenharmony_ci u64 s = 0, last = addr + len - 1; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci spin_lock(vrh->iotlb_lock); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci while (len > s) { 112762306a36Sopenharmony_ci uintptr_t io_addr; 112862306a36Sopenharmony_ci size_t io_len; 112962306a36Sopenharmony_ci u64 size; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci if (unlikely(ret >= ivec->count)) { 113262306a36Sopenharmony_ci ret = -ENOBUFS; 113362306a36Sopenharmony_ci break; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci map = vhost_iotlb_itree_first(iotlb, addr, last); 113762306a36Sopenharmony_ci if (!map || map->start > addr) { 113862306a36Sopenharmony_ci ret = -EINVAL; 113962306a36Sopenharmony_ci break; 114062306a36Sopenharmony_ci } else if (!(map->perm & perm)) { 114162306a36Sopenharmony_ci ret = -EPERM; 114262306a36Sopenharmony_ci break; 114362306a36Sopenharmony_ci } 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci size = map->size - addr + map->start; 114662306a36Sopenharmony_ci io_len = min(len - s, size); 114762306a36Sopenharmony_ci io_addr = map->addr - map->start + addr; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci if (vrh->use_va) { 115062306a36Sopenharmony_ci struct iovec *iovec = ivec->iov.iovec; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci iovec[ret].iov_len = io_len; 115362306a36Sopenharmony_ci iovec[ret].iov_base = (void __user *)io_addr; 115462306a36Sopenharmony_ci } else { 115562306a36Sopenharmony_ci u64 pfn = io_addr >> PAGE_SHIFT; 115662306a36Sopenharmony_ci struct bio_vec *bvec = ivec->iov.bvec; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci bvec_set_page(&bvec[ret], pfn_to_page(pfn), io_len, 115962306a36Sopenharmony_ci io_addr & (PAGE_SIZE - 1)); 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci s += size; 116362306a36Sopenharmony_ci addr += size; 116462306a36Sopenharmony_ci ++ret; 116562306a36Sopenharmony_ci } 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci spin_unlock(vrh->iotlb_lock); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci if (translated) 117062306a36Sopenharmony_ci *translated = min(len, s); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci return ret; 117362306a36Sopenharmony_ci} 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci#define IOTLB_IOV_STRIDE 16 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_cistatic inline int copy_from_iotlb(const struct vringh *vrh, void *dst, 117862306a36Sopenharmony_ci void *src, size_t len) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci struct iotlb_vec ivec; 118162306a36Sopenharmony_ci union { 118262306a36Sopenharmony_ci struct iovec iovec[IOTLB_IOV_STRIDE]; 118362306a36Sopenharmony_ci struct bio_vec bvec[IOTLB_IOV_STRIDE]; 118462306a36Sopenharmony_ci } iov; 118562306a36Sopenharmony_ci u64 total_translated = 0; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci ivec.iov.iovec = iov.iovec; 118862306a36Sopenharmony_ci ivec.count = IOTLB_IOV_STRIDE; 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci while (total_translated < len) { 119162306a36Sopenharmony_ci struct iov_iter iter; 119262306a36Sopenharmony_ci u64 translated; 119362306a36Sopenharmony_ci int ret; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci ret = iotlb_translate(vrh, (u64)(uintptr_t)src, 119662306a36Sopenharmony_ci len - total_translated, &translated, 119762306a36Sopenharmony_ci &ivec, VHOST_MAP_RO); 119862306a36Sopenharmony_ci if (ret == -ENOBUFS) 119962306a36Sopenharmony_ci ret = IOTLB_IOV_STRIDE; 120062306a36Sopenharmony_ci else if (ret < 0) 120162306a36Sopenharmony_ci return ret; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci if (vrh->use_va) { 120462306a36Sopenharmony_ci iov_iter_init(&iter, ITER_SOURCE, ivec.iov.iovec, ret, 120562306a36Sopenharmony_ci translated); 120662306a36Sopenharmony_ci } else { 120762306a36Sopenharmony_ci iov_iter_bvec(&iter, ITER_SOURCE, ivec.iov.bvec, ret, 120862306a36Sopenharmony_ci translated); 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci ret = copy_from_iter(dst, translated, &iter); 121262306a36Sopenharmony_ci if (ret < 0) 121362306a36Sopenharmony_ci return ret; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci src += translated; 121662306a36Sopenharmony_ci dst += translated; 121762306a36Sopenharmony_ci total_translated += translated; 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci return total_translated; 122162306a36Sopenharmony_ci} 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_cistatic inline int copy_to_iotlb(const struct vringh *vrh, void *dst, 122462306a36Sopenharmony_ci void *src, size_t len) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci struct iotlb_vec ivec; 122762306a36Sopenharmony_ci union { 122862306a36Sopenharmony_ci struct iovec iovec[IOTLB_IOV_STRIDE]; 122962306a36Sopenharmony_ci struct bio_vec bvec[IOTLB_IOV_STRIDE]; 123062306a36Sopenharmony_ci } iov; 123162306a36Sopenharmony_ci u64 total_translated = 0; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci ivec.iov.iovec = iov.iovec; 123462306a36Sopenharmony_ci ivec.count = IOTLB_IOV_STRIDE; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci while (total_translated < len) { 123762306a36Sopenharmony_ci struct iov_iter iter; 123862306a36Sopenharmony_ci u64 translated; 123962306a36Sopenharmony_ci int ret; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci ret = iotlb_translate(vrh, (u64)(uintptr_t)dst, 124262306a36Sopenharmony_ci len - total_translated, &translated, 124362306a36Sopenharmony_ci &ivec, VHOST_MAP_WO); 124462306a36Sopenharmony_ci if (ret == -ENOBUFS) 124562306a36Sopenharmony_ci ret = IOTLB_IOV_STRIDE; 124662306a36Sopenharmony_ci else if (ret < 0) 124762306a36Sopenharmony_ci return ret; 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci if (vrh->use_va) { 125062306a36Sopenharmony_ci iov_iter_init(&iter, ITER_DEST, ivec.iov.iovec, ret, 125162306a36Sopenharmony_ci translated); 125262306a36Sopenharmony_ci } else { 125362306a36Sopenharmony_ci iov_iter_bvec(&iter, ITER_DEST, ivec.iov.bvec, ret, 125462306a36Sopenharmony_ci translated); 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci ret = copy_to_iter(src, translated, &iter); 125862306a36Sopenharmony_ci if (ret < 0) 125962306a36Sopenharmony_ci return ret; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci src += translated; 126262306a36Sopenharmony_ci dst += translated; 126362306a36Sopenharmony_ci total_translated += translated; 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci return total_translated; 126762306a36Sopenharmony_ci} 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_cistatic inline int getu16_iotlb(const struct vringh *vrh, 127062306a36Sopenharmony_ci u16 *val, const __virtio16 *p) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci struct iotlb_vec ivec; 127362306a36Sopenharmony_ci union { 127462306a36Sopenharmony_ci struct iovec iovec[1]; 127562306a36Sopenharmony_ci struct bio_vec bvec[1]; 127662306a36Sopenharmony_ci } iov; 127762306a36Sopenharmony_ci __virtio16 tmp; 127862306a36Sopenharmony_ci int ret; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci ivec.iov.iovec = iov.iovec; 128162306a36Sopenharmony_ci ivec.count = 1; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci /* Atomic read is needed for getu16 */ 128462306a36Sopenharmony_ci ret = iotlb_translate(vrh, (u64)(uintptr_t)p, sizeof(*p), 128562306a36Sopenharmony_ci NULL, &ivec, VHOST_MAP_RO); 128662306a36Sopenharmony_ci if (ret < 0) 128762306a36Sopenharmony_ci return ret; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci if (vrh->use_va) { 129062306a36Sopenharmony_ci ret = __get_user(tmp, (__virtio16 __user *)ivec.iov.iovec[0].iov_base); 129162306a36Sopenharmony_ci if (ret) 129262306a36Sopenharmony_ci return ret; 129362306a36Sopenharmony_ci } else { 129462306a36Sopenharmony_ci void *kaddr = kmap_local_page(ivec.iov.bvec[0].bv_page); 129562306a36Sopenharmony_ci void *from = kaddr + ivec.iov.bvec[0].bv_offset; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci tmp = READ_ONCE(*(__virtio16 *)from); 129862306a36Sopenharmony_ci kunmap_local(kaddr); 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci *val = vringh16_to_cpu(vrh, tmp); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci return 0; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_cistatic inline int putu16_iotlb(const struct vringh *vrh, 130762306a36Sopenharmony_ci __virtio16 *p, u16 val) 130862306a36Sopenharmony_ci{ 130962306a36Sopenharmony_ci struct iotlb_vec ivec; 131062306a36Sopenharmony_ci union { 131162306a36Sopenharmony_ci struct iovec iovec; 131262306a36Sopenharmony_ci struct bio_vec bvec; 131362306a36Sopenharmony_ci } iov; 131462306a36Sopenharmony_ci __virtio16 tmp; 131562306a36Sopenharmony_ci int ret; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci ivec.iov.iovec = &iov.iovec; 131862306a36Sopenharmony_ci ivec.count = 1; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci /* Atomic write is needed for putu16 */ 132162306a36Sopenharmony_ci ret = iotlb_translate(vrh, (u64)(uintptr_t)p, sizeof(*p), 132262306a36Sopenharmony_ci NULL, &ivec, VHOST_MAP_RO); 132362306a36Sopenharmony_ci if (ret < 0) 132462306a36Sopenharmony_ci return ret; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci tmp = cpu_to_vringh16(vrh, val); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci if (vrh->use_va) { 132962306a36Sopenharmony_ci ret = __put_user(tmp, (__virtio16 __user *)ivec.iov.iovec[0].iov_base); 133062306a36Sopenharmony_ci if (ret) 133162306a36Sopenharmony_ci return ret; 133262306a36Sopenharmony_ci } else { 133362306a36Sopenharmony_ci void *kaddr = kmap_local_page(ivec.iov.bvec[0].bv_page); 133462306a36Sopenharmony_ci void *to = kaddr + ivec.iov.bvec[0].bv_offset; 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci WRITE_ONCE(*(__virtio16 *)to, tmp); 133762306a36Sopenharmony_ci kunmap_local(kaddr); 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci return 0; 134162306a36Sopenharmony_ci} 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_cistatic inline int copydesc_iotlb(const struct vringh *vrh, 134462306a36Sopenharmony_ci void *dst, const void *src, size_t len) 134562306a36Sopenharmony_ci{ 134662306a36Sopenharmony_ci int ret; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci ret = copy_from_iotlb(vrh, dst, (void *)src, len); 134962306a36Sopenharmony_ci if (ret != len) 135062306a36Sopenharmony_ci return -EFAULT; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci return 0; 135362306a36Sopenharmony_ci} 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_cistatic inline int xfer_from_iotlb(const struct vringh *vrh, void *src, 135662306a36Sopenharmony_ci void *dst, size_t len) 135762306a36Sopenharmony_ci{ 135862306a36Sopenharmony_ci int ret; 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci ret = copy_from_iotlb(vrh, dst, src, len); 136162306a36Sopenharmony_ci if (ret != len) 136262306a36Sopenharmony_ci return -EFAULT; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci return 0; 136562306a36Sopenharmony_ci} 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_cistatic inline int xfer_to_iotlb(const struct vringh *vrh, 136862306a36Sopenharmony_ci void *dst, void *src, size_t len) 136962306a36Sopenharmony_ci{ 137062306a36Sopenharmony_ci int ret; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci ret = copy_to_iotlb(vrh, dst, src, len); 137362306a36Sopenharmony_ci if (ret != len) 137462306a36Sopenharmony_ci return -EFAULT; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci return 0; 137762306a36Sopenharmony_ci} 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_cistatic inline int putused_iotlb(const struct vringh *vrh, 138062306a36Sopenharmony_ci struct vring_used_elem *dst, 138162306a36Sopenharmony_ci const struct vring_used_elem *src, 138262306a36Sopenharmony_ci unsigned int num) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci int size = num * sizeof(*dst); 138562306a36Sopenharmony_ci int ret; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci ret = copy_to_iotlb(vrh, dst, (void *)src, num * sizeof(*dst)); 138862306a36Sopenharmony_ci if (ret != size) 138962306a36Sopenharmony_ci return -EFAULT; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci return 0; 139262306a36Sopenharmony_ci} 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci/** 139562306a36Sopenharmony_ci * vringh_init_iotlb - initialize a vringh for a ring with IOTLB. 139662306a36Sopenharmony_ci * @vrh: the vringh to initialize. 139762306a36Sopenharmony_ci * @features: the feature bits for this ring. 139862306a36Sopenharmony_ci * @num: the number of elements. 139962306a36Sopenharmony_ci * @weak_barriers: true if we only need memory barriers, not I/O. 140062306a36Sopenharmony_ci * @desc: the userspace descriptor pointer. 140162306a36Sopenharmony_ci * @avail: the userspace avail pointer. 140262306a36Sopenharmony_ci * @used: the userspace used pointer. 140362306a36Sopenharmony_ci * 140462306a36Sopenharmony_ci * Returns an error if num is invalid. 140562306a36Sopenharmony_ci */ 140662306a36Sopenharmony_ciint vringh_init_iotlb(struct vringh *vrh, u64 features, 140762306a36Sopenharmony_ci unsigned int num, bool weak_barriers, 140862306a36Sopenharmony_ci struct vring_desc *desc, 140962306a36Sopenharmony_ci struct vring_avail *avail, 141062306a36Sopenharmony_ci struct vring_used *used) 141162306a36Sopenharmony_ci{ 141262306a36Sopenharmony_ci vrh->use_va = false; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci return vringh_init_kern(vrh, features, num, weak_barriers, 141562306a36Sopenharmony_ci desc, avail, used); 141662306a36Sopenharmony_ci} 141762306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_init_iotlb); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci/** 142062306a36Sopenharmony_ci * vringh_init_iotlb_va - initialize a vringh for a ring with IOTLB containing 142162306a36Sopenharmony_ci * user VA. 142262306a36Sopenharmony_ci * @vrh: the vringh to initialize. 142362306a36Sopenharmony_ci * @features: the feature bits for this ring. 142462306a36Sopenharmony_ci * @num: the number of elements. 142562306a36Sopenharmony_ci * @weak_barriers: true if we only need memory barriers, not I/O. 142662306a36Sopenharmony_ci * @desc: the userspace descriptor pointer. 142762306a36Sopenharmony_ci * @avail: the userspace avail pointer. 142862306a36Sopenharmony_ci * @used: the userspace used pointer. 142962306a36Sopenharmony_ci * 143062306a36Sopenharmony_ci * Returns an error if num is invalid. 143162306a36Sopenharmony_ci */ 143262306a36Sopenharmony_ciint vringh_init_iotlb_va(struct vringh *vrh, u64 features, 143362306a36Sopenharmony_ci unsigned int num, bool weak_barriers, 143462306a36Sopenharmony_ci struct vring_desc *desc, 143562306a36Sopenharmony_ci struct vring_avail *avail, 143662306a36Sopenharmony_ci struct vring_used *used) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci vrh->use_va = true; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci return vringh_init_kern(vrh, features, num, weak_barriers, 144162306a36Sopenharmony_ci desc, avail, used); 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_init_iotlb_va); 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci/** 144662306a36Sopenharmony_ci * vringh_set_iotlb - initialize a vringh for a ring with IOTLB. 144762306a36Sopenharmony_ci * @vrh: the vring 144862306a36Sopenharmony_ci * @iotlb: iotlb associated with this vring 144962306a36Sopenharmony_ci * @iotlb_lock: spinlock to synchronize the iotlb accesses 145062306a36Sopenharmony_ci */ 145162306a36Sopenharmony_civoid vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb, 145262306a36Sopenharmony_ci spinlock_t *iotlb_lock) 145362306a36Sopenharmony_ci{ 145462306a36Sopenharmony_ci vrh->iotlb = iotlb; 145562306a36Sopenharmony_ci vrh->iotlb_lock = iotlb_lock; 145662306a36Sopenharmony_ci} 145762306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_set_iotlb); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci/** 146062306a36Sopenharmony_ci * vringh_getdesc_iotlb - get next available descriptor from ring with 146162306a36Sopenharmony_ci * IOTLB. 146262306a36Sopenharmony_ci * @vrh: the kernelspace vring. 146362306a36Sopenharmony_ci * @riov: where to put the readable descriptors (or NULL) 146462306a36Sopenharmony_ci * @wiov: where to put the writable descriptors (or NULL) 146562306a36Sopenharmony_ci * @head: head index we received, for passing to vringh_complete_iotlb(). 146662306a36Sopenharmony_ci * @gfp: flags for allocating larger riov/wiov. 146762306a36Sopenharmony_ci * 146862306a36Sopenharmony_ci * Returns 0 if there was no descriptor, 1 if there was, or -errno. 146962306a36Sopenharmony_ci * 147062306a36Sopenharmony_ci * Note that on error return, you can tell the difference between an 147162306a36Sopenharmony_ci * invalid ring and a single invalid descriptor: in the former case, 147262306a36Sopenharmony_ci * *head will be vrh->vring.num. You may be able to ignore an invalid 147362306a36Sopenharmony_ci * descriptor, but there's not much you can do with an invalid ring. 147462306a36Sopenharmony_ci * 147562306a36Sopenharmony_ci * Note that you can reuse riov and wiov with subsequent calls. Content is 147662306a36Sopenharmony_ci * overwritten and memory reallocated if more space is needed. 147762306a36Sopenharmony_ci * When you don't have to use riov and wiov anymore, you should clean up them 147862306a36Sopenharmony_ci * calling vringh_kiov_cleanup() to release the memory, even on error! 147962306a36Sopenharmony_ci */ 148062306a36Sopenharmony_ciint vringh_getdesc_iotlb(struct vringh *vrh, 148162306a36Sopenharmony_ci struct vringh_kiov *riov, 148262306a36Sopenharmony_ci struct vringh_kiov *wiov, 148362306a36Sopenharmony_ci u16 *head, 148462306a36Sopenharmony_ci gfp_t gfp) 148562306a36Sopenharmony_ci{ 148662306a36Sopenharmony_ci int err; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci err = __vringh_get_head(vrh, getu16_iotlb, &vrh->last_avail_idx); 148962306a36Sopenharmony_ci if (err < 0) 149062306a36Sopenharmony_ci return err; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci /* Empty... */ 149362306a36Sopenharmony_ci if (err == vrh->vring.num) 149462306a36Sopenharmony_ci return 0; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci *head = err; 149762306a36Sopenharmony_ci err = __vringh_iov(vrh, *head, riov, wiov, no_range_check, NULL, 149862306a36Sopenharmony_ci gfp, copydesc_iotlb); 149962306a36Sopenharmony_ci if (err) 150062306a36Sopenharmony_ci return err; 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci return 1; 150362306a36Sopenharmony_ci} 150462306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_getdesc_iotlb); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci/** 150762306a36Sopenharmony_ci * vringh_iov_pull_iotlb - copy bytes from vring_iov. 150862306a36Sopenharmony_ci * @vrh: the vring. 150962306a36Sopenharmony_ci * @riov: the riov as passed to vringh_getdesc_iotlb() (updated as we consume) 151062306a36Sopenharmony_ci * @dst: the place to copy. 151162306a36Sopenharmony_ci * @len: the maximum length to copy. 151262306a36Sopenharmony_ci * 151362306a36Sopenharmony_ci * Returns the bytes copied <= len or a negative errno. 151462306a36Sopenharmony_ci */ 151562306a36Sopenharmony_cissize_t vringh_iov_pull_iotlb(struct vringh *vrh, 151662306a36Sopenharmony_ci struct vringh_kiov *riov, 151762306a36Sopenharmony_ci void *dst, size_t len) 151862306a36Sopenharmony_ci{ 151962306a36Sopenharmony_ci return vringh_iov_xfer(vrh, riov, dst, len, xfer_from_iotlb); 152062306a36Sopenharmony_ci} 152162306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_iov_pull_iotlb); 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci/** 152462306a36Sopenharmony_ci * vringh_iov_push_iotlb - copy bytes into vring_iov. 152562306a36Sopenharmony_ci * @vrh: the vring. 152662306a36Sopenharmony_ci * @wiov: the wiov as passed to vringh_getdesc_iotlb() (updated as we consume) 152762306a36Sopenharmony_ci * @src: the place to copy from. 152862306a36Sopenharmony_ci * @len: the maximum length to copy. 152962306a36Sopenharmony_ci * 153062306a36Sopenharmony_ci * Returns the bytes copied <= len or a negative errno. 153162306a36Sopenharmony_ci */ 153262306a36Sopenharmony_cissize_t vringh_iov_push_iotlb(struct vringh *vrh, 153362306a36Sopenharmony_ci struct vringh_kiov *wiov, 153462306a36Sopenharmony_ci const void *src, size_t len) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci return vringh_iov_xfer(vrh, wiov, (void *)src, len, xfer_to_iotlb); 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_iov_push_iotlb); 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci/** 154162306a36Sopenharmony_ci * vringh_abandon_iotlb - we've decided not to handle the descriptor(s). 154262306a36Sopenharmony_ci * @vrh: the vring. 154362306a36Sopenharmony_ci * @num: the number of descriptors to put back (ie. num 154462306a36Sopenharmony_ci * vringh_get_iotlb() to undo). 154562306a36Sopenharmony_ci * 154662306a36Sopenharmony_ci * The next vringh_get_iotlb() will return the old descriptor(s) again. 154762306a36Sopenharmony_ci */ 154862306a36Sopenharmony_civoid vringh_abandon_iotlb(struct vringh *vrh, unsigned int num) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci /* We only update vring_avail_event(vr) when we want to be notified, 155162306a36Sopenharmony_ci * so we haven't changed that yet. 155262306a36Sopenharmony_ci */ 155362306a36Sopenharmony_ci vrh->last_avail_idx -= num; 155462306a36Sopenharmony_ci} 155562306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_abandon_iotlb); 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci/** 155862306a36Sopenharmony_ci * vringh_complete_iotlb - we've finished with descriptor, publish it. 155962306a36Sopenharmony_ci * @vrh: the vring. 156062306a36Sopenharmony_ci * @head: the head as filled in by vringh_getdesc_iotlb. 156162306a36Sopenharmony_ci * @len: the length of data we have written. 156262306a36Sopenharmony_ci * 156362306a36Sopenharmony_ci * You should check vringh_need_notify_iotlb() after one or more calls 156462306a36Sopenharmony_ci * to this function. 156562306a36Sopenharmony_ci */ 156662306a36Sopenharmony_ciint vringh_complete_iotlb(struct vringh *vrh, u16 head, u32 len) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci struct vring_used_elem used; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci used.id = cpu_to_vringh32(vrh, head); 157162306a36Sopenharmony_ci used.len = cpu_to_vringh32(vrh, len); 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci return __vringh_complete(vrh, &used, 1, putu16_iotlb, putused_iotlb); 157462306a36Sopenharmony_ci} 157562306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_complete_iotlb); 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci/** 157862306a36Sopenharmony_ci * vringh_notify_enable_iotlb - we want to know if something changes. 157962306a36Sopenharmony_ci * @vrh: the vring. 158062306a36Sopenharmony_ci * 158162306a36Sopenharmony_ci * This always enables notifications, but returns false if there are 158262306a36Sopenharmony_ci * now more buffers available in the vring. 158362306a36Sopenharmony_ci */ 158462306a36Sopenharmony_cibool vringh_notify_enable_iotlb(struct vringh *vrh) 158562306a36Sopenharmony_ci{ 158662306a36Sopenharmony_ci return __vringh_notify_enable(vrh, getu16_iotlb, putu16_iotlb); 158762306a36Sopenharmony_ci} 158862306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_notify_enable_iotlb); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci/** 159162306a36Sopenharmony_ci * vringh_notify_disable_iotlb - don't tell us if something changes. 159262306a36Sopenharmony_ci * @vrh: the vring. 159362306a36Sopenharmony_ci * 159462306a36Sopenharmony_ci * This is our normal running state: we disable and then only enable when 159562306a36Sopenharmony_ci * we're going to sleep. 159662306a36Sopenharmony_ci */ 159762306a36Sopenharmony_civoid vringh_notify_disable_iotlb(struct vringh *vrh) 159862306a36Sopenharmony_ci{ 159962306a36Sopenharmony_ci __vringh_notify_disable(vrh, putu16_iotlb); 160062306a36Sopenharmony_ci} 160162306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_notify_disable_iotlb); 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci/** 160462306a36Sopenharmony_ci * vringh_need_notify_iotlb - must we tell the other side about used buffers? 160562306a36Sopenharmony_ci * @vrh: the vring we've called vringh_complete_iotlb() on. 160662306a36Sopenharmony_ci * 160762306a36Sopenharmony_ci * Returns -errno or 0 if we don't need to tell the other side, 1 if we do. 160862306a36Sopenharmony_ci */ 160962306a36Sopenharmony_ciint vringh_need_notify_iotlb(struct vringh *vrh) 161062306a36Sopenharmony_ci{ 161162306a36Sopenharmony_ci return __vringh_need_notify(vrh, getu16_iotlb); 161262306a36Sopenharmony_ci} 161362306a36Sopenharmony_ciEXPORT_SYMBOL(vringh_need_notify_iotlb); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci#endif 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1618