VHOST_SET_MEM_TABLE 的设置

vhost收到 VHOST_SET_MEM_TABLE 后,设置guest内存空间布局,用于映射 guest 物理内存与 host 虚拟内存。

KVMTOOL SETUP

struct vhost_memory *mem;
list_for_each_entry(bank, &kvm->mem_banks, list) {
		mem->regions[i] = (struct vhost_memory_region) { 
                            //guest 物理内存与 host 用户态虚拟内存的1:1映射
							.guest_phys_addr = bank->guest_phys_addr,
							.memory_size     = bank->size,
							.userspace_addr  = (unsignedlong)bank->host_addr,
		};
		i++;
}
mem->nregions = i;

r = ioctl(vdev->vhost_fd, VHOST_SET_MEM_TABLE, mem);
if (r != 0)
    die_perror("VHOST_SET_MEM_TABLE failed");

KERNEL SETUP

vhost_dev_ioctl
    vhost_set_memory
        vhost_iotlb_add_range(newumem,
		    		    region->guest_phys_addr,
                        region->guest_phys_addr + region->memory_size - 1,
				        region->userspace_addr,
                        VHOST_MAP_RW)

int vhost_iotlb_add_range(struct vhost_iotlb *iotlb, u64 start,
                          u64 last, u64 addr, unsignedint perm)
{               
		struct vhost_iotlb_map *map;      

        map = kmalloc(sizeof(*map), GFP_ATOMIC);

		map->start = start; //guest_phys_addr start
		map->size = last - start + 1;
		map->last = last;   //guest_phys_addr end
		map->addr = addr;   //userspace_addr start
		map->perm = perm;

		iotlb->nmaps++;
		vhost_iotlb_itree_insert(map, &iotlb->root);//map信息插入到rb tree

		INIT_LIST_HEAD(&map->link);
		list_add_tail(&map->link, &iotlb->list);
		return0;
}

KERNEL USESAGE

tx kick func(receive guest message)
    vhost_get_vq_desc
        translate_desc


static int translate_desc(struct vhost_virtqueue *vq, u64 addr,
                          u32 len, struct iovec iov[], int 	
                          iov_size, int access)
{
        const struct vhost_iotlb_map *map;
        map = vhost_iotlb_itree_first(umem, addr, addr + len - 1); 
                                            //addr是virtio前端驱动填充到vring desc中的
                                            //guest物理物址

		size = map->size - addr + map->start; 
           //= map->size - offset (addr - map->start)
 
		_iov->iov_len = min((u64)len - s, size);

        //host 用户态虚拟地址 = host 用户态起始虚拟地址 + offset(guest 物理地址 - guest 物
                              理起始地址)
		_iov->iov_base = (void __user *)(unsigned long)(map->addr + addr - 
                                                                   map->start);
}

上一篇:JAVA 动态规划


下一篇:ptr_fun/mem_fun/mem_fun_ref