kvm虚拟化简介

1、KVM介绍

KVM是一个基于Linux内核的虚拟机,它属于完全虚拟化范畴,从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的优势所在。

2、硬件虚拟化intel vtx

2.1 问题背景

处理器一般存在应用编程接口和系统编程接口。对于x86处理器来说,应用编程接口仅向应用程序暴露了通用寄存器、RFLAGS、RIP和一组非特权指令,而系统编程接口向操作系统暴露了全部的ISA(Instruction Set Architecture)。传统的进程/线程模型也是对处理器的一种虚拟化,但只是对处理器的应用编程接口的虚拟化,而所谓的系统虚拟化(system virtualization)是要实现处理器系统编程接口的虚拟化。从这个角度讲,系统虚拟化与进程/线程模型相比并无本质的区别。
处理器虚拟化的本质是分时共享。实现虚拟化需要两个必要条件,第一是能够读取和恢复处理器的当前状态,第二是有某种机制防止虚拟机对系统全局状态进行修改。
第一个必要条件没有必要一定由硬件来实现,虽然硬件实现可能比软件实现更为简单。例如,x86处理器对多任务,也就是应用编程接口虚拟化,提供了硬件的支持,软件通常只需要执行一条指令,就可以实现任务切换,处理器硬件负责保存当前应用编程接口的状态,并为目标任务恢复应用编程接口的状态。但操作系统并不一定要使用处理器提供的这种虚拟化机制,完全可以使用软件来完成应用接口状态的切换。例如,Linux就没有使用x86处理器提提供多任务机制,完全依赖软件实现任务切换。
第二个必要条件一定要由硬件来实现,通常处理器采用多模式操作(multi-mode operation)来确保这一点。在传统x86处理器上,共有4种模式的操作,也就是常说的4个特权级。虚拟机(这里指进程/线程)通常运行在特权级3上,而虚拟机监控器(这里指操作系统)运行于特权级0上,进程/线程的所有访问全局的操作,如访问共享的操作系统所在的地址空间,访问I/O等等,均会导致异常的发生,被操作系统所截获并处理,使操作系统有机会向进程/线程提供一个虚拟的世界。

2.2 传统处理的解决

许多基于传统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平台的虚拟化漏洞。

2.3 备注

但是,光靠特权级只能解决虚拟机的一部分问题。比如你在windows XP中安装windows 98,两个操作系统都使用CPU硬件中断CR3来进行线程上下文切换(CPU一共有8个中断寄存器,从CR0到CR7,但是Inter规定硬件中断只有4个,CR0到CR3,剩下的保留或者作为标志位)那么怎么知道到底是XP还是98在进行线程切换呢?虚拟机原来的解决方案是把真实操作系统声明为主操作系统,运行于特权级0之上(本例中主操作系统是XP),而把虚拟操作系统(本例中是98)声明为副操作系统,运行于特权级3之上。换句话说虚拟机就是主操作系统的一个应用程序而已,虚拟机上的任何改变都不会影响主操作系统。这是一个好处,虚拟机上的任何操作不影响主操作系统;但是坏处也是显而易见的,由于必须让虚拟机的操作系统也“认为”自己运行在特权级0之上(否则副操作系统就无法运行了),所以虚拟机软件必须不断监视副操作系统,一旦副操作系统发出特权级0的指令,虚拟机软件就必须通过CPU硬件截获指令(特权级3试图执行特权级0的指令时CPU就会抛出异常)并通过主操作系统执行完毕之后再将结果返回副操作系统。现代操作系统每秒钟要执行数万条指令,因此虚拟机软件频繁的进行特权切换造成的开销是很大的,所以纯软件虚拟机的效率只有50%-60%。
好在CPU制造商意识到了这个问题。2008年Inter和AMD都推出了硬件虚拟机技术。Inter叫VT-x,它实际上就是在硬件上多了一个虚拟机监视器VMM,由VMM来承担特权级别切换任务。如果操作系统安装虚拟机,那么主操作系统就相当于运行在真正的的特权级0上(也可以理解为运行在更高的特权级别-1上),而副操作系统运行于受VMM控制的特权级0上,这样的分配免除了软件频繁进行特权切换造成的可观开销,所以带有VT-x功能的虚拟机效率最高能达到95%左右。

2.4 VT-x

2.4.1 VMX工作模式

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)使虚拟机重新获得控制权。

2.4.2 VMCS结构

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设计了一个Virtual-Machine Control Structure(VMCS,虚拟机控制结构)的数据结构,包括了Guest-State Area(客户状态区)和Host-State Area(主机状态区),用来保存虚拟机以及主机的各种状态参数,并提供了VM entry和VM exit两种操作在虚拟机与VMM之间切换,用户可以通过在VMCS的VM-execution control fields里面指定在执行何种指令/发生何种事件的时候,VMX non-root operation环境下的虚拟机就执行VM exit,从而让VMM获得控制权,因此VT-x解决了虚拟机的隔离问题,又解决了性能问题。

VT技术有两种转换,分别为VM Entry和VM Exit。VM Entry就是从VMX root模式切换到VMX non-root模式,简单的说,就是VMM切换到虚拟机这个转换过程。VM Exit就是从VMX non-root模式切换到VMX root模式,同理可理解为从虚拟机返回到VMM这个过程。
在这里插入图片描述
另外每个硬件虚拟的CPU都有一个表示其状态以及控制其特性的结构,VT-x技术的叫做VMCS。该结构包含3个部分:版本标志、VMX退出原因、数据区。而数据区则包含大量与CPU状态和控制相关的信息,包括虚拟机状态保存区(各种寄存器)、宿主机状态保存区、虚拟机运行控制域、VM Entry行为控制域、VM Exit行为控制域、VM Exit信息域。
支持VT-x技术的指令集叫做VMX指令集,该指令集总共有10条指令,如表1.1所示VMX指令集

指令 作用
VMPTRLD 加载一个VMCS结构体指针作为当前操作对象
VMPTRST 保存当前VMCS结构体指针
VMCLEAR 清除当前VMCS结构体
VMREAD 读VMCS结构体指定域
VMWRITE 写VMCS结构体指定域
VMCALL 引发一个VM Exit事件,返回到VMM
VMLAUNCH 启动一个虚拟机
VMRESUME 从VMM返回到虚拟机继续运行
VMXOFF 退出VMX操作模式
VMXON 进入VMX操作模式

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还提供了中断事件退出机制和中断事件注入机制,方便对设备中断进行虚拟化。

2.5 KVM实现

作为VMM,KVM分为两部分,分别是运行于Kernel模式的KVM内核模块和运行于User模式的Qemu模块。这里的Kernel模式和User模式,实际上指的是VMX根模式下的特权级0和特权级3。另外,KVM将虚拟机所在的运行模式称为Guest模式。所谓Guest模式,实际上指的是VMX的非根模式。
在这里插入图片描述

利用VT-x技术的支持,KVM中的每个虚拟机可具有多个虚拟处理器VCPU,每个VCPU对应一个Qemu线程,VCPU的创建、初始化、运行以及退出处理都在Qemu线程上下文中进行,需要Kernel、User和Guest三种模式相互配合,其工作模型如图2.1所示。Qemu线程与KVM内核模块间以ioctl的方式进行交互,而KVM内核模块与客户软件之间通过VM Exit和VM entry操作进行切换。
Qemu线程以ioctl的方式指示KVM内核模块进行VCPU的创建和初始化等操作,主要指VMM创建VCPU运行所需的各种数据结构并初始化。其中很重要的一个数据结构就是VMCS,其初始化配置见附2。
初始化工作完成之后,Qemu线程以ioctl的方式向KVM内核模块发出运行VCPU的指示,后者执行VM entry操作,将处理器由kernel模式切换到Guest模式,中止宿主机软件,转而运行客户软件。注意,宿主机软件被中止时,正处于Qemu线程上下文,且正在执行ioctl系统调用的kernel模式处理程序。客户软件在运行过程中,如发生异常或外部中断等事件,或执行I/O操作,可能导致VM exit,将处理器状态由Guest模式切换回Kernel模式。KVM内核模块检查发生VM exit的原因,如果VM exit由于I/O操作导致,则执行系统调用返回操作,将I/O操作交给处于User模式的Qemu线程来处理,Qemu线程在处理完I/O操作后再次执行ioctl,指示KVM切换处理器到Guest模式,恢复客户软件的运行;如果VM exit由于其它原因导致,则由KVM内核模块负责处理,并在处理后切换处理器到Guest模式,恢复客户机的运行。

发布了27 篇原创文章 · 获赞 1 · 访问量 888

猜你喜欢

转载自blog.csdn.net/luuJa_IQ/article/details/104198113