drivers/vhost/vringh.c

Source file repositories/reference/linux-study-clean/drivers/vhost/vringh.c

File Facts

System
Linux kernel
Corpus path
drivers/vhost/vringh.c
Extension
.c
Size
39568 bytes
Lines
1500
Domain
Driver Families
Bucket
drivers/vhost
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct iotlb_vec {
	union {
		struct iovec *iovec;
		struct bio_vec *bvec;
	} iov;
	size_t count;
};

static int iotlb_translate(const struct vringh *vrh,
			   u64 addr, u64 len, u64 *translated,
			   struct iotlb_vec *ivec, u32 perm)
{
	struct vhost_iotlb_map *map;
	struct vhost_iotlb *iotlb = vrh->iotlb;
	int ret = 0;
	u64 s = 0, last = addr + len - 1;

	spin_lock(vrh->iotlb_lock);

	while (len > s) {
		uintptr_t io_addr;
		size_t io_len;
		u64 size;

		if (unlikely(ret >= ivec->count)) {
			ret = -ENOBUFS;
			break;
		}

		map = vhost_iotlb_itree_first(iotlb, addr, last);
		if (!map || map->start > addr) {
			ret = -EINVAL;
			break;
		} else if (!(map->perm & perm)) {
			ret = -EPERM;
			break;
		}

		size = map->size - addr + map->start;
		io_len = min(len - s, size);
		io_addr = map->addr - map->start + addr;

		if (vrh->use_va) {
			struct iovec *iovec = ivec->iov.iovec;

			iovec[ret].iov_len = io_len;
			iovec[ret].iov_base = (void __user *)io_addr;
		} else {
			u64 pfn = io_addr >> PAGE_SHIFT;
			struct bio_vec *bvec = ivec->iov.bvec;

			bvec_set_page(&bvec[ret], pfn_to_page(pfn), io_len,
				      io_addr & (PAGE_SIZE - 1));
		}

		s += size;
		addr += size;
		++ret;
	}

	spin_unlock(vrh->iotlb_lock);

	if (translated)
		*translated = min(len, s);

	return ret;
}

#define IOTLB_IOV_STRIDE 16

static inline int copy_from_iotlb(const struct vringh *vrh, void *dst,
				  void *src, size_t len)
{
	struct iotlb_vec ivec;
	union {
		struct iovec iovec[IOTLB_IOV_STRIDE];
		struct bio_vec bvec[IOTLB_IOV_STRIDE];
	} iov;
	u64 total_translated = 0;

	ivec.iov.iovec = iov.iovec;
	ivec.count = IOTLB_IOV_STRIDE;

	while (total_translated < len) {
		struct iov_iter iter;
		u64 translated;
		int ret;
		size_t size;

		ret = iotlb_translate(vrh, (u64)(uintptr_t)src,

Annotation

Implementation Notes