QEMU-KVM的初始化与客户系统的执行
2013-07-19 17:11
295 查看
本博文为原创,遵循CC3.0协议,转载请注明出处:/article/8087643.html
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
虚拟机运行概览
首先直观的了解一下利用QEMU运行客户虚拟机的流程。
在命令行中运行QEMU的系统模式的可执行文件,参数声明虚拟CPU的个数,内存大小,指定已经安装好的硬盘镜像,启动QEMU虚拟机主窗口。启动命令格式举例:
以下为笔者的Mac-mini上弹出QEMU虚拟机界面的图示:
QEMU的核心初始化流程
客户系统运行之前,QEMU作为全系统模拟软件,需要为客户系统模拟出CPU、主存以及I/O设备,使客户系统就像运行在真实硬件之上,而不用对客户系统代码做修改。
如概览部分所示,由用户为客户系统指定需要的虚拟CPU资源(包括CPU核心数,SOCKET数目,每核心的超线程数,是否开启NUMA等等),虚拟内存资源,具体参数设置参见${QEMU}/qemu-options.hx。创建QEMU主线程,执行QEMU系统的初始化,在初始化的过程中针对每一个虚拟CPU,单独创建一个posix线程。每当一个虚拟CPU线程被调度到物理CPU上执行时,该VCPU对应的一套完整的寄存器集合被加载到物理CPU上,通过VM-LAUNCH或VM-RESUME指令切换到非根模式执行。直到该线程时间片到,或者其它中断引发虚拟机退出,VCPU退出到根模式,进行异常处理。
如下图所示,当用户运行QEMU的System Mode的可执行文件时,QEMU从${QEMU}/vl.c的main函数执行主线程。以下着重分析,客户系统启动之前,QEMU所做的初始化工作:
1.处理命令行参数:
进入vl.c的main函数,首先有一个很长的for(;;)循环,用于分析处理通过命令行传进来的参数,进行相应系统的初始化设置。比如创建多少VCPU,是否开启NUMA,分配多少虚拟内存资源等等。
2.选择虚拟化方案:
configure_accelerator()函数,选择使用哪种虚拟化解决方案。
accel_list[] = {
{ "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
{ "xen", "Xen", xen_available, xen_init, &xen_allowed },
{ "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
{ "qtest", "QTest", qtest_available, qtest_init, &qtest_allowed },
};
accel_list[]数组声明了QEMU使用的系统模拟方案。“tcg”模式是不使用任何硬件虚拟化辅助方式,采用基于二进制指令翻译的方式,将目标平台的指令代码通过一个叫做TCG的模块翻译为本机可以执行的指令。“xen”、“kvm”分别为两种主流的开源虚拟化解决方案。本文主要针对kvm这种硬件辅助的虚拟化解决方案。
3.初始化内存布局:
新版本的QEMU(1.4)中,cpu_exec_init_all()函数只负责注册主存与IO内存两个顶层的memory_region,并且注册memory_listener。
4.虚拟客户机硬件初始化:
在完成了QEMU自身的初始化工作后,便开始了客户系统核心的初始化工作,主要是QEMU根据命令行参数,为客户系统创建虚拟的CPU、内存、I/O资源。核心过程是machine->init(&args),对于x86目标平台,实际调用的是pc_init1函数。下面着重分析该函数。
4.1 VCPU初始化pc_cpus_init()
pc_init1的函数调用关系如下图所示,对于每一个即将创建的VCPU(个数由命令行传入smp_cpus),执行cpu_x86_init,逐层调用后,由qemu_kvm_start_vcpu创建一个VCPU线程,新的VCPU线程将执行qemu_kvm_cpu_thread_fn函数,逐层调用后经过kvm_vcpu_ioctl系统调用切换到核心态,由KVM执行VCPU的创建工作,包括创建VMCS等非根模式下工作所需要的核心数据结构。
4.2 pc_memory_init初始化主存空间
利用mmap系统调用,在QEMU主线程的虚拟地址空间中申明一段连续的大小的空间用于客户机物理内存映射。在QEMU的内存管理结构中逐步添加subregion。此处添加了低于4g的memory_region,高于4g的memory_region,BIOS的memory_region。并调用bochs_bios_init,初始化BIOS。
4.3 i440fx_init初始化桥片及总线结构
4.4 pc_cmos_init初始化CMOS及时钟
客户系统的执行流程
在创建了全部VCPU后,这些VCPU线程并没有被立即调度执行,直至vl.c的main函数执行完全部初始化工作后,调用resume_all_vcpus(),将pcpu->stop和 pcpu->stopped 置为false,当VCPU线程再次被调度到物理CPU上执行时,VCPU正式开始工作。
由于pc_memory_init阶段已将BIOS初始化,创建了“bios.bin”文件到内存的映射,已处于非根模式下的VCPU到客户物理地址0xFFFF0(即“bios.bin”文件被映射到的地址的一个线性偏移)处,获取第一条指令,开始执行客户系统代码。
此时多个VCPU线程由宿主系统轮流调度执行,QEMU主线程处于循环中,用于接收来自客户系统传回的I/O模拟请求。每一个VCPU线程,只要被调度的物理CPU上,便切到非根模式执行客户系统代码,产生需要退出的异常时(如EPT缺页,处理I/O指令等),保存异常原因到VMCS,切换到根模式下,由KVM捕获该异常,查询VMCS异常号执行相应处理,完成后再切换回非根模式,如此循环往复执行下去。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
虚拟机运行概览
首先直观的了解一下利用QEMU运行客户虚拟机的流程。
在命令行中运行QEMU的系统模式的可执行文件,参数声明虚拟CPU的个数,内存大小,指定已经安装好的硬盘镜像,启动QEMU虚拟机主窗口。启动命令格式举例:
qemu-system-x86_64 --enable-kvm -cpu host \ -smp cores=4,threads=2,sockets=4 \ -m 16384 -k en-us -hda /pps/guohongwei/vm_test/ubuntu.img -monitor stdio
以下为笔者的Mac-mini上弹出QEMU虚拟机界面的图示:
QEMU的核心初始化流程
客户系统运行之前,QEMU作为全系统模拟软件,需要为客户系统模拟出CPU、主存以及I/O设备,使客户系统就像运行在真实硬件之上,而不用对客户系统代码做修改。
如概览部分所示,由用户为客户系统指定需要的虚拟CPU资源(包括CPU核心数,SOCKET数目,每核心的超线程数,是否开启NUMA等等),虚拟内存资源,具体参数设置参见${QEMU}/qemu-options.hx。创建QEMU主线程,执行QEMU系统的初始化,在初始化的过程中针对每一个虚拟CPU,单独创建一个posix线程。每当一个虚拟CPU线程被调度到物理CPU上执行时,该VCPU对应的一套完整的寄存器集合被加载到物理CPU上,通过VM-LAUNCH或VM-RESUME指令切换到非根模式执行。直到该线程时间片到,或者其它中断引发虚拟机退出,VCPU退出到根模式,进行异常处理。
如下图所示,当用户运行QEMU的System Mode的可执行文件时,QEMU从${QEMU}/vl.c的main函数执行主线程。以下着重分析,客户系统启动之前,QEMU所做的初始化工作:
1.处理命令行参数:
进入vl.c的main函数,首先有一个很长的for(;;)循环,用于分析处理通过命令行传进来的参数,进行相应系统的初始化设置。比如创建多少VCPU,是否开启NUMA,分配多少虚拟内存资源等等。
2.选择虚拟化方案:
configure_accelerator()函数,选择使用哪种虚拟化解决方案。
accel_list[] = {
{ "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
{ "xen", "Xen", xen_available, xen_init, &xen_allowed },
{ "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
{ "qtest", "QTest", qtest_available, qtest_init, &qtest_allowed },
};
accel_list[]数组声明了QEMU使用的系统模拟方案。“tcg”模式是不使用任何硬件虚拟化辅助方式,采用基于二进制指令翻译的方式,将目标平台的指令代码通过一个叫做TCG的模块翻译为本机可以执行的指令。“xen”、“kvm”分别为两种主流的开源虚拟化解决方案。本文主要针对kvm这种硬件辅助的虚拟化解决方案。
3.初始化内存布局:
新版本的QEMU(1.4)中,cpu_exec_init_all()函数只负责注册主存与IO内存两个顶层的memory_region,并且注册memory_listener。
4.虚拟客户机硬件初始化:
在完成了QEMU自身的初始化工作后,便开始了客户系统核心的初始化工作,主要是QEMU根据命令行参数,为客户系统创建虚拟的CPU、内存、I/O资源。核心过程是machine->init(&args),对于x86目标平台,实际调用的是pc_init1函数。下面着重分析该函数。
4.1 VCPU初始化pc_cpus_init()
void pc_cpus_init(const char *cpu_model) { int i; /* init CPUs */ if (cpu_model == NULL) { #ifdef TARGET_X86_64 cpu_model = "qemu64"; #else cpu_model = "qemu32"; #endif } for (i = 0; i < smp_cpus; i++) { if (!cpu_x86_init(cpu_model)) { fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } } }
pc_init1的函数调用关系如下图所示,对于每一个即将创建的VCPU(个数由命令行传入smp_cpus),执行cpu_x86_init,逐层调用后,由qemu_kvm_start_vcpu创建一个VCPU线程,新的VCPU线程将执行qemu_kvm_cpu_thread_fn函数,逐层调用后经过kvm_vcpu_ioctl系统调用切换到核心态,由KVM执行VCPU的创建工作,包括创建VMCS等非根模式下工作所需要的核心数据结构。
4.2 pc_memory_init初始化主存空间
利用mmap系统调用,在QEMU主线程的虚拟地址空间中申明一段连续的大小的空间用于客户机物理内存映射。在QEMU的内存管理结构中逐步添加subregion。此处添加了低于4g的memory_region,高于4g的memory_region,BIOS的memory_region。并调用bochs_bios_init,初始化BIOS。
4.3 i440fx_init初始化桥片及总线结构
4.4 pc_cmos_init初始化CMOS及时钟
客户系统的执行流程
在创建了全部VCPU后,这些VCPU线程并没有被立即调度执行,直至vl.c的main函数执行完全部初始化工作后,调用resume_all_vcpus(),将pcpu->stop和 pcpu->stopped 置为false,当VCPU线程再次被调度到物理CPU上执行时,VCPU正式开始工作。
由于pc_memory_init阶段已将BIOS初始化,创建了“bios.bin”文件到内存的映射,已处于非根模式下的VCPU到客户物理地址0xFFFF0(即“bios.bin”文件被映射到的地址的一个线性偏移)处,获取第一条指令,开始执行客户系统代码。
此时多个VCPU线程由宿主系统轮流调度执行,QEMU主线程处于循环中,用于接收来自客户系统传回的I/O模拟请求。每一个VCPU线程,只要被调度的物理CPU上,便切到非根模式执行客户系统代码,产生需要退出的异常时(如EPT缺页,处理I/O指令等),保存异常原因到VMCS,切换到根模式下,由KVM捕获该异常,查询VMCS异常号执行相应处理,完成后再切换回非根模式,如此循环往复执行下去。
相关文章推荐
- 转【Windows源码分析】(一)初始化内核与执行体子系统
- 用buildroot qemu 执行 Android 系统
- QEMU KVM 虚拟机移植之性能提高篇小结(android 虚拟机双系统方案)
- linux之kvm安装及使用qemu工具安装系统
- 【Windows源码分析】(一)初始化内核与执行体子系统
- qemu-kvm virtio 虚拟化-----Linux客户机 virtio设备初始化
- SpirngMVC系统启动系统配置初始化执行顺序以及防止onApplicationEvent执行两次
- qemu-kvm virtio 虚拟化-----Linux客户机 virtio设备初始化
- Windows内核源码分析 1.初始化内核与执行体子系统
- 【Windows源码分析】(一)初始化内核与执行体子系统
- [转载]qemu-kvm virtio 虚拟化-----Linux客户机 virtio设备初始化
- qemu-kvm设备初始化
- 【Windows源码分析】(一)初始化内核与执行体子系统
- qemu中KVM硬件虚拟化的初始化分析 (tcg、xen、kvm、qtest)(转)
- kvm初体验——linux之kvm安装及使用qemu工具安装系统【转】
- 当引用了Properties.Settings后,如果执行的时候,出现"配置系统无法初始化" 或者 某某节点不正确
- 系统调用的初始化过程与系统调用执行过程
- Windows源码分析 - 1.初始化内核与执行体子系统
- qemu中KVM硬件虚拟化的初始化分析 (tcg、xen、kvm、qtest)(转)
- linux文件系统初始化过程(6 完结)---执行init程序