#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/export.h>
#include <uapi/linux/virtio_config.h>
static __printf(1,2) __cold void vringh_bad(const char *fmt, ...)
static DEFINE_RATELIMIT_STATE(vringh_rs,
DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
if (__ratelimit(&vringh_rs)) {
printk(KERN_NOTICE "vringh:");
static inline int __vringh_get_head(const struct vringh *vrh,
int (*getu16)(const struct vringh *vrh,
u16 *val, const __virtio16 *p),
err = getu16(vrh, &avail_idx, &vrh->vring.avail->idx);
vringh_bad("Failed to access avail idx at %p",
if (*last_avail_idx == avail_idx)
virtio_rmb(vrh->weak_barriers);
i = *last_avail_idx & (vrh->vring.num - 1);
err = getu16(vrh, &head, &vrh->vring.avail->ring[i]);
vringh_bad("Failed to read head: idx %d address %p",
*last_avail_idx, &vrh->vring.avail->ring[i]);
if (head >= vrh->vring.num) {
vringh_bad("Guest says index %u > %u is available",
static inline ssize_t vringh_iov_xfer(struct vringh_kiov *iov,
int (*xfer)(void *addr, void *ptr,
while (len && iov->i < iov->used) {
partlen = min(iov->iov[iov->i].iov_len, len);
err = xfer(iov->iov[iov->i].iov_base, ptr, partlen);
iov->consumed += partlen;
iov->iov[iov->i].iov_len -= partlen;
iov->iov[iov->i].iov_base += partlen;