虚拟化技术概要之处理器虚拟化

19 views
Skip to first unread message

hamody

unread,
Apr 13, 2010, 6:19:06 AM4/13/10
to borqs-kernel, hamody
虚拟话 grdwr....

 
 

Sent to you by hamody via Google Reader:

 
 

via 弯曲评论 by comcat on 4/12/10

VMM 对物理资源的虚拟可以分为三个部分:处理器虚拟化、内存虚拟化和 I/O 设备虚拟化。

其中以处理器虚拟化最为关键。

 

0. 体系结构背景

简而言之,处理器呈现给软件的接口就是一堆的指令(指令集)和一堆的寄存器(含用于通用运算的寄存器和用于控制处理器行为的状态和控制寄存器)。而 I/O 设备呈现给软件的接口也就是一堆的状态和控制寄存器(有些设备还有内部存储)。这些都是系统的资源,其中影响处理器和设备状态和行为的寄存器称为关键资源或特权资源,如 x86 之 CR0 ~ CR4,MIPS 的 CP0 寄存器,PowerPC 的 Privileged SPR(SPR 编号第 5 位为 1)。

可以读写系统关键资源的指令叫做敏感指令,如 x86 的 lgdt/sgdt/lidt/sidt/in/out,MIPS 的 mtc0/mfc0,PowerPC 的 mtmsr/mfmsr,SPARC 的 rdpr/wrpr 等,此类又可称为控制敏感指令。

还有一类行为敏感指令,该类指令的执行结果依赖于系统的状态(如 x86 之 popf)

现代计算机体系结构一般至少有两个特权级,(即用户态和核心态,未加虚拟化扩展的 SPARC和PowerPC 即是,MIPS 有三个特权级(外加一个 Supervisor 态),而 x86 有四个特权级 (Ring0 ~ Ring3))用来分隔系统软件和应用软件。

决大多数的敏感指令是特权指令,特权指令只能在处理器的最高特权级(内核态)执行,如果执行特权指令时处理器的状态不在内核态,通常会引发一个异常而交由系统软件来处理这个“非法访问”(陷入)。

少数敏感指令是非特权指令,如 x86 的 sgdt/sidt 等,非特权指令可以在用户态读取处理器的状态,如 sgdt/sidt 则可在用户态 (Ring3) 将 GDTR 和 IDTR 的值读取到通用寄存器中。

对于一般 RISC 处理器,如 MIPS,PowerPC 以及 SPARC,敏感指令定是特权指令,唯 x86 例外。

正是为了这个例外,造就了后来 x86 上的虚拟化技术的江湖纷争。先是以 VMware 为代表的 Full 派对无需修改直接运行理念的偏执,到后来 Xen 适当修改 Guest OS 后获得极佳的性能,以至让 Para 大热,再到后来 Intel 和 AMD 卷入战火,从硬件上扩展,一来解决传统 x86 虚拟化的困难,二来为了性能的提升;到最后硬件扩展皆为 Full 派和 Para 派所采用,自此 Para 派的性能优势再不那么明显,Full 派的无需修改直接运行的友好性渐占上风。

 

1. 经典的虚拟化方法

经典的虚拟化方法主要使用“特权解除” (Privilege deprivileging) 和“陷入 — 模拟” (Trap-and-Emulation) 的方式。即:将 Guest OS 运行在非特权级(特权解除),而将 VMM 运行于最高特权级(完全控制系统资源)。解除了 Guest OS 的特权后,Guest OS 的大部分指令仍可以在硬件上直接运行,只有当执行到特权指令时,才会陷入到 VMM 模拟执行(陷入 — 模拟)。其早期的代表系统是 IBM VM/370

由此可引入虚拟化对体系结构 (ISA) 的要求:

A. 须支持多个特权级

此亦是现代操作系统的要求

B. 非敏感指令的执行结果不依赖于 CPU 的特权级

“陷入-模拟” 的本质是保证可能影响 VMM 正确运行的指令由 VMM 模拟执行,大部分的非敏感指令还是照常运行。

C. CPU 需支持一种保护机制,如 MMU,可将物理系统和其它 VM 与当前活动的 VM 隔离

以上三个条件,现代体系结构一般都满足,唯有最后一个也是最重要的条件:

D. 敏感指令需皆为特权指令

此是为了保证敏感指令在 VM 上执行时,能陷入到 VMM,接受 VMM 的控制。

因控制敏感指令的执行可能改变系统(处理器和设备)的状态,为保证 VMM 对资源的绝对控制力维护 VM 的正常运行,这类指令的执行需要陷入而将控制权转移到 VMM,并由其模拟处理之。

行为敏感指令的执行结果依赖于 CPU 的最高特权级,而 Guest OS 运行于非最高特权级,为保证其结果正确,亦需要陷入 VMM,并由其模拟之。

 

2. x86 ISA 分析

x86 ISA 中有十多条敏感指令不是特权指令,因此 x86 无法轻松地使用经典的虚拟化技术完全虚拟化。

如:sgdt/sidt/sldt 可以在用户态读取特权寄存器 GDTR/IDTR/LDTR 的值;popf/pushf 在 Ring0 和 Ring3 的执行结果不同;其它的还有 smsw, lar, lsl, verr, verw, pop, push, call, jmp, int n, ret, str, move

