Qemu创建KVM虚拟机内存初始化流程
转载请注明:【转载自博客xelatex KVM】,并附本文链接。谢谢。
【注】文章中采用的版本:
- Linux-3.11,https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.11.tar.gz
- qemu-kvm,git clone http://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git,
git checkout 4d9367b76f71c6d938cf8201392abe4bfb1136cb
一、Qemu的内存模型
Qemu中的内存模型,简单来说就是Qemu申请用户态内存并进行管理,并将该部分申请的内存注册到对应的加速器(如KVM)中。这样的模型有如下好处:
- 策略与机制分离。加速的机制由KVM负责,而如何调用加速的机制由Qemu负责
- 可以由Qemu设置多种内存模型,如UMA、NUMA等等
- 方便Qemu对特殊内存的管理(如MMIO)
- 内存的分配、回收、换出等都可以采用Linux原有的机制,不需要为KVM单独开发。
- 兼容其他加速器模型(或者无加速器,单纯使用Qemu做模拟)
所以在初始化阶段,Qemu需要做的有两方面工作:向KVM注册用户态内存空间,申请用户态内存空间。
Qemu主要通过如下结构来维护内存:
/* A system address space - I/O, memory, etc. */
struct AddressSpace {
MemoryRegion *root;
FlatView current_map;
int ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
};
AddressSpace设置了一段内存,其主要信息存储在root成员中,root成员是个MemoryRegion结构,主要存储内存区的结构。在Qemu中最主要的两个AddressSpace是address_space_memory和address_space_io,分别对应的MemoryRegion变量是system_memory和system_io。
二、Qemu初始化KVM内存流程
Qemu的主函数是vl.c中的main函数,其中调用了configure_accelerator(),是KVM初始化的配置部分。
configure_accelerator中首先根据命令行输入的参数找到对应的accelerator,这里是KVM。之后调用accel_list[i].init(),即kvm_init()。
在kvm_init()函数中主要做如下几件事情:
- s->fd = qemu_open("/dev/kvm", O_RDWR),打开kvm控制的总设备文件/dev/kvm
- s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0),调用创建虚拟机的API,对应Linux kernel中的创建流程,请全文搜索kernel,关键词“KVM_CREATE_VM”
- kvm_check_extension,检查各种extension,并设置对应的features
- ret = kvm_arch_init(s),做一些体系结构相关的初始化,如msr、identity map、mmu pages number等等
- kvm_irqchip_create,调用kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP)在KVM中虚拟IRQ芯片,详细流程请全文搜索
- memory_listener_register,该函数是初始化内存的主要函数,下面详细分析
memory_listener_register调用了两次,分别注册了kvm_memory_listener和kvm_io_listener,即通用的内存和MMIO是分开管理的。以通用的内存注册为例,函数首先在全局的memory_listener链表中添加了kvm_memory_listener,之后调用listener_add_address_space分别将该listener添加到address_space_memory和address_space_io中。
然后调用listener的region_add(即kvm_region_add()),该函数最终调用了kvm_set_user_memory_region(),其中调用kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem),该调用是最终将内存区域注册到kvm中的函数。
之后在vl.c的main函数中调用了cpu_exec_init_all() => memory_map_init(),设置system_memory和system_io。
至此初始化好了所有Qemu中需要维护的相关的内存结构,并完成了在KVM中的注册。下面需要初始化KVM中的MMU支持。
ram_size内存大小从内存被读取到ram_size中,在vl.c的main中调用machine->init()来初始化,machine是命令行指定的机器类型,默认的init是pc_init_pci
- 调用pc_init1,参数分别是system_memory,system_io,ram_size,boot_device,kernel_filename,kernel_cmdline,initrd_filename,cpu_model,pci_enabled,kvmclock_enabled
- 设置above_4g_mem_size和below_4g_mem_size
- 调用pc_memory_init设置ram,第5、6个参数分别是below_4g_mem_size和above_4g_mem_size,MemoryRegion是system_memory
- 调用memory_region_init_ram初始化ram
- 调用memory_region_init()初始化MemoryRegion ram
- 设置destructor memory_region_destructor_ram
- 调用qemu_ram_alloc()初始化ram空间,内部调用qemu_ram_alloc_from_ptr()
- 如果没有设置-mem-path参数,则进入到第二个else(if (xen_enabled()) {)
- if (kvm_enabled()),调用kvm_vmalloc
- 如果是TARGET_S390X,调用kvm_arch_vmalloc
- 否则调用qemu_vmalloc(此处走posix流程)
- 调用qemu_memalign->posix_memalign(),此处真正alloc memory并且aligned
- 或者直接调用malloc(在qemu_memalign中,没有_POSIX_C_SOURCE和CONFIG_BSD
- 调用memory_region_init_alias初始化ram_below_4g,设置MemoryRegion的一个alias
- if (above_4g_mem_size > 0),调用memory_region_init_alias初始化ram_above_4g,设置alias
- memory_region_init_ram初始化pc.rom
- 调用bochs_bios_init初始化bios
- 调用memory_region_init_ram初始化ram
这样就建立好了Qemu-KVM的内存结构。在KVM创建Qemu内存映射的入口在kernel中kvm_vm_ioctl的case KVM_SET_USER_MEMORY_REGION,调用kvm_vm_ioctl_set_memory_region。kvm中用kvm_memory_slot结构来维护队用户空间地址的映射。该部分会在其他文章中详细介绍。
Qemu创建KVM虚拟机内存初始化流程的更多相关文章
- [图文] Fedora 28 使用 Virt-Manager 创建 KVM 虚拟机以及 配置 KVM 虚拟机
实验说明: 往后的许多实验都将以Linux平台下的 KVM虚拟机为主,所以不可少的就是 Virt-Manager 虚拟机管理器. 本章将对如何安装和使用Virt-Manager管理器进行讲解,并且会对 ...
- CentOS7中KVM虚拟机内存、CPU调整
CentOS7中KVM虚拟机内存.CPU调整 1. 调小虚拟机内存 调小虚拟机内存可以动态实现,不用关机 1.1 查看当前内存大小 [root@kvm01 ~]# virsh dominfo vm1- ...
- centos创建kvm虚拟机
1.检查kvm模块是否已经加载 lsmod |grep kvm 上图已经加载 没有加载 2.加载kvm 模块至内核 modprobe kvm modprobe kvm-intel modprobe: ...
- CentOS7.6中 KVM虚拟机内存、CPU调整
CentOS7.6中 KVM虚拟机内存.CPU调整 一.调小虚拟机内存 调小虚拟机内存可以动态实现,不用关机 1.查看当前内存大小 [root@heyong kvm]# virsh dominfo t ...
- 创建KVM虚拟机
#此操作是在VMware workstations上面做的,要在开机前 编辑虚拟机设置——>处理器--->虚拟化Intel/VT-x/ept 选项勾选上,如果是在服务器上请在bios界面设 ...
- 命令行创建KVM虚拟机
qemu命令创建虚拟机: qemu-img create -f qcow2 /home/ubuntu.img 20G qemu-system-x86_64 -m 2048 -enable-kvm ...
- 使用virsh命令创建KVM虚拟机快照
查看虚拟机所在主机和虚拟机名称:[root@node-1 ~]# nova show a88dcf5d-c8b2-46a5-af27-a176d8235c9d|grep hyper| OS-EXT-S ...
- centos6安装创建kvm虚拟机
的虚拟机名 virsh domid name # 显示虚拟机id号 virsh domuuid name ...
- 编写shell脚本实现一键创建KVM虚拟机
shell脚本一键创建虚拟机 代码如下: #!/bin/bashname=$1 #把位置变量$1重新定义为name(创建虚拟机的名字)path1=/var/lib/libvirt/images/ #i ...
随机推荐
- logstash收集Nginx日志,转换为JSON格式
Nginx日志处理为JSON格式,并放置在http区块: log_format json '{"@timestamp":"$time_iso8601",' '& ...
- 2017-2018-1 Java小组-1623 第二周作业
2017-2018-1 Java小组-1623 第二周作业 关于游戏软件的问题 讨论结果 20162301张师瑜 20162305李昱兴 20162306陈是奇 20162308马平川 2016231 ...
- ubuntu 18.04 64bit如何安装GPU版本tensorflow
注:笔者的ubuntu18.04 64bit已经安装好了显卡驱动,因此没有此步操作 1.获取cuda(https://developer.nvidia.com/cuda-downloads,选择ubu ...
- php 关联数组遍历
<?php $age=array("); foreach($age as $x=>$x_value) { echo "Key=" . $x . ", ...
- Ubuntu16 nginx安装http_image_filter_module模块
目录 配置image_filter 配置 重启nginx 如何安装呢? 安装image_filter模块依赖的库. 查看之前的配置 添加上图片模块[由于它是系统模块,不需要额外下载,直接添加就可以了] ...
- mac上将代码上传到github以及github对100M以上文件限制上传的处理(lfs)。
前言 有时我们会写一些小程序来学习新的知识,但是完事之后过一段时间可能会忘记,最好的办法就是找到原来的代码看一看.现在可以将代码免费托管到一些网站上,其中最著名的非github莫属了, 今天就把这个过 ...
- Python 中的那些坑总结——持续更新
1.三元表达式之坑 很显然,Python把第一行的(10 + 4)看成了三元表达式的前部分,这个坑是看了<Python cookbook>(P5)中学到的,书中的代码: 2.Python生 ...
- SNMP:使用net-snmp捕捉trap
管理端:172.18.0.135 win7系统 代理端:172.18.0.212 Debian7.2 前提:代理端已配置snmp,可正常实现用SNMP协议实现系统信息监控 1.管理端下 ...
- wikioi 1028 花店橱窗布置 最大权匹配
中文题意不描述. 链接:http://wikioi.com/problem/1028/ 这题一开始很裸的最大权二分匹配.但是原来没有接触过,KM的这个最大权不大会.然后一开始以为用最大费用最大流直接就 ...
- Facebook的工程师文化——《打造facebook》读后感
在今年北京的QCon大会上听了facebook早期中国籍工程师王淮的演讲,受益匪浅,主题是如何打造高效能团队,主要介绍他在facebook的一些经历和管理上的经验分享.现在的他是一名天使投资人,投资的 ...