// SPDX-License-Identifier: GPL-2.0-only /* * Helpers for the host side of a virtio ring. * * Since these may be in userspace, we use (inline) accessors.
*/ #include <linux/compiler.h> #include <linux/module.h> #include <linux/vringh.h> #include <linux/virtio_ring.h> #include <linux/kernel.h> #include <linux/ratelimit.h> #include <linux/uaccess.h> #include <linux/slab.h> #include <linux/export.h> #if IS_REACHABLE(CONFIG_VHOST_IOTLB) #include <linux/bvec.h> #include <linux/highmem.h> #include <linux/vhost_iotlb.h> #endif #include <uapi/linux/virtio_config.h>
if (!iov->iov[iov->i].iov_len) { /* Fix up old iov element then increment. */
iov->iov[iov->i].iov_len = iov->consumed;
iov->iov[iov->i].iov_base -= iov->consumed;
iov->consumed = 0;
iov->i++;
}
len -= partlen;
}
}
EXPORT_SYMBOL(vringh_kiov_advance);
/* Copy some bytes to/from the iovec. Returns num copied. */ staticinline ssize_t vringh_iov_xfer(struct vringh *vrh, struct vringh_kiov *iov, void *ptr, size_t len, int (*xfer)(conststruct vringh *vrh, void *addr, void *ptr,
size_t len))
{ int err, done = 0;
while (len && iov->i < iov->used) {
size_t partlen;
if (!iov->iov[iov->i].iov_len) { /* Fix up old iov element then increment. */
iov->iov[iov->i].iov_len = iov->consumed;
iov->iov[iov->i].iov_base -= iov->consumed;
iov->consumed = 0;
iov->i++;
}
} return done;
}
/* May reduce *len if range is shorter. */ staticinlinebool range_check(struct vringh *vrh, u64 addr, size_t *len, struct vringh_range *range, bool (*getrange)(struct vringh *,
u64, struct vringh_range *))
{ if (addr < range->start || addr > range->end_incl) { if (!getrange(vrh, addr, range)) returnfalse;
}
BUG_ON(addr < range->start || addr > range->end_incl);
/* To end of memory? */ if (unlikely(addr + *len == 0)) { if (range->end_incl == -1ULL) returntrue; goto truncate;
}
/* No reason for this code to be inline. */ staticint move_to_indirect(conststruct vringh *vrh, int *up_next, u16 *i, void *addr, conststruct vring_desc *desc, struct vring_desc **descs, int *desc_max)
{
u32 len;
/* Indirect tables can't have indirect. */ if (*up_next != -1) {
vringh_bad("Multilevel indirect %u->%u", *up_next, *i); return -EINVAL;
}
len = vringh32_to_cpu(vrh, desc->len); if (unlikely(len % sizeof(struct vring_desc))) {
vringh_bad("Strange indirect len %u", desc->len); return -EINVAL;
}
/* We will check this when we follow it! */ if (desc->flags & cpu_to_vringh16(vrh, VRING_DESC_F_NEXT))
*up_next = vringh16_to_cpu(vrh, desc->next); else
*up_next = -2;
*descs = addr;
*desc_max = len / sizeof(struct vring_desc);
/* Now, start at the first indirect. */
*i = 0; return 0;
}
if (unlikely(desc.flags &
cpu_to_vringh16(vrh, VRING_DESC_F_INDIRECT))) {
u64 a = vringh64_to_cpu(vrh, desc.addr);
/* Make sure it's OK, and get offset. */
len = vringh32_to_cpu(vrh, desc.len); if (!rcheck(vrh, a, &len, &range, getrange)) {
err = -EINVAL; goto fail;
}
if (unlikely(len != vringh32_to_cpu(vrh, desc.len))) {
slow = true; /* We need to save this range to use offset */
slowrange = range;
}
if (desc.flags & cpu_to_vringh16(vrh, VRING_DESC_F_NEXT)) {
i = vringh16_to_cpu(vrh, desc.next);
} else { /* Just in case we need to finish traversing above. */ if (unlikely(up_next > 0)) {
i = return_from_indirect(vrh, &up_next,
&descs, &desc_max);
slow = false;
indirect_count = 0;
} else break;
}
if (i >= desc_max) {
vringh_bad("Chained index %u > %u", i, desc_max);
err = -EINVAL; goto fail;
}
}
if (err) {
vringh_bad("Failed to write %u used entries %u at %p",
num_used, off, &used_ring->ring[off]); return err;
}
/* Make sure buffer is written before we update index. */
virtio_wmb(vrh->weak_barriers);
err = putu16(vrh, &vrh->vring.used->idx, used_idx + num_used); if (err) {
vringh_bad("Failed to update used index at %p",
&vrh->vring.used->idx); return err;
}
vrh->completed += num_used; return 0;
}
staticinlineint __vringh_need_notify(struct vringh *vrh, int (*getu16)(conststruct vringh *vrh,
u16 *val, const __virtio16 *p))
{ bool notify;
u16 used_event; int err;
/* Flush out used index update. This is paired with the * barrier that the Guest executes when enabling
* interrupts. */
virtio_mb(vrh->weak_barriers);
/* Old-style, without event indices. */ if (!vrh->event_indices) {
u16 flags;
err = getu16(vrh, &flags, &vrh->vring.avail->flags); if (err) {
vringh_bad("Failed to get flags at %p",
&vrh->vring.avail->flags); return err;
} return (!(flags & VRING_AVAIL_F_NO_INTERRUPT));
}
/* Modern: we know when other side wants to know. */
err = getu16(vrh, &used_event, &vring_used_event(&vrh->vring)); if (err) {
vringh_bad("Failed to get used event idx at %p",
&vring_used_event(&vrh->vring)); return err;
}
/* Just in case we added so many that we wrap. */ if (unlikely(vrh->completed > 0xffff))
notify = true; else
notify = vring_need_event(used_event,
vrh->last_used_idx + vrh->completed,
vrh->last_used_idx);
if (!vrh->event_indices) { /* Old-school; update flags. */ if (putu16(vrh, &vrh->vring.used->flags, 0) != 0) {
vringh_bad("Clearing used flags %p",
&vrh->vring.used->flags); returntrue;
}
} else { if (putu16(vrh, &vring_avail_event(&vrh->vring),
vrh->last_avail_idx) != 0) {
vringh_bad("Updating avail event index %p",
&vring_avail_event(&vrh->vring)); returntrue;
}
}
/* They could have slipped one in as we were doing that: make
* sure it's written, then check again. */
virtio_mb(vrh->weak_barriers);
if (getu16(vrh, &avail, &vrh->vring.avail->idx) != 0) {
vringh_bad("Failed to check avail idx at %p",
&vrh->vring.avail->idx); returntrue;
}
/* This is unlikely, so we just leave notifications enabled * (if we're using event_indices, we'll only get one
* notification anyway). */ return avail == vrh->last_avail_idx;
}
staticinlinevoid __vringh_notify_disable(struct vringh *vrh, int (*putu16)(conststruct vringh *vrh,
__virtio16 *p, u16 val))
{ if (!vrh->event_indices) { /* Old-school; update flags. */ if (putu16(vrh, &vrh->vring.used->flags,
VRING_USED_F_NO_NOTIFY)) {
vringh_bad("Setting used flags %p",
&vrh->vring.used->flags);
}
}
}
/* Userspace access helpers: in this case, addresses are really userspace. */ staticinlineint getu16_user(conststruct vringh *vrh, u16 *val, const __virtio16 *p)
{
__virtio16 v = 0; int rc = get_user(v, (__force __virtio16 __user *)p);
*val = vringh16_to_cpu(vrh, v); return rc;
}
/** * vringh_init_user - initialize a vringh for a userspace vring. * @vrh: the vringh to initialize. * @features: the feature bits for this ring. * @num: the number of elements. * @weak_barriers: true if we only need memory barriers, not I/O. * @desc: the userspace descriptor pointer. * @avail: the userspace avail pointer. * @used: the userspace used pointer. * * Returns an error if num is invalid: you should check pointers * yourself!
*/ int vringh_init_user(struct vringh *vrh, u64 features, unsignedint num, bool weak_barriers,
vring_desc_t __user *desc,
vring_avail_t __user *avail,
vring_used_t __user *used)
{ /* Sane power of 2 please! */ if (!num || num > 0xffff || (num & (num - 1))) {
vringh_bad("Bad ring size %u", num); return -EINVAL;
}
/** * vringh_getdesc_user - get next available descriptor from userspace ring. * @vrh: the userspace vring. * @riov: where to put the readable descriptors (or NULL) * @wiov: where to put the writable descriptors (or NULL) * @getrange: function to call to check ranges. * @head: head index we received, for passing to vringh_complete_user(). * * Returns 0 if there was no descriptor, 1 if there was, or -errno. * * Note that on error return, you can tell the difference between an * invalid ring and a single invalid descriptor: in the former case, * *head will be vrh->vring.num. You may be able to ignore an invalid * descriptor, but there's not much you can do with an invalid ring. * * Note that you can reuse riov and wiov with subsequent calls. Content is * overwritten and memory reallocated if more space is needed. * When you don't have to use riov and wiov anymore, you should clean up them * calling vringh_iov_cleanup() to release the memory, even on error!
*/ int vringh_getdesc_user(struct vringh *vrh, struct vringh_iov *riov, struct vringh_iov *wiov, bool (*getrange)(struct vringh *vrh,
u64 addr, struct vringh_range *r),
u16 *head)
{ int err;
/** * vringh_iov_pull_user - copy bytes from vring_iov. * @riov: the riov as passed to vringh_getdesc_user() (updated as we consume) * @dst: the place to copy. * @len: the maximum length to copy. * * Returns the bytes copied <= len or a negative errno.
*/
ssize_t vringh_iov_pull_user(struct vringh_iov *riov, void *dst, size_t len)
{ return vringh_iov_xfer(NULL, (struct vringh_kiov *)riov,
dst, len, xfer_from_user);
}
EXPORT_SYMBOL(vringh_iov_pull_user);
/** * vringh_iov_push_user - copy bytes into vring_iov. * @wiov: the wiov as passed to vringh_getdesc_user() (updated as we consume) * @src: the place to copy from. * @len: the maximum length to copy. * * Returns the bytes copied <= len or a negative errno.
*/
ssize_t vringh_iov_push_user(struct vringh_iov *wiov, constvoid *src, size_t len)
{ return vringh_iov_xfer(NULL, (struct vringh_kiov *)wiov,
(void *)src, len, xfer_to_user);
}
EXPORT_SYMBOL(vringh_iov_push_user);
/** * vringh_complete_user - we've finished with descriptor, publish it. * @vrh: the vring. * @head: the head as filled in by vringh_getdesc_user. * @len: the length of data we have written. * * You should check vringh_need_notify_user() after one or more calls * to this function.
*/ int vringh_complete_user(struct vringh *vrh, u16 head, u32 len)
{ struct vring_used_elem used;
/** * vringh_complete_multi_user - we've finished with many descriptors. * @vrh: the vring. * @used: the head, length pairs. * @num_used: the number of used elements. * * You should check vringh_need_notify_user() after one or more calls * to this function.
*/ int vringh_complete_multi_user(struct vringh *vrh, conststruct vring_used_elem used[], unsigned num_used)
{ return __vringh_complete(vrh, used, num_used,
putu16_user, putused_user);
}
EXPORT_SYMBOL(vringh_complete_multi_user);
/** * vringh_notify_enable_user - we want to know if something changes. * @vrh: the vring. * * This always enables notifications, but returns false if there are * now more buffers available in the vring.
*/ bool vringh_notify_enable_user(struct vringh *vrh)
{ return __vringh_notify_enable(vrh, getu16_user, putu16_user);
}
EXPORT_SYMBOL(vringh_notify_enable_user);
/** * vringh_notify_disable_user - don't tell us if something changes. * @vrh: the vring. * * This is our normal running state: we disable and then only enable when * we're going to sleep.
*/ void vringh_notify_disable_user(struct vringh *vrh)
{
__vringh_notify_disable(vrh, putu16_user);
}
EXPORT_SYMBOL(vringh_notify_disable_user);
/** * vringh_need_notify_user - must we tell the other side about used buffers? * @vrh: the vring we've called vringh_complete_user() on. * * Returns -errno or 0 if we don't need to tell the other side, 1 if we do.
*/ int vringh_need_notify_user(struct vringh *vrh)
{ return __vringh_need_notify(vrh, getu16_user);
}
EXPORT_SYMBOL(vringh_need_notify_user);
/** * vringh_init_kern - initialize a vringh for a kernelspace vring. * @vrh: the vringh to initialize. * @features: the feature bits for this ring. * @num: the number of elements. * @weak_barriers: true if we only need memory barriers, not I/O. * @desc: the userspace descriptor pointer. * @avail: the userspace avail pointer. * @used: the userspace used pointer. * * Returns an error if num is invalid.
*/ int vringh_init_kern(struct vringh *vrh, u64 features, unsignedint num, bool weak_barriers, struct vring_desc *desc, struct vring_avail *avail, struct vring_used *used)
{ /* Sane power of 2 please! */ if (!num || num > 0xffff || (num & (num - 1))) {
vringh_bad("Bad ring size %u", num); return -EINVAL;
}
/** * vringh_getdesc_kern - get next available descriptor from kernelspace ring. * @vrh: the kernelspace vring. * @riov: where to put the readable descriptors (or NULL) * @wiov: where to put the writable descriptors (or NULL) * @head: head index we received, for passing to vringh_complete_kern(). * @gfp: flags for allocating larger riov/wiov. * * Returns 0 if there was no descriptor, 1 if there was, or -errno. * * Note that on error return, you can tell the difference between an * invalid ring and a single invalid descriptor: in the former case, * *head will be vrh->vring.num. You may be able to ignore an invalid * descriptor, but there's not much you can do with an invalid ring. * * Note that you can reuse riov and wiov with subsequent calls. Content is * overwritten and memory reallocated if more space is needed. * When you don't have to use riov and wiov anymore, you should clean up them * calling vringh_kiov_cleanup() to release the memory, even on error!
*/ int vringh_getdesc_kern(struct vringh *vrh, struct vringh_kiov *riov, struct vringh_kiov *wiov,
u16 *head,
gfp_t gfp)
{ int err;
/** * vringh_complete_kern - we've finished with descriptor, publish it. * @vrh: the vring. * @head: the head as filled in by vringh_getdesc_kern. * @len: the length of data we have written. * * You should check vringh_need_notify_kern() after one or more calls * to this function.
*/ int vringh_complete_kern(struct vringh *vrh, u16 head, u32 len)
{ struct vring_used_elem used;
/** * vringh_notify_enable_kern - we want to know if something changes. * @vrh: the vring. * * This always enables notifications, but returns false if there are * now more buffers available in the vring.
*/ bool vringh_notify_enable_kern(struct vringh *vrh)
{ return __vringh_notify_enable(vrh, getu16_kern, putu16_kern);
}
EXPORT_SYMBOL(vringh_notify_enable_kern);
/** * vringh_notify_disable_kern - don't tell us if something changes. * @vrh: the vring. * * This is our normal running state: we disable and then only enable when * we're going to sleep.
*/ void vringh_notify_disable_kern(struct vringh *vrh)
{
__vringh_notify_disable(vrh, putu16_kern);
}
EXPORT_SYMBOL(vringh_notify_disable_kern);
/** * vringh_need_notify_kern - must we tell the other side about used buffers? * @vrh: the vring we've called vringh_complete_kern() on. * * Returns -errno or 0 if we don't need to tell the other side, 1 if we do.
*/ int vringh_need_notify_kern(struct vringh *vrh)
{ return __vringh_need_notify(vrh, getu16_kern);
}
EXPORT_SYMBOL(vringh_need_notify_kern);
ret = copy_to_iotlb(vrh, dst, src, len); if (ret != len) return -EFAULT;
return 0;
}
staticinlineint putused_iotlb(conststruct vringh *vrh, struct vring_used_elem *dst, conststruct vring_used_elem *src, unsignedint num)
{ int size = num * sizeof(*dst); int ret;
ret = copy_to_iotlb(vrh, dst, (void *)src, num * sizeof(*dst)); if (ret != size) return -EFAULT;
return 0;
}
/** * vringh_init_iotlb - initialize a vringh for a ring with IOTLB. * @vrh: the vringh to initialize. * @features: the feature bits for this ring. * @num: the number of elements. * @weak_barriers: true if we only need memory barriers, not I/O. * @desc: the userspace descriptor pointer. * @avail: the userspace avail pointer. * @used: the userspace used pointer. * * Returns an error if num is invalid.
*/ int vringh_init_iotlb(struct vringh *vrh, u64 features, unsignedint num, bool weak_barriers, struct vring_desc *desc, struct vring_avail *avail, struct vring_used *used)
{
vrh->use_va = false;
/** * vringh_init_iotlb_va - initialize a vringh for a ring with IOTLB containing * user VA. * @vrh: the vringh to initialize. * @features: the feature bits for this ring. * @num: the number of elements. * @weak_barriers: true if we only need memory barriers, not I/O. * @desc: the userspace descriptor pointer. * @avail: the userspace avail pointer. * @used: the userspace used pointer. * * Returns an error if num is invalid.
*/ int vringh_init_iotlb_va(struct vringh *vrh, u64 features, unsignedint num, bool weak_barriers, struct vring_desc *desc, struct vring_avail *avail, struct vring_used *used)
{
vrh->use_va = true;
/** * vringh_set_iotlb - initialize a vringh for a ring with IOTLB. * @vrh: the vring * @iotlb: iotlb associated with this vring * @iotlb_lock: spinlock to synchronize the iotlb accesses
*/ void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb,
spinlock_t *iotlb_lock)
{
vrh->iotlb = iotlb;
vrh->iotlb_lock = iotlb_lock;
}
EXPORT_SYMBOL(vringh_set_iotlb);
/** * vringh_getdesc_iotlb - get next available descriptor from ring with * IOTLB. * @vrh: the kernelspace vring. * @riov: where to put the readable descriptors (or NULL) * @wiov: where to put the writable descriptors (or NULL) * @head: head index we received, for passing to vringh_complete_iotlb(). * @gfp: flags for allocating larger riov/wiov. * * Returns 0 if there was no descriptor, 1 if there was, or -errno. * * Note that on error return, you can tell the difference between an * invalid ring and a single invalid descriptor: in the former case, * *head will be vrh->vring.num. You may be able to ignore an invalid * descriptor, but there's not much you can do with an invalid ring. * * Note that you can reuse riov and wiov with subsequent calls. Content is * overwritten and memory reallocated if more space is needed. * When you don't have to use riov and wiov anymore, you should clean up them * calling vringh_kiov_cleanup() to release the memory, even on error!
*/ int vringh_getdesc_iotlb(struct vringh *vrh, struct vringh_kiov *riov, struct vringh_kiov *wiov,
u16 *head,
gfp_t gfp)
{ int err;
/** * vringh_iov_pull_iotlb - copy bytes from vring_iov. * @vrh: the vring. * @riov: the riov as passed to vringh_getdesc_iotlb() (updated as we consume) * @dst: the place to copy. * @len: the maximum length to copy. * * Returns the bytes copied <= len or a negative errno.
*/
ssize_t vringh_iov_pull_iotlb(struct vringh *vrh, struct vringh_kiov *riov, void *dst, size_t len)
{ return vringh_iov_xfer(vrh, riov, dst, len, xfer_from_iotlb);
}
EXPORT_SYMBOL(vringh_iov_pull_iotlb);
/** * vringh_iov_push_iotlb - copy bytes into vring_iov. * @vrh: the vring. * @wiov: the wiov as passed to vringh_getdesc_iotlb() (updated as we consume) * @src: the place to copy from. * @len: the maximum length to copy. * * Returns the bytes copied <= len or a negative errno.
*/
ssize_t vringh_iov_push_iotlb(struct vringh *vrh, struct vringh_kiov *wiov, constvoid *src, size_t len)
{ return vringh_iov_xfer(vrh, wiov, (void *)src, len, xfer_to_iotlb);
}
EXPORT_SYMBOL(vringh_iov_push_iotlb);
/** * vringh_complete_iotlb - we've finished with descriptor, publish it. * @vrh: the vring. * @head: the head as filled in by vringh_getdesc_iotlb. * @len: the length of data we have written. * * You should check vringh_need_notify_iotlb() after one or more calls * to this function.
*/ int vringh_complete_iotlb(struct vringh *vrh, u16 head, u32 len)
{ struct vring_used_elem used;
/** * vringh_need_notify_iotlb - must we tell the other side about used buffers? * @vrh: the vring we've called vringh_complete_iotlb() on. * * Returns -errno or 0 if we don't need to tell the other side, 1 if we do.
*/ int vringh_need_notify_iotlb(struct vringh *vrh)
{ return __vringh_need_notify(vrh, getu16_iotlb);
}
EXPORT_SYMBOL(vringh_need_notify_iotlb);
#endif
MODULE_DESCRIPTION("host side of a virtio ring");
MODULE_LICENSE("GPL");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.