上QQ阅读APP看书,第一时间看更新
1.5.2 创建内存
接下来我们开始组装机器,首先是内存,就像需要在内存槽上插上内存条一样,我们也需要为我们的虚拟机安装内存。KVM为用户空间工具配置虚拟机内存定义的数据结构如下:
commit 6fc138d2278078990f597cb1f62fde9e5b458f96 KVM: Support assigning userspace memory to the guest linux.git/include/linux/kvm.h struct kvm_userspace_memory_region { __u32 slot; __u32 flags; __u64 guest_phys_addr; __u64 memory_size; /* bytes */ __u64 userspace_addr; /* start of the userspace … */ };
其中,slot表示一个内存槽,如果虚拟机中这个内存槽上尚未插入内存,那么就相当于安装一条新的内存,否则就是修改已有的内存。flags是内存的类型,比如KVM_MEM_READONLY表示是只读内存。guest_phys_addr表示这块内存条映射到虚拟机的物理内存地址空间的起始地址,比如guest_phys_addr为0x10000,表示插入的这块内存条占据虚拟机的从64KB开始的一段物理内存,内存大小由字段memory_size指明。宿主机需要分配一段内存作为虚拟机的物理内存,这段内存在Host中的起始地址即HVA,由字段userspace_addr告知KVM子系统。
在例子中,我们使用mmap分配了一段按照页面尺寸对齐的64MB的内存作为虚拟机的物理内存。然后通过KVM子系统为用户空间配置虚拟机内存提供的API KVM_SET_USER_MEMORY_REGION,为虚拟机在0号槽上插入一条内存:
int setup_vm(struct vm *vm, int ram_size) { … vm->ram_size = ram_size; vm->ram_start = (__u64)mmap(NULL, vm->ram_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); if ((void *)vm->ram_start == MAP_FAILED) { fprintf(stderr, "failed to map memory for vm.\n"); return -1; } vm->mem.slot = 0; vm->mem.guest_phys_addr = 0; vm->mem.memory_size = vm->ram_size; vm->mem.userspace_addr = vm->ram_start; if ((ioctl(vm->vm_fd, KVM_SET_USER_MEMORY_REGION, &(vm->mem))) < 0) { fprintf(stderr, "failed to set memory for vm.\n"); return -1; } … }