QEMU KVM系列一: Intel VT-x 硬件虚拟化产生的背景

参考文章:http://blog.csdn.net/yearn520/article/details/6461047

虚拟化分为 para-virtualization 和 full virtualization. Para-Virtualization 的主要目的是在不支持硬件虚拟化的平台上面实现虚拟化,但是需要改动操作系统。而FULL virtualization是由硬件提供支持的虚拟化解决方案,不需要改动操作系统。那么intel,AMD 等CPU厂商为什么要推出硬件虚拟化呢?基于软件的虚拟化存在一些什么问题。

1. Intel 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位需要在CPL<=IOPL的情况下进行,否则将产生故障。操作系统可能需要频繁地修改IF位,会频繁地导致虚拟机监控器的陷入,影响系统性能。而且,有些情况下,虚拟机监控器需要向虚拟机注入事件,但如果虚拟机正处于中断屏蔽状态,虚拟机监控器就必须等待,直到虚拟机打开中断。虚拟机监控器为了及时得知虚拟机已打开中断,也必须截获操作系统对EFLAGS.IF位的修改。

access to hidden state问题是指,IA-32处理器的某些状态,例如段描述符高速缓存,是无法通过指令访问的。当虚拟机切换时,IA-32没有提供保存和恢复段描述符高速缓存的手段。也就是说,上文所述的实现虚拟化的第一个必要条件,能够读取和恢复处理器的当前状态,并不完全具备。

总之,虽然采用ring deprivileging方法可能实现系统虚拟化,但具有很多缺陷,且软件上比较复杂。为此,Intel提出了VT-x技术来解决系统虚拟化问题,其主要思路是增加一个新的比0还高的特权级,通常称之为特权级-1,并在硬件上支持系统编程接口状态的保存和恢复。

首先,VT-x提供了一套称作VMX(Virtual Machine eXtension)的新的工作模式,工作在该模式下的处理器又具有两类操作模式:VMX root operation和VMX non-root operation。通常,虚拟机监控器运行在VMX root operation模式下,即所谓的特权级-1,客户操作系统运行在VMX non-root operation模式下。VMX non-root operation模式仍保留4个特权级,对操作系统来说,VMX non-root operation模式与传统的x86处理器兼容,最大的差别在于当虚拟机执行一些访问全局资源的指令时将导致虚拟机退出操作(VM exit),从而使虚拟机监控器获得控制权,以便对访问全局资源的指令进行模拟。以后,虚拟机监控器可以通过虚拟机进入操作(VM entry)使虚拟机重新获得控制权。

其次,VT-x为系统编程接口状态的切换提供硬件支持。VT-x为每个虚拟机维护至少一个VMCS(Virtual Machine Control Structure)结构,其中保存了虚拟机和虚拟机监控器的系统编程接口状态。当执行VM exit和VM entry操作时,VT-x自动根据VMCS中的内容完成虚拟机和虚拟机监控器间的系统编程接口状态切换。为系统编程接口状态的切换提供硬件支持是必要的,因为x86处理器的系统编程接口相比应用编程接口要复杂的多,且在不停的变化,如较新的处理器可能增加一些MSR(Model Specific Register),这使得单独依靠软件来实现系统编程接口的保存和恢复工作变得十分复杂。另外,VT-x还提供了一组指令,使得虚拟机监控器通过一条指令就可以完成虚拟机间的切换。

VT-x解决了ring deprivileging方法的一系列问题,从硬件上堵住了所谓的x86平台的虚拟化漏洞。由于操作系统所在的VMX non-root operation模式仍具有4个特权级,使得ring aliasing问题不存在了。同时,由于SYSENTER和SYSEXIT指令所引起的adverse impact on guest transitions问题也不存在了;由于VT-x在VM exit和VM entry时完成系统编程接口的切换,也就是说虚拟机和虚拟机监控器拥有各自的GDT,也就拥有了各自的地址空间,解决了address space compression问题。同时,虚拟机和虚拟机监控器拥有各自的GDTR/IDTR等寄存器,在虚拟机中访问这些寄存器无需陷入,解决了nonfaulting accessing to privileged state问题,再者,VMCS中保存了虚拟机的段描述符高速缓存,因此在虚拟机切换时不会出现access to hidden state问题;通过对VMCS进行设置,可以使处理器在VMX non-root operation模式时的EFLAGS.IF失效,即该标志位不再对中断屏蔽产生影响,因此操作系统对EFLAGS.IF的频繁操作不会导致频繁的VM exit,解决了interrupt virtualization的问题。

VT-x提供了完备的处理器虚拟化机制,利用VT-x可以在单个硬件平台上虚拟出任意数量的虚拟处理器VCPU。VT-x除了解决了处理器虚拟化的问题之外,还为内存虚拟化和I/O虚拟化提供了支撑。在内存虚拟化方面,VT-x为影子页表的实现提供了支撑,并且在较新的处理器中还提供了EPT机制,进一步提高了内存虚拟化的效率。在I/O虚拟化方面,通过I/O位图机制可以方便地实现对Programmed I/O的虚拟化,除此之外,VT-x还提供了中断事件退出机制和中断事件注入机制,方便对设备中断进行虚拟化。

你可能感兴趣的:(QEMU,KVM,sourcecode分析系列)