1. 前言
虚拟化是现代计算机领域不可或缺的一种技术,它让公开的虚拟资源等于被虚拟化的底层物理资源,通常是使用多路复用、聚合和模拟中的一种或多种基本技术实现。等效性、安全性和性能是衡量虚拟化的三个重要标准。Gerald Popek 和 Robert Goldberg 在 1974 年就确立了一个指令集架构(ISA)是否支持虚拟化的基本要求。直到今天,这个核心思想仍然理解计算机体系结构和支持虚拟机能力的基本原则。
2. 名词解释
在开始正文之前,先复习下几个虚拟化相关的重要名词。
2.1 虚拟机
英文是 Virtual Machine,简称 VM。虚拟机是对完整计算机环境的抽象,它将处理器、内存(memory)和 I/O 设备联合虚拟化,具有自己独立的处理能力、内存和通信通道。每个虚拟机的内部环境类似于计算机的硬件,都有自己的底层硬件副本,或者至少有自己的某些底层硬件副本,且可以运行自己的独立客户操作系统(Guest OS)及其应用程序(App),且与其它虚拟机和环境其余部分完全隔离,互不影响和感知。虚拟机的运行平台可以分为两类:虚拟机管理程序(Hypervisor)和机器模拟器(Machine Simulator)。这两个名词在下面介绍。
2.2 虚拟机管理程序
英文是 Hypervisor,中文也叫超级监督者。Hypervisor 是管理和运行虚拟机的专用系统软件。当多个虚拟机同时存在于同一个计算机系统上时,hypervisor 对它们进行调度,使虚拟机之间进行多路复用来分配真实物理资源。Hypervisor 让虚拟机直接在 CPU 上执行可以获得最大效率,理想情况下基本不影响性能开销。Hypervisor 先配置好硬件环境(寄存器等),随后让虚拟机指令在 CPU 上执行。由于虚拟机指令序列必须在虚拟机的抽象中操作,因此执行更新或依赖系统状态的指令会引起 Trap(捕获),hypervisor 会处理这个 Trap 并模拟该指令的功能。Hypervisor 设计的核心就是 Trap-and-Emulate 范式。
Hypervisor 分为 type-1 和 type-2 两种类型。Type-1 hypervisor 直接控制物理计算机的所有资源。相比之下,type-2 hypervisor 要么作为现有主机操作系统(Host OS)的一部分运行,要么直接在现有 Host OS 之上运行,其实就是扩展 Host OS 的功能。常见的 hypervisor 如下图 1 所示。
图 1 常见的 hypervisor
最基本的 hypervisor 使用两种关键虚拟化技术:
- 在虚拟机之间多路复用物理资源(在空间上,也可能在时间上);
- 模拟其它一切需要的资源,特别是 I/O 总线和 I/O 设备;
由于 Hypervisor 允许虚拟 CPU 直接执行物理处理器的指令,这种调度技术被称为直接执行(Direct Execution)。当然,hypervisor 要负责确保虚拟机的安全性。因此,hypervisor 会确保虚拟机总是以更低的特权执行,这样虚拟 CPU 就不能直接执行特权指令等。只要 Guest OS 试图执行特权指令,虚拟机的直接执行就会导致 Trap,然后就由 hypervisor 接管去模拟了。因此,围绕直接执行设计的 hypervisor 遵循 trap-and-emulate 范式,其中大部分执行开销是用于 hypervisor 代表虚拟机模拟 trap 指令的功能。
2.3 机器模拟器
英文是 Machine Simulator。Machine Simulator 通常使用普通的用户级应用程序实现,其目标是提供对虚拟架构的精确模拟,取决于模拟细节的级别,它通常会比本机速度慢 x5 到 1000x 不等。因为 Machine simulators 允许对复杂工作负载的详细研究,在计算机体系结构研究中起着重要作用。
实际上,Machine Simulator 和 Hypervisor 之间的主要区别在于,前者模拟虚拟机的 CPU 指令集体系结构,而后者对 CPU 进行多路复用。CPU 的多路复用是一个调度任务,与操作系统调度进程任务非常的类似。调度实体(这里是 hypervisor)设置硬件环境(寄存器等),然后让被调度实体(虚拟机)以较低的特权等级直接在硬件上执行。Machine Simulator 可以说是 Full(soft) virtualization,Hypervisor 可以说是 Hardware virtualization(HVM, HV)。
除了 Hypervisor 和 Machine Simulator,其实还有一种半虚拟化(paravirtualization)。它是由于早期处理器缺乏对虚拟化清晰的体系结构支持,因此出现了一系列解决运行与底层硬件相似或兼容相同虚拟机问题的方法。这种方法做出了不同的权衡,将简单性和整体效率置于与底层硬件的完全兼容性之上。
在早期没有虚拟化体系结构支持的平台上,paravirtualization 需要更改与底层硬件不兼容的 Guest OS。在具有 Full virtualization 支持的体系结构的当前使用中,通过平台特定的扩展,paravirtualization 仍然用于增强 HWM,通常在设备驱动程序中实现,例如管理协作内存或实现高性能前端设备。
2.4 虚拟机监控器
英文是 Virtual Machine Monitor,简称 VMM。VMM 是 hypervisor 中专门用于 CPU 和内存虚拟化的部分。不过有些文献中,VMM 和 hypervisor 是一样。在 Type-1 hypervisor 中,VMM 直接在裸机上运行,type-2 hypervisor 中,VMM 运行在 Host OS 之下。Type-1 和 type-2 的 hypervisor 中,VMM 都需要创建虚拟机。
Type-1 环境中,裸机上的 VMM 必须执行系统的调度和实际的资源分配,因此,type-1 VMM 需要编写额外的资源调度和分配代码。Type-2 环境中,Host OS 调度所有的系统资源,Host OS 像调度进程一样调度 hypervisor,尽管这种模式需要依赖繁琐的 Kernel 模式来执行虚拟机,但好处就是可移植性强、代码改动量少。
VMM 的基本结构如图 2 所示,每个 Processing Element(PE)包括了 CPU 和物理内存。PE 连接到 I/O 总线上,并附带两个 I/O 设备:磁盘和网络接口卡。该图也是服务器部署的典型代表。PC 的话可能还包括键盘、鼠标、串行接口和 USB 等附加设备。移动平台可能还需要 GPS、加速度计和收音机等。图中有三个虚拟机,每个虚拟机都有自己的虚拟硬件、自己的 Guest OS 和自己的应用程序。Hypervisor 直接运行在真实硬件上,且控制着实际的物理资源。
图 2 VMM 的基本架构
2.5 内存
英文是 Memory。内存有很多种类定义,不过大致分为两种类型:Virtual memory(虚拟内存)和Physical memory(物理内存),虚拟内存通过分段或分页的组合转换为物理内存。
虚拟内存通常就是处理器执行指令时所使用的地址空间。除了极少数例外,所有指向内存位置的寄存器和指令地址都包含一个虚拟地址。在分段体系结构中,虚拟地址空间是由基址和偏移限制决定的。基址会被添加到虚拟地址中,偏移限制会用于检查以进行保护地址是否越界。在分页体系结构中,虚拟地址空间由内存管理单元(MMU)在逐页的基础上确定,其映射由页表或软件 TLB miss 处理程序定义。有些体系结构(如 x86-32)将分段与分页结合起来,虚拟地址首先(通过分段)转换成线性地址,然后(通过分页)转换成物理地址。
物理内存就是处理器的内存层次结构访问所使用的地址空间,通常由 DRAM 提供支持。在非虚拟化的计算机系统中,物理地址空间通常由硬件资源决定,并由处理器的内存控制器定义。在虚拟计算机系统中,hypervisor 定义虚拟机可用物理内存大小。从技术上讲,对虚拟机可见的抽象应该称为“virtual physical memory”(虚拟物理内存)。然而,为了避免与虚拟内存混淆,它通常被称谓guest-physical memory。为了进一步避免歧义,底层资源被称为host-physical memory。不过要注意,一些早期的虚拟化论文使用了不同的术语,特别是分别使用 physical memory 和 machine memory 来指代 guest-physical memory 和 host-physical memory。
3. 虚拟化模型
1974 年,Gerald Popek 和 Robert Goldberg 在Communications of the ACM上发表了一篇名为“Formal Requirements for Virtualizable Third-Generation Architectures”的论文,其中定义决定了一个给定的指令集架构(ISA)是否可以被一个使用多路复用的 VMM 虚拟化。对于任何满足定义假设的体系结构,任何可以直接在硬件上运行的操作系统也可以在虚拟机中运行,而无需修改操作系统代码。这项工作的动机是解决新架构可能阻碍 VMM 构建,让架构师在设计时就考虑这个问题。直到今天,这个定理仍然是理解计算机体系结构与其支持虚拟机的能力之间的基本关系的起点。具体地说,该定理决定了仅依赖于直接执行的 VMM 是否能够支持任意 Guest OS。
这个定理假设有一个标准的计算机体系结构的处理器,处理器有两种执行模式:用户级(user-level)和主管级(supervisor),且支持虚拟内**存**。特别是,操作系统可以将硬件配置为相互隔离地运行多个任意的应用程序。为了证明,文章定义了一个简单的模型,该模型具有以下特点:
- 计算机有一个拥有两个执行级别的处理器:主管模式(supervisor mode)和用户模式(user mode)。
- 虚拟内存是通过分段(而不是分页)实现的,它使用基址 B 和限制 L 的单个段**(B 和 L 也称作 relocation-bound register pair)**。分段定义[B, B+L]范围的线性地址空间为有效地虚拟地址[0, L]。由于不采用分页,线性地址直接以 1:1 的比例映射到物理地址。对于所有内存访问,在 supervisor 和 user 模式下都是用虚拟内存。
- 物理内存是连续的,从地址 0 开始,物理内存大小(SZ)在处理器复位时是已知的。
处理器的系统状态称为处理器状态字(processor status word, PSW),由元组(M, B, L, PC)组成。
- 执行级别(execution level):M={s,u};
- 段寄存器(segment register):(B, L);
- 当前程序计数器(program counter, PC),虚拟地址;
- Trap architecture 规定首先将 PSW 内容保存到内存中的一个已知位置(MEM[0]),然后将来自内存中另一个已知位置(MEM[1])的值加载到 PSW 中。Trap architecture 机制用于在系统调用或执行指令时出现异常后进入。
- ISA 包括至少一条指令或指令序列,该指令或指令序列可以将元组(M, B, L, PC)从内存的一个位置加载到硬件 PSW 中。用于在系统调用或 Trap 处理完成后,恢复到用户模式下执行。
- 为了简化讨论,忽略 I/O 和中断。
我们首先考虑这种体系结构的操作系统是什么样的(在没有 VMM 的情况下)。
- Kernel 将在 supervisor 模式(M=s)下运行,而应用程序将始终在 user 模式(M=u)下运行;
- 在初始化过程中,kernel 首先设置 Trap 入口点:MEM[0]←(M:s,B:0,L:SZ,PC:trap_en);
- Kernel 将为每个应用程序分配一个连续的物理内存范围;
- 要启动或恢复存储在物理内存[B, B+L]中的应用程序和当前正在执行指令 PC,操作系统只需要把(M:u, B, L, PC)加载到 PSW 中;
- 在 Trap 入口点(PC=trap_en),kernel 首先解码存储在 MEM[1].PC 中的指令,确定产生 Trap 的原因,然后采取适当的行动;
这个体系结构比较理想化,特别是缺少寄存器,但与现今所熟悉的体系结构本质上没有什么不同。对于这样的架构,Popek 和 Goldberg 提出了以下正式的研究问题。
给一台满足这个基本体系结构模型的计算机,在这个模型的精确条件下可以构造 VMM,使 VMM:
- 可以执行一个或多个虚拟机;
- 可以始终完全控制 machine;
- 支持为相同的体系结构设计任意的、未经修改的或潜在的恶意操作系统;
- 在最坏的情况下,速度只有较小的下降;
这个问题的答案决定了是否可以为特定的体系结构构造 VMM,从而得到的虚拟机可以是真实机器的高效、独立的副本。当条件满足时,定理必须确保符合以下三个标准:
- Equivalence:虚拟机本质上与底层处理器相同,即计算机体系结构的副本。在虚拟机中运行的任何程序,即任何 Guest OS 和应用程序组合,都应该表现出与直接在底层硬件上运行的程序相同的行为,除了可能出现的例外情况,比如由时间依赖关系或资源可用性(如物理内存大小)引起的差异。
- Safety:VMM 必须始终完全控制硬件,且不对虚拟机内部运行的软件做任何假设。虚拟机与底层硬件是隔离的,它的操作就像在一台独立的计算机上运行一样。此外,不同的虚拟机之间必须相互隔离。
- Performance:效率要求意味着,与直接在底层硬件上运行相比,在虚拟化环境中程序的执行速度即使最坏的情况下也只会有轻微的下降。
4. 虚拟化定理
基于上述虚拟化模型,Gerald Popek 和 Robert Goldberg 提出了以下定义:对于任何计算机,如果该计算机的敏感指令集(sensitive instructions)是特权指令集(privileged instructions)的子集,则可以构造虚拟机监视器(virtual machine monitor, VMM),也称 hypervisor。
Popek 和 Goldberg 研究的问题的答案取决于 ISA 指令的分类。如果一条指令可以更新系统状态,那么他就是控制敏感指令(control-sensitive);如果一条指令的语义依赖于系统状态中设置的实际值,那么它就是行为敏感指令(behavior-sensitive);否则,就是无害指令(innocuous instruction)。如果一条指令只能在 supervisor 模式下执行,并且尝试从 user 模式下执行时会产生 Trap,那么它具有特权(privileged)。当所有 control-sensitive 和 behavior-sensitive 指令都具有特权时,则可以构造 VMM。如:
control-sensitive || behavior-sensitive ≤ privileged
图 3(a)描述了三种主要形式的内存之间的关系:host-physical memory, guest-physical memory 和 virtual memory。图 3 也表述了在三种不同情况下,处理器的 PSW,以及执行级别 M 和 relocation-bound pair(B, L)是如何配置的。
(a) host-physical memory, guest-physical memory 和 virtual memory
(b) 执行应用程序、Guest OS 和 VMM 时的硬件配置
图 3 VMM 的构造
如果满足定理的条件,则 VMM 的操作如下:
- VMM 是唯一实际运行在 supervisor 模式下的软件。VMM 为自己的代码和数据结构保留了一部分物理内存,这些内存永远不会映射到任何虚拟机的任何虚拟地址空间。
- VMM 在 host-physical 地址空间中为每个虚拟机连续分配 guest-physical memory,每个虚拟机都有固定的内存大小。这些参数如图 3 中的 addr0 和 memsize。
- VMM 在内存中保存每个虚拟机的系统状态的副本:vPSW。与硬件类似,vPSW 由虚拟机的执行层、段寄存器(B, L)和 PC 组成。
虚拟机通过从内存加载元组(M’, B’, L’, PC’)恢复 PSW 来执行:
- M’←u:虚拟机始终以用户模式执行;
- B’←addr0+vPSW.B:将 guest-physical 偏移量添加到虚拟机的段基址中;
- L’←min(vPSW.L, vPSW.memsize-vPSW.B):一般情况下,是直接使用虚拟机的段限制。然而,恶意 Guest OS 可能会尝试允许其应用程序读取超出 guest-physical memory 末端的内容。这样 min()是放置了这种情况,以确保安全性;
- PC’←vPSW.PC:恢复虚拟机的执行;
- 在每次 Trap 时,VMM 更新 PC 值(vPSW.PC←PSW.PC)。vPSW 的其它域段即使在任意长的直接执行周期之后也不需要更新。实际上,任何可以更新 PSW 的 B/L/M 的指令都是 control-sensitive 的。VMM 假定所有 control-sensitive 的指令都是 privileged,并依赖于虚拟机始终使用 PSW.M==u 来执行。
- VMM 模拟引起 Trap 的指令。如果 guest OS 正在运行(vPSW.M==u),VMM 首先对指令进行解码,然后根据 ISA 模拟特权指令的语义。例如,根据 Guest OS 设置的新值,VMM 通过更新 vPSW.B 和 vPSW.L 来模拟更改 segment register pair。在成功模拟后,VMM 增加 PC(vPSW.PC++),然后根据步骤 4 恢复虚拟机的执行。
然而,VMM 可能得出结论,根据 ISA,指令的模拟实际上是一个 Trap。例如,考虑虚拟机处于 user 模式的情况(vPSW.M==u),恶意应用程序试图发出特权指令,或者如果应用程序访问内存超出了 Guest OS 在段描述符(B)中设置的限制。根据架构,VMM 会模拟 Trap,即:
- MEM[addr0]←vPSW:根据体系结构将虚拟机的 vPSW 存储到 Guest-physical memory 的第一个字;
- vPSW←MEM[addr0+1]根据体系结构将 Guest-physical memory 中的第二个字复制到 vPSW 中。根据 Guest OS 设置的配置更新虚拟机的状态;
- 按照步骤 4 恢复执行;
- 如果满足定理的假设,所有更新系统状态的指令(程序计数器除外)是 control-sensitive,且具有 privileged。在 user 模式下执行这些指令将会造成 Trap。它将包括任何改变定义虚拟地址空间的 base-bound registers 指令、或在 user 和 supervisor 模式之间转换的指令。VMM 根据体系结构规范模拟这些指令。
- 如果这个假设得到满足,那么任何 behavior-sensitive 指令都将拥有特权,在 user 模式下执行将会导致 Trap。VMM 也会模拟这些指令,例如,考虑一条指令需要读取执行层(PSW.M)或段基址(PSW.B),这种指令的行为直接依赖于处理器状态的实际值,而处理器状态的实际值会在虚拟化过程中发生变化。这些指令必须具有特权,以确保正确的值返回给程序。
5. 递归虚拟化
实际上,满足定理标准的理想化架构也可以支持递归虚拟化(recursive virtualization)。在这个场景中,虚拟机可以在 Guest-supervisor 模式下运行 VMM,而不是在操作系统模式下运行 VMM。当然,VMM 可以运行多个虚拟机、它们的 Guest OS 和各自的应用程序。在递归虚拟化中,VMM 本身必须在虚拟机中运行。
6. 总结
本文旨在用最简单的方式描述虚拟化的本质和基本实现框架,任何复杂的虚拟机都是基于此基本原理上增补功能来的。只要大家心里有个虚拟机原理框架,我相信学习任何虚拟机都能很快入手,摆脱只见树木,不见森林的状态。
本文从名词解释,在使用一个基本简单的模型,引出了 Popek 和 Goldberg 研究的虚拟化定理,根据这个定理,可比较快判断一个处理器体系结构是否好支持 Hypervisor。Hypervisor 实际上也是一个 OS,两者都必须确保保持控制,并且必须正确配置硬件以实现其目标。不同之处在于,OS 运行应用程序,而 hypervisor 运行整个虚拟机(包括 Guest OS 和应用程序)。
END
作者:沪闵菜菜子
文章来源:专芯致志er
推荐阅读
- m_sequencer 和 p_sequencer 到底谁大
- protocol——命令行绘制协议图大杀器
- PCIe 调试:超级好用的 rescan 与 remove 命令
- 使用 scp 命令跨服务器传输文件
- PCIE , USB , SATA , Ethernet 都在用的 SerDes 到底是个啥?
更多 IC 设计干货请关注IC设计专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。