在计算机领域,虚拟化技术从初概念的提出到现在已经走过了几十个年头。虚拟化技术在很多领域都已经被广泛运用,但我们常用的x86平台却迟迟没有提供硬件级虚拟化支持。近几年来x86平台硬件性能大幅提高,硬件资源浪费的现象越来越严重。而虚拟化技术可以在一台计算机上运行多个独立的虚拟操作系统,维护成本和其它非技术成本会有相当程度的降低。随着英特尔和AMD的硬件辅助虚拟化技术的成熟,虚拟化技术成了近来IT界的热点话题。然而,大家对于虚拟化的认识大多还停留在字面理解上,什么是虚拟化?x86硬件辅助虚拟化(Intel VT和AMD-V)又是怎么一回事呢?希望本文能够为大家解开谜团。
2005年英特尔发布了第一款支持虚拟化技术的处理器,其竞争对手AMD也在2006年紧接着将虚拟化技术应用到处理器产品上。随着两大核心平台厂商虚拟化技术的逐渐成熟并获得周边虚拟化软件厂家的支持,硬件辅助虚拟化正以不可阻挡之势来到众人面前,越来越多的桌面CPU和芯片组开始支持虚拟化技术,让这个以前主要应用在服务器和大型机领域的技术渐渐走入寻常百姓家。从表格中大家就能够看出,硬件辅助虚拟化技术可以说囊括了计算机体系架构中重要的几个方面,而且还在一直发展当中。到现在为止,两家的CPU虚拟化技术走过了四五年时间已经慢慢成熟,内存和I/O虚拟化也都有了成熟的规范,可以说已经进入了虚拟化2.0的时代。
英特尔/AMD硬件辅助虚拟化技术对比
虚拟化起源于对分时系统的需求,在1959年的国际信息处理大会上,一篇名为《大型高速计算机中的时间共享》被认为是虚拟化技术的早论述。抽象地说,虚拟化是资源的逻辑表示,它不会受物理限制的约束。在计算机科学方面的虚拟化定义有很多种,其中有一种定义笔者认为相对更贴切和便于理解:“虚拟化是以某种用户和应用程序都可以很容易从中获益的方式来表示计算机资源的过程,而不是根据这些资源的实现、地理位置或物理包装的专有方式来表示它们。换句话说,它为数据、计算能力、存储资源以及其它资源提供了一个逻辑视图,而不是物理视图。”
在正文开始之前,我们先来解读一下本文的主题——x86硬件辅助虚拟化。“认请自己的位置”是老人们给我们的教诲,所以要认识x86硬件辅助虚拟化首先必须明白它在虚拟化技术中英特尔/AMD硬件辅助虚拟化技术对比的“位置”。虚拟化技术应用十分广泛,分类方法也多种多样,下图是笔者根据国外一些虚拟化大师的介绍并融入自己的理解绘制而成的。硬件辅助虚拟化只是“虚拟化-系统虚拟化-平台虚拟化”体系末端的一个分支,包括x86硬件辅助虚拟化和非x86硬件辅助虚拟化。支持虚拟化的硬件技术非常多,我们这次要讲的Intel VT和AMD-V只是其中的两项而已。
硬件辅助虚拟化是虚拟化技术中非常小的一个范畴
提供虚拟机支持的硬件技术清单
硬件辅助虚拟化属于系统虚拟化类别,其终的呈现方式是虚拟机,因此要了解硬件辅助虚拟化,我们首先需要做好前期的知识储备:什么是系统虚拟化,什么是虚拟机?
在x86运行模式中有一种可能一些老玩家还会有印象:虚拟8086模式(Virtual 8086 Mode),它是为了让一些老程序能够在保护模式下运行而提供的。大家在获得便利的同时可能忽略了一点,这其实就是x86给大家带来的虚拟化技术。其实系统虚拟化就是对计算机这个“抽象对象”的虚拟化,我们可以认为它的实现形式是在系统中加入一个虚拟化层,虚拟化层将下层的资源抽象成另一形式的资源,提供给上层系统使用。
虚拟化层直接加到了传统的计算机体系层次结构中,难道不会破坏原有的体系结构吗?其实虚拟化层从某种意义上说就像一个替代品,谁的替代品呢?硬件抽象层和API抽象层的替代品,它们只不过是在一定程度上取代了系统中原有硬件抽象层和API抽象层的部分功能,使得工作在这个代工的虚拟化层上面的客户机操作系统能够正常工作而已。
前面给大家讲解了虚拟化及计算机体系中抽象层的概念,当我们把虚拟化概念应用到计算机(具体的机器)上时,虚拟机的概念就出现了。虚拟机是指在一个硬件平台上模拟多个独立的、ISA结构和实际硬件相同的虚拟硬件系统,在每个虚拟硬件系统上都可以运行不同的操作系统(Guest OS),这些客户操作系统通过虚拟机监视器(VMM,后面会讲到其类型)访问实际的物理资源。1974年Popek和Goldberg在《Formal Requirements for Virtualizable Third Generation Architectures》一文是这样描述虚拟机的:“它可以看作是物理机的一种高效隔离的复制”。
虚拟机通过增加了一个新的软件层——虚拟机监控器(VMM)而使得其上运行的多个操作系统可以共享硬件资源
从图中我们可以看到计算机体系结构存在两个抽象层:硬件抽象层(HAL)和API抽象层。在计算机中,硬件抽象层(Hardware Abstraction Layer,HAL)是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化。它隐藏了特定平台的硬件接口细节,允许计算机操作系统在逻辑层而不是硬件层与硬件设备交互。调用程序不用了解硬件的具体设计细节,只需要给出抽象层所需的参数即可。这个抽象接口通常包括CPU的各种寄存器、内存管理模块和I/O端口等信息(需要注意的是,CPU、内存和I/O正是英特尔和AMD硬件辅助虚拟化技术中主要的三个方向)。
API抽象层抽象的是一个进程所能控制的系统功能的集合,包括创建新进程、内存申请和归还、进程间同步与共享、文件系统和网络操作等。虚拟化和计算机体系中的抽象层有着非常密切的关系,通常虚拟化技术就是对体系中的相关抽象层的模拟替代,让虚拟软件层上面的客户机操作系统产生一定的“错觉”,而平台虚拟化和应用程序虚拟化在一定程度上就是取代计算机体系中的硬件抽象层和API抽象层的工作。诸如硬件辅助虚拟化、ISA虚拟化其实都是属于硬件抽象层虚拟化范畴之内,而JVM之类的高级语言虚拟化则是API抽象层虚拟化的典范。
大家在谈到虚拟机时可能会有不同的看法:编程的朋友肯定对JVM不会陌生,JVM本身就是一种虚拟机;而喜欢系统虚拟软件的朋友则对VMware、Xen和微软这些虚拟化厂家的虚拟化产品有着更实际的理解。大家只知道它们是不同类别的虚拟机,但是它们之间是如何分类的呢?哪种虚拟机与Intel VT和AMD-V的关联性大呢?
根据笔者的理解,虚拟机可以分为进程虚拟机和系统虚拟机两大类,进程虚拟机支持ABI——用户指令加上系统调用;系统虚拟机则支持完整的ISA——包括用户指令和系统指令。在这个分类方法中,又可以根据客户机和本地机(Host Machine,在虚拟化资料中也常常称其为宿主机)是否使用了相同的ISA进行次级细分。
虚拟机大致可分为两大类,并可进一步细分
为了简化讲解,我们只考虑和硬件虚拟化关系为密切的、在相同ISA情况下的系统虚拟机(右图中黑框圈选的地方,因为大部分读者接触不到不同ISA指令集转换的情况)分类情况。前面我们提到的VMware、Xen的虚拟软件产品都属于系统虚拟机类别,而Intel VT和AMD-V等x86硬件辅助虚拟化技术能够提升系统虚拟机的执行性能。
大家谈到虚拟化时常用的一个词就是VMM(也称作Hypervisor,虚拟机监控器,基本上大家可以认为就是前文讲到的那个虚拟化层,抽象层的替代品),在系统虚拟机中虚拟软件常常被称为VMM,VMM在虚拟机中可以算是为关键的组件,对于系统虚拟机的分类就是对虚拟机监视器(VMM)的分类。VMM一般有三种类型,分别是独立(Type-1)、宿主(Type-2)和混合(Hybrid)类型。不论是哪一种系统虚拟机模型,只要它能够提供对Intel VT和AMD-V的支持,都可以在一定程度上减少虚拟化软件带来的性能开销(早期的RISC硬件辅助虚拟化除外)。
虚拟软件把一个硬件平台上的ISA翻译成另一个,以构成系统虚拟机。
Type-1型VMM直接安装在物理机器上,运行在高特权模式下,而客户机系统则运行在特权较少的模式上。这种虚拟机在很多方面都是很高效的,但明显的缺点是要考虑的方面较多(比如各种驱动程序),所以设计比较复杂,VMware的ESX server就属于这种类型。
Type-2型VMM类似于在操作系统上安装的应用程序,VMM可以依赖主机操作系统提供设备驱动和其它底层服务,因此不需要考虑大量的设备驱动问题,VMM体积较小。大家常用的VMware Workstation和JVM都属于此类型,这种虚拟机的缺点是会损失一些效率,因为当请求操作系统服务时要通过更多的软件层次,来回的次数也更多。
混合型是Type-1和Type-2的结合体,在这个类型中VMM和主机操作系统处于平行关系,微软的Virtual Server 2005R2以及近非常受大家关注的Xen就是混合型的典范。
ISA是Instruction Set Architecture的简写,译为指令集体系结构。在这个结构中有两个部分是和虚拟机密切相关的,一个是用户指令集(User ISA),另一个是系统指令集(Syetem ISA)。
用户指令集是应用程序可直接调用的,而系统指令集则是操作系统才能看到的,负责管理硬件资源。ABI是Application Binary Interface的简写,译为应用二进制接口。它包括两个主要组件,一个是用户指令集,另一个则是系统调用接口(System Calls)。
Popek和Goldberg在1974年发表的那篇论文中给出了一个真正的VMM必须满足的三个条件:高效性、资源控制和同质性。高效性是指所有的安全指令都可以在本地硬件上直接运行而不需要VMM的干预或仿真,资源控制是指任何客户机软件都不能改变它可用的系统资源分配,同质性是指抛开性能略微下降的因素,虚拟机上执行的任何程序的行为必须和在本地机器上运行一样。这里面我们之所以重点关注高效性,是因为x86指令集系统本身存在问题——有少部分指令不能在以前的虚拟化环节中进行正常VMM陷入,导致指令执行失败,使得这个条件难以满足。要理解其中的问题,我们首先要了解CPU虚拟化的基本原理、特权级别和敏感指令。
VMM通常分为三种类型
在VMM对硬件资源虚拟化的过程中,CPU虚拟化是非常重要的一个环节。CPU虚拟化是为物理机器上的每一个虚拟机提供一个或者多个虚拟CPU(简称VCPU),每个VCPU分时复用物理CPU,在任意时刻一个物理CPU只能被一个VCPU使用。VMM要在整个过程中合理分配时间片以及维护所有VCPU的状态(资深一些的读者应该会联想到现代多任务操作系统中TSS工作机理以及超线程技术中涉及到的上下文切换,是不是有似曾相识的感觉呢?),当进行VCPU切换时,要保存当前VCPU的状态,将被调度的VCPU状态载入物理CPU,可见如何保证VCPU的正确运行和合理调度是CPU虚拟化技术中需要解决的问题。
Type-2型VMM更易使用但是会损失一定效率
大部分的现代计算机体系结构都有两个或两个以上的特权级别,用来分隔内核和应用软件。以x86为例,为了得到更高的保护控制,在x86的保护模式下定义了当前特权级别(Current Previleged Level,简称CPL),一共有四个特级层次(0 to 3)被定义,我们一般称之为Ring。Ring后面的数字越大特权越小,我们的操作系统一般都运行在Ring0上,而Ring1和2一般用来支持设备驱动,Ring3上面跑的就是应用软件了。而在现在的x86处理器中,64位架构已经非常普遍,64位CPU因为必须支持页表模式,所以只有两个特权级别,我们可以简单理解为Ring0和Ring3(实际上另有明确定义),这种模型我们常称为0/3模型。
系统中有一些关键操作指令只能在高特权级别上执行,它们一般被称为特权指令,特权指令仅仅在当前的特权级别为零时(CPL=0)才会执行。如果在非特权级别上试图执行特权指令,将生成一个一般保护异常(这通常会生成一个应用程序错误),而非特权指令则可以在任何一个权限级别执行。
在虚拟化世界的VMM模型中,我们可以看到所有的客户机操作系统都运行在非特权模式下,即非Ring0级。因为Guest OS已经不处在特权级别,所以存在一部分原本应该在特权级别执行但现在因为层级权限不够必须转交VMM进行处理的指令,这部分指令就叫敏感指令。
x86的敏感指令中明显有一部分漏网之鱼
而根据Popek和Goldberg的定义,指令集支持虚拟化的前提是:所有敏感指令都是特权指令。很可惜x86指令集不能满足这个要求,这是它和RISC架构相比的一个不足。
在IBM之类的RISC指令集方面,因为敏感指令全部是特权指令,所以敏感指令的执行都可以被VMM捕获,而在x86方面,因为有一部分敏感指令不属于特权指令,变成了非特权指令,而非特权指令在较低的特权级别上是可以直接执行的,也就是说VMM不会处理这些指令。这样就势必会带来问题,试想一个不受虚拟化软件层控制的指令却工作在虚拟化层之上,这是怎样一个情景?x86至少有十几条敏感指令是不会引发异常的非特权指令,在IA-32指令集中,我们称这些非特权级别的敏感指令为临界指令,它们可以分成两类:
敏感寄存器指令:它们读取或者修改敏感寄存器和(或者)敏感内存数据区所存放的内容,比如时钟寄存器、中断寄存器。
1.SGDT、SIDT、SLDT
2.SMSW
3.PUSHF、POPF
保护系统指令:涉及存储保护系统、内存或者地址定位系统。
1.LAR、LSL、VERR、VERW
2.POP
3.PUSH
4.CALL、JMP、INT n、RET
5.STR
6.MOV
我们用一个实际的例子来解释x86指令集的虚拟化漏洞。SMSW指令(取机器状态字的指令)是为了向下兼容老式处理器,这个指令应该由操作系统完成,也就是说需要Ring0才可以,但很可惜它没有被放在特权指令中。在虚拟化环境中,客户机操作系统都工作在非特权层次上(一般为Ring1或者Ring3),前面我们讲到非特权指令在较低特权级别时可以不被VMM捕获而直接执行。
不同的特权级别满足不同程序运行的需求
客户机操作系统在执行这个指令时,直接取到的是真实机器的值(假设取值1为保护模式,0为实模式),现在的VMM一般都工作在保护模式下,如果客户机操作系统正好运行在实模式下,那么问题就出来了,SMSW取到的值是1,表示系统运行在保护模式下,而不是真正的客户机操作系统的实模式的返回值0,这显然是不正确的。
讲到这里,大家应该对虚拟化和虚拟机的定义以及VMM有了一个整体的认识,也搞明白了x86指令集为什么是不可虚拟化架构,这为我们更好地理解后续要讲解的硬件辅助虚拟化奠定了一定的理论基础。下一次我们就给大家讲解传统CPU虚拟化模型的技术(特权解除和先陷入后模拟)以及软件CPU虚拟化和硬件CPU辅助虚拟化的解决方法,敬请关注!
虚拟化技术优势日益体现,不仅大幅度降低了IT支出成本、减少能源浪费,而且还极大地增强了系统整体安全性和可靠性。软硬件厂商未来可能携手提高虚拟化产品的自身性能以及提供更丰富的功能。基于主机操作系统的虚拟机产品以及硬件虚拟化技术得到更广泛应用。硬件厂商在操作模式间的转换速度、TLB性能、内存虚拟化和I/O虚拟化等方面加以改进和完善;软件厂商则利用二进制动态翻译及程序行为分析的技术减小性能开销,利用内存和存储的重复删除技术降低资源开销。而分布式文件系统和分布式共享内存等技术的引入将有助于打造一个高可用、高容错的分布式虚拟化软件平台,便于虚拟机的部署和动态迁移。