关于这些指令的详细分析可以参见:”Analysis of the Intel Pentium’s Ability to Support a Secure Virtual Machine Monitor”

 

3. x86 虚拟化方法

鉴于 x86 指令集本身的局限,长期以来对 x86 的虚拟化实现大致分为两派,即以 VMWare 为代表的 Full 派和以 Xen 为代表的 Para 派。两派的分歧主要在对非特权敏感指令的处理上,Full 派采用的是动态的方法,即:运行时监测,捕捉后在 VMM 中模拟;而 Para 派则主动进攻,将所有用到的非特权敏感指令全部替换,这样就少掉了大量的陷入 —> 上下文切换 —> 模拟 —> 上下文切换过程,获得了大幅的性能提升,但缺点也很明显。后来 x86 的主要厂商 Intel 和 AMD 也卷入战火,且都引入各自的硬件虚拟化技术来扩展。

 

3.1 全虚拟化派 (Full virtualization)

秉承无需修改直接运行的理念,该派一直在对“运行时监测,捕捉后模拟”的过程,进行偏执的优化。

该派内部之实现又有些差别,其有 VMWare 为代表的 BT 和以 SUN 为代表的 Scan-and-Patch

3.1.1 基于二进制翻译 (BT) 的全虚拟化

其主要思想是在执行时将 VM 上执行的 Guest OS 之指令,翻译成 x86 ISA 的一个子集,其中的敏感指令被替换成陷入指令。翻译过程与指令执行交叉进行。不含敏感指令的用户态程序可以不经翻译直接执行。该技术为 VMWare Workstation,VMWare ESX Server 早期版本,Virtual PC 以及 QEMU 所采用。

 

3.1.2 基于扫描与修补 (Scan-and-Patch) 的全虚拟化

主要思想:

(1) VMM 会在 VM 运行每块指令之前对其扫描,查找敏感指令
(2) 补丁指令块会在 VMM 中动态生成,通常每一个需要修补的指令会对应一块补丁指令
(3) 敏感指令被替换成一个外跳转,从 VM 跳转到 VMM,在 VMM 中执行动态生成的补丁指令块
(4) 当补丁指令块执行完后,执行流再跳转回 VM 的下一条指令处继续执行

SUN 之 Virtualbox 即采用该技术。

 

3.2 OS 协助的类虚拟化派 (Paravirtualization)

其基本思想是通过修改 Guest OS 的代码,将含有敏感指令的操作,替换为对 VMM 的超调用 (Hypercall,类似 OS 的系统调用,可将控制权转移到 VMM)。该技术的优势在于 VM 的性能能接近于物理机,缺点在于需要修改 Guest OS.

该技术因 Xen 项目而广为人知。

目前嵌入式领域的虚拟化,考虑到性能的因素,亦会在可以使用经典虚拟化方法实现全虚拟的体系结构上采用类虚拟化技术。

 

3.3 硬件协助的虚拟化

鉴于 x86 在虚拟化上的缺陷,Intel 和 AMD 都引入自己的硬件虚拟化技术来协助完成虚拟化。

Intel VT-x (Virtualization Technology for x86)
Intel VT-i (Virtualization Technology for Itanium)
Intel VT-d (Virtualization Technology for Directed I/O)
AMD-V (AMD Virtualization)

其基本思想就是引入新的处理器运行模式和新的指令,使得 VMM 和 Guest OS 运行于不同的模式下,Guest OS 运行于受控模式,原来的一些敏感指令在受控模式下全部会陷入 VMM,这样就解决了部分非特权的敏感指令的陷入 — 模拟难题,而且模式切换时上下文的保存恢复由硬件来完成,这样就大大提高了陷入 — 模拟时上下文切换的效率。

该技术的引入使 x86 可以很容易地实现完全虚拟化。其皆被双方所采用,如: KVM-x86,新版 VMWare ESX Server 3,Xen 3.0

 

4. 其它体系结构分析

其它 RISC 之体系结构,如 MIPS, PowerPC, SPARC 等,似乎不存在有敏感指令为非特权指令的情形。即它们应不存在虚拟化的困难。但由于设计理念不一样,RISC 不太可能(至少目前我还没看到)在硬件上实现像 x86 那样复杂的虚拟化扩张,因此为了性能的考虑,一样皆采用 Paravirtualization,在嵌入式领域尤其如此。

至于硬件上的扩展,概况如下:

2001 年 IBM 在 Power4 中加入虚拟化支持,并在 2004 年的 Power5 中推出增强的虚拟化支持,且在 2009 年发布的 Power ISA v2.06 中规范化。Freescale 亦在 e500mc 中实现 PowerISA v2.06 的虚拟化增强。

2005 年 SUN 即在 SPARC 中引入虚拟化支持。

MIPS 至今未见动作。

 

5. 其它体系所采用之虚拟化方法

目前可见的非 x86 体系的虚拟化产品,似乎都倾向于使用类虚拟化的技术手段。

 

 

 


 
 

Things you can do from here:

 
 
Reply all
Reply to author
Forward
0 new messages