资源描述
KVM分析报告虚拟化技术工作组2008-12-311. 概述1.1. KVM简介KVM是以色列开源组织Qumranet开发的一个开源虚拟机监控器,从Linux-2.6.20开始被包含在Linux内核中。KVM基于x86硬件虚拟化技术,它的运行要求Intel VT-x或AMD SVM的支持。一般认为,虚拟机监控的实现模型有两类:监控模型(Hypervisor)和宿主机模型(Host-based)。由于监控模型需要进行处理器调度,还需要实现各种驱动程序,以支撑运行其上的虚拟机,因此实现难度上一般要大于宿主机模型。KVM的实现采用宿主机模型(Host-based),由于KVM是集成在Linux内核中的,因此可以自然地使用Linux内核提供的内存管理、多处理器支持等功能,易于实现,而且还可以随着Linux内核的发展而发展。另外,目前KVM的所有I/O虚拟化工作是借助Qemu完成的,也显著地降低了实现的工作量。以上可以说是KVM的优势所在。1.2. 本报告的组织本报告的第2章介绍处理器虚拟化技术及KVM实现,第3章介绍内存虚拟化技术及KVM实现,第4章介绍I/O虚拟化技术及KVM实现。1.3. 说明本报告仅分析KVM中与Intel VT-x相关的实现,不考虑KVM中与AMD SVM相关的实现,因此有关术语的使用与Intel VT-x保持一致。2. 处理器虚拟化2.1. VT-x技术我们知道处理器一般存在应用编程接口和系统编程接口。对于x86处理器来说,应用编程接口仅向应用程序暴露了通用寄存器、RFLAGS、RIP和一组非特权指令,而系统编程接口向操作系统暴露了全部的ISA(Instruction Set Architecture)。传统的进程/线程模型也是对处理器的一种虚拟化,但只是对处理器的应用编程接口的虚拟化,而所谓的系统虚拟化(system virtualization)是要实现处理器系统编程接口的虚拟化。从这个角度讲,系统虚拟化与进程/线程模型相比并无本质的区别。处理器虚拟化的本质是分时共享。实现虚拟化需要两个必要条件,第一是能够读取和恢复处理器的当前状态,第二是有某种机制防止虚拟机对系统全局状态进行修改。第一个必要条件没有必要一定由硬件来实现,虽然硬件实现可能比软件实现更为简单。例如,x86处理器对多任务,也就是应用编程接口虚拟化,提供了硬件的支持,软件通常只需要执行一条指令,就可以实现任务切换,处理器硬件负责保存当前应用编程接口的状态,并为目标任务恢复应用编程接口的状态。但操作系统并不一定要使用处理器提供的这种虚拟化机制,完全可以使用软件来完成应用接口状态的切换。例如,Linux就没有使用x86处理器提提供多任务机制,完全依赖软件实现任务切换。第二个必要条件一定要由硬件来实现,通常处理器采用多模式操作(multi-mode operation)来确保这一点。在传统x86处理器上,共有4种模式的操作,也就是常说的4个特权级。虚拟机(这里指进程/线程)通常运行在特权级3上,而虚拟机监控器(这里指操作系统)运行于特权级0上,进程/线程的所有访问全局的操作,如访问共享的操作系统所在的地址空间,访问I/O等等,均会导致异常的发生,被操作系统所截获并处理,使操作系统有机会向进程/线程提供一个虚拟的世界。系统虚拟化与进程/线程模型相比并无本质的区别。x86处理器完全有机会以较小的代价提供对系统虚拟化的支持,但很可惜Intel没有考虑那么长远。x86的4个特权级对于实现系统虚拟化已经足够了,但传统的x86处理器上,许多特权指令要求必须在特权级0上执行,如LGDT,因此通常操作系统都占用了特权级0,也就没有特权级供虚拟机监控器使用了。为此,许多基于传统x86处理器的虚拟化软件不得不采用ring deprivileging方法,让操作系统运行于特权级1,而由虚拟机监控器使用特权级0。ring deprivileging方法带来了许多问题,包括:ring aliasing、address space compression、nonfaulting accessing to privileged state、adverse impact on guest transitions、interrupt virtualization、access to hidden state等问题,通常将以上问题统称为x86平台的虚拟化漏洞。ring aliasing问题是指,采用ring deprivileging方法时,由于处理器的CPL保存在CS的低两位,所以操作系统通过执行PUSH CS指令和一条POP EAX指令可以很容易发现其目前不在特权级0上执行,这违背了虚拟化对操作系统透明的原则。address space compression问题是指,操作系统通常期望能够访问整个4GB线性地址空间,但虚拟机监控器可能也需要占用操作系统的一部分线性地址空间,以便其能够方便地访问操作系统的地址空间。但如果操作系统是运行于特权级1,那么操作系统也同样可以访问虚拟机监控器的存储空间,对虚拟机监控器造成威胁。nonfaulting accessing to privileged state问题是指,Intel的特权级机制不能确保所有的访问处理器状态的指令在低特权级状态下执行时都产生故障(Fault),这使得操作系统在访问某些处理器状态时虚拟机监控器无法获得控制,也就无法对这些指令进行仿真。例如,IA-32的GDTR, LDTR, IDTR, TR包含了控制处理器状态的指针,对这些寄存器的修改只能在特权级0进行,但IA-32允许在所有的特权级中读取这些寄存器的值。操作系统可以读取这些寄存器的值,如果与真实的计算机上的值不同,操作系统就可以认为自己正运行在虚拟机环境中。adverse impact on guest transitions问题是指,为加快系统调用的速度,Intel引入了SYSENTER和SYSEXIT指令,但SYSENTER指令总是将特权级切换到0,且从0以外的特权级执行SYSEXIT指令将导致故障。因此,在采用ring deprivileging方法实现虚拟化时,SYSENTER和SYSEXIT指令总是先陷入到虚拟机监控器,经后者仿真后再交给操作系统,这使系统调用的速度减慢。interrupt virtualization问题是指,IA-32使用EFLAGS.IF位来控制中断的屏蔽,修改IF位需要在CPLpgoff = 0)page = virt_to_page(vcpu-run);#ifdef CONFIG_X86else if (vmf-pgoff = KVM_PIO_PAGE_OFFSET)page = virt_to_page(vcpu-arch.pio_data);vmx.c:2815vmx_intr_assist() 附1 KVM数据结构附2 KVM虚拟机的VMCS的基本配置字段最低配置可选配置备注pin-based vm-execution controlPIN_BASED_EXT_INTR_MASKPIN_BASED_NMI_EXITINGPIN_BASED_VIRTUAL_NMIScpu-based vm-execution controlCPU_BASED_HLT_EXITINGCPU_BASED_CR3_LOAD_EXITINGCPU_BASED_CR3_STORE_EXITINGCPU_BASED_USE_IO_BITMAPSCPU_BASED_MOV_DR_EXITINGCPU_BASED_USE_TSC_OFFSETING#ifdef CONFIG_X86_64CPU_BASED_CR8_LOAD_EXITING CPU_BASED_CR8_STORE_EXITING#endifCPU_BASED_TPR_SHADOWCPU_BASED_USE_MSR_BITMAPSCPU_BASED_ACTIVATE_SECONDARY_CONTROLS如果配置了CPU_BASED_TPR_SHADOW,则关闭CPU_BASED_CR8_LOAD_EXITING和CPU_BASED_CR8_STORE_EXITING配置,这样可以避免无谓的VM exitsecondary cpu-based vm-execution controlSECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSESSECONDARY_EXEC_WBINVD_EXITINGSECONDARY_EXEC_ENABLE_VPIDSECONDARY_EXEC_ENABLE_EPT仅当cpu-based vm-execution control中开启了CPU_BASED_ACTIVATE_SECONDARY_CONTROLS配置时,secondary cpu-based vm-execution control才有效如果启用了SECONDARY_EXEC_ENABLE_EPT配置,则关闭cpu-based vm-execution control中的CPU_BASED_CR3_LOAD_EXITINGCPU_BASED_CR3_STORE_EXITING以避免无谓的退出vm_exit control#ifdef CONFIG_X86_64VM_EXIT_HOST_ADDR_SPACE_SIZE;#endifvm_entry control附3 Intel分页机制简介在介绍内存虚拟化原理和实现之前,有必要首先介绍以下Intel处理器的分页机制。由于历史的原因,Intel处理器的分页机制比较复杂,可分为普通IA-32分页机制、支持PAE的IA-32分页机制、IA-32e分页机制和PSE-36分页机制。普通IA-32分页机制支持32位物理地址和32位线性地址。采用2级页表,页目录PD或每个页表PT中可容纳1024个32位表项,此时CR3又称为PDBR,指向页目录物理地址。支持PAE的IA-32分页机制支持36位物理地址和32位线性地址。采用3级页表,除页目录PD和页表PT之外还引入了处于第3级的页目录指针表PDPT(Page Directory Pointer Table)。PDPT只有1个,其中容纳4个64位表项,每个PD或PT容纳512个64位表项,此时CR3又称为PDPTR,指向PDPT的物理地址。IA-32e分页机制支持64位线性地址和52位物理地址,不过在目前的实现中,仅支持48位线性地址和40位物理地址。采用4级页表,除PDPT、PD和PT外,还引入了PML4T(Page Map Level 4 Table),并且每个PDPT的表项数目由PAE机制中的4项扩展为512项,每个PD和PT中包含512个表项。此时CR3又称为PML4,指向PML4T的物理地址。从Pentium III开始还支持PSE-36分页机制,支持36位物理地址和32位线性地址。该机制给出了一种除PAE以外的至此36位物理地址的方式,采用该机制需关闭PAE。仅有1张页表PD,其中包含1024个表项,每个表项中的2231以及1316位共同构成4MB页地址的高14位,线性地址的低22位用于页内索引。此时CR3称为PDBR,指向PD。如果启动了PSE机制,页的大小除了典型的4KB以外,还可能是4MB或2MB。其中,普通IA-32分页机制可支持4MB页,而支持PAE的IA-32分页机制和IA-32e分页机制支持2MB页。
展开阅读全文