目录
硬件辅助的虚拟化技术概览硬件辅助的虚拟化技术,又称为芯片辅助(Chip-Assisted)的虚拟化技术,最初来自于 Intel CPU 实现的 VT(Virtualization Technology)技术,现在已经逐渐发展为以下虚拟化技术扩展分支:
CPU 虚拟化技术基于二进制翻译的全虚拟化技术(Full-Virtualization)基于二进制翻译的全虚拟化技术,是一种完全由软件实现的虚拟化技术,最初诞生于 1998 年,是由 VMware 在 x86 CPU 上实现的 “二进制翻译(Binary Translation)” 技术。其实现原理如下:
可见,完全由软件实现的全虚拟化技术需要频繁的捕获这些特权指令,将这些指令进行转换之后,再交给 CPU 执行,导致其性能低下。 需要改造 GuestOS 的半虚拟化技术(Para-Virtualization)半虚拟化(Para-Virtualization)技术,也是一种完全由软件实现的虚拟化技术,最初诞生与 2003 年,是由开源的 Xen 虚拟化项目首先提出。其实现原理如下:
另外,Xen 为了进一步提升 VM 的存储和网络 I/O 效率,还提供了一个特殊的 Domain0 VM,作为所有 Normal VMs 的 I/O 中转站。即:VM 通过一个 I/O Front-end(前端模块)与 Domain0 中的 Backend(后端模块)进行交互,并最终由 Domain0 中的 Device drivers 实现物理 I/O。 Domain0 的本质是 Xen 的一个特权虚拟机,运行着被修改过的 Linux kernel,它拥有访问物理 I/O 资源的权限,为其它的 Normal VMs 提供 I/O 外设模拟仿真功能。 Intel VT-x 硬件辅助的虚拟化技术(Hardware-assisted virtualization)硬件辅助的虚拟化技术,顾名思义,是一种由 CPU 硬件来辅助实现的虚拟化技术,最早诞生于 2006 年,由 Intel 实现的 VT-x(Virtualization Technology for x86)技术。其实现原理如下:
这种由硬件辅助来完成的方式显然会比完全由软件实现的方式效率更高。并且 Root Mode 和 Non-root Mode 之间的模式切换时,上下文的保存与恢复也是由 CPU 硬件来完成,也有效提高了陷入(模拟时上下文切换)的效率。 Intel VT-x(Intel Virtualization Technology for x86)技术的另一个核心是为 VMM 提供了一组 CPU 指令和硬件辅助功能。其中,最核心的 CPU 指令集有以下 3 个:
VMCS 指令集和 VMCS Configuration 空间VMCS(Virtual Machine Control Structures,虚拟机控制指令)有两个部分组成:
VMX 切换(VM Entry 和 VM Exit 指令集)VMX 切换,即:CPU Root Mode 和 Non-root Mode 之间的切换。CPU 收到 VMM 的控制,在这 2 种模式中进行切换,继而轮流执行 VMM 或 GuestOS 的代码。 VMX 切换,是 VMM 通过调用 VM Entry 和 VM Exit 这 2 个指令集来完成:
一个执行 VMX 切换的例子是:GuestOS 发出了 I/O 请求,执行了 VM Exit,然后 VMM 可以直接读取 GuestOS 的内存并将 I/O 操作模拟出来,VMM 完成后,再调用 VMRESUME 指令执行 VM Entry,GuestOS 继续执行。此时在 VM 的角度看来,GuestOS 的 I/O 操作指令就像是直接被 CPU 执行了一样。 VMCS Configuration 空间解析VMCS Configuration 空间非常重要,每次发生 VM Exit 时,硬件自动在 VMCS Configuration 中存入丰富的信息,方便 VMM 甄别事件的种类和原因。而当发生 VM Entry 时,VMM 可以方便地为 GuestOS 注入事件(中断和异常),因为 VMCS Configuration 中存有 GuestOS 的中断描述表(IDT)的地址,因此硬件能够自动地调用 GuestOS 的处理程序。 Guest State Area 和 Host State Area 都会存储部分 CPU 物理寄存器的信息,例如:
另外,Guest State Area 还会包含非物理寄存器的内容,例如:一个 32bits 的 Active State 值,以此表明 GuestOS 执行时 CPU 所处于的活跃状态,如果正常执行指令就是处于 Active 状态,如果触发了三重故障(Triple Fault)或其它严重错误就处于 Shutdown 状态等等。同时,Guest State Area 并不强制性包含通用寄存器的数据,这些数据由 VMM 在 VM Exit 的时候来决定是否进行保存,从而提高了系统性能。 Execute State Area 存放可以操控 VM Entry 和 VM Exit 的标志位,包括:
VMCS 还包括一组 BitMap 以提供更好的适应性:
Memory 虚拟化技术Linux 操作系统采用页表的方式来管理虚拟内存技术,在没有引入 VM 之前,只需要完成 Virtual Memory 和 Physical Memory 之间的地址转换。 软件实现的两级地址映射技术在引入了 VM 的同时,虚拟地址转换就增加了一层,形成了一种两级地址映射关系。如下图所示:Host Virtual Address(HVA)=> Host Physical Address(HPA)=> Guest Virtual Address(GVA)=> Guest Physical Address(GPA)。 需要注意的是,VM 的本质是一个 User Process,按理说应该像其他 Normal User Process 一样可以直接访问 HVA,但事实上,由于 VM User Process 运行于 CPU 的 Non-root Mode 中,所以无法直接访问 HVA,而是需要通过 VMM 来完成 GPA 到 HVA 之间的地址转换。即:VMM 需要 intercept (截获)VM 的内存访问指令,然后 virtualize(模拟)为 HVA(e.g. kvm_memory_slot 数据结构)。而 GVA 到 GPA 的地址转换则由 GuestOS 的系统页表完成。 显然,在 VMM 实现的两级地址映射中,VM 的每次内存访问都需要 VMM 介入,并由软件进行多次地址转换,其效率是非常低的。 软件实现的 SPT 影子页表技术SPT(Shadow Page Table,影子页表)技术就是一种优化的地址转换过程,可以直接将 GVA 转换为 HPA。 SPT 为 GuestOS 的系统页表设计了一套对应的影子页表,并将影子页表装载到 CPU 的 MMU 中。影子页表的本质也是一个系统页表,从 MMU 的角度来看两者并无差别。只是系统页表是由 Kernel 来维护的,而影子页表是由 VMM 来维护的。并且 VMM 要为每个 VMs 都维护了一套对应的影子页表。 有了 SPT 之后,当 GuestOS 访问内存时,就可以根据 MMU 中的影子页表映射关系,完成 GVA 到 HPA 的直接映射。 虽然 SPT 将 VMM 实现的两级地址映射优化成为了一种基于 MMU 的直接映射,但本质上还是纯软件实现的,效率不高,而且 VMM 承担了太多影子页表的维护工作,设计不好。 Intel VT-x 硬件辅助的 EPT 扩展页表技术为了进一步改善 SPT 内存虚拟化技术,同样需要由 CPT 来进行辅助。 EPT(Extend Page Table,扩展页表)技术最早由 Intel 提出,为 MMU 增加了 SLAT(Second Level Address Translation,二级内存翻译)功能,即:为 VMM 提供了一套专用的页表空间,进而抛弃掉了影子页表。 EPT 的基本原理如上图所示,EPT 在原有 CR3 页表一级映射的基础上,引入了 EPT 页表来实现另一层二级映射,这样就完全由硬件来实现了 GVA => GPA => HPA 之间的两次地址转换。 举例来说,当 GuestOS 中的 User Application 访问内存,CPU 首先会访问 GuestOS 的 CR3 页表来完成 GVA 到 GPA 的转换,如果 GPA 不为空,则 CPU 接着通过 EPT 页表来实现 GPA 到 HPA 的转换(实际上,CPU 首先会查看 Cache 或 TLB,如果没有缓存记录才会进一步查看 EPT 页表)。另外,如果 HPA 为空,那么 CPU 就会抛出 EPT Violation 异常,并交由 VMM 来处理。 另外,CPU 访问 GuestOS 的 CR3 页表发现 GPA 为空的话,那么就会触发缺页异常,并交由 GuestOS 的缺页异常中断处理程序处理。在中断处理程序中会调用 EXIT_REASON_EPT_VIOLATION 指令,VM Exit,VMM 截获到该异常,然后分配 HPA,并建立 GVA 到 HPA 的映射,最后保存到 EPT 中。这样在下次访问的时候就可以完成从 GVA 到 HPA 的转换了。 I/O 虚拟化技术I/O 虚拟化技术大体上也可以分为 3 种类型:
本文主要讨论第 2 种类型。 IOMMU由硬件辅助实现的 Passthrough(直通)网络设备,即:把真实的硬件直接给 VM 使用,避免了 VMM 对 CPU 的 I/O 指令进行捕获/翻译、上下文切换、内存拷贝等损耗。主流的实现技术就是 IOMMU(Input/Output Memory Management Unit,I/O 内存管理单元)。 IOMMU 的本质是一个北桥芯片组(North Bridge,连接 I/O 总线和主存之间的桥梁)。值得注意的是,IOMMU 是一个通用的术语,而 Intel VT-d 和 AMD IOMMU 则是 Intel 和 AMD 公司对 IOMMU 技术的一个特定实现。 从硬件 I/O 外设进行抽象的角度来看,每个 I/O 设备都拥有 2 种资源和 2 种能力:
所以要实现 I/O 设备的虚拟化主要就是对上述的 2 种资源和 2 种能力实现隔离、保护和性能着 3 方面的增强。其中,IOMMU 实现了 2 种 “能力的虚拟化“,而 SR-IOV 标准则实现了 2 种 “资源的虚拟化“。 Intel VT-d 硬件辅助的 I/O 虚拟化技术Intel VT-d(Intel Virtualization Technology for Directed I/O)的核心实现主要在下列 2 个方面:
通过 Intel VT-d 可以最终实现将 PCIe 网卡 Passthrough(直通)给 VM 使用,而无需 VMM 的参与。 DMA Remapping Feature在传统的 DMA 中,DMA Controller 实现了 Device Address 和 Host Physical Address(ZONE_DMA)之间的直接映射,并交由 HostOS 完全掌控。 但在 VM 的 Passthrough 场景中,如果 GuestOS 执行 DMA 访问时依旧和 HostOS 一样,使用 HPA 进行访问的话,那么不同的 GuestOS 之间就会看见同一块 ZONE_DMA 地址空间。因此,在该场景中,需要通过额外的手段来保证 GuestOS 执行 DMA 操作时的安全性,保障一个 GuestOS 执行 DMA 访问时不能影响到其他 VM 的内存地址空间。 Intel VT-d DMA Remapping Feature(DMA 重映射)为此实现了 “DMA 地址隔离” 和 “DMA 地址翻译”:
通过 DMA Remapping Feature,实现了当 GuestOS 访问自己 GPA 的 ZONE_DMA 时,实际上就是直接访问了 HostOS 的 HPA 中的 ZONE_DMA 地址空间,并保证了隔离与安全。 Interrupt Remapping Feature传统的 I/O 硬中断请求格式称之为 Compatibility format,内含了一个 “DMA 写请求” 结构体,包括一个 32bits 的 dstAddress 和一个 32bits 的 Data 字段。DMA Controller 根据 dstAddress 定向地发出一个 MSI(Message signaled interrupts,消息中断)。在 HostOS 中 DMA Controller 可以访问到整个 HPA 中的 ZONE_DMA 地址空间,并没有实现 VM 场景中要求的访问隔离,即:传统的 I/O 硬中断请求无法正确的将不同的 I/O 硬中断请求路由分发到对应的 VMs 上进行处理。 Intel VT-d 还实现了 Interrupt Remapping Feature(硬中断重映射)功能,将传统的 Compatibility format 改造为了 Remapping format。其结构增加了一个 Msg ID,并通过维护一个 Interrupt Remapping Table 结构,来完成 Msg ID 和 VM GPA 地址空间的映射。 启用 Intel VT-d在 Linux 操作系统中启用 Intel VT-d 的步骤:
VFIO 用户态 PCI 驱动框架从操作系统层面看 IOMMU 技术,其另外一个核心价值就是实现了一种 “用户态的 DMA 驱动”,可以应用于 VFIO 用户态性能 I/O 场景中。 随着 SR-IOV 技术的成熟,传统的 IOMMU 实现存在多个 PCI devices 之间无法互相访问的问题(安全隔离),难以适应多个 VFs 之间互相访问的需求。所以在 2012 年,Linux Kernel 引入了 VFIO(Virtual Function I/O),本质是一个基于 IOMMU 的用户态 PCI 驱动程序框架,提供了 2 种核心服务:
一个 VFIO Interface 在操作系统上表现为:
现如今 VFIO 已经广泛的被应用到 QEMU/KVM 和 DPDK 技术中。以 QEMU PCI device Passthrough 为例:
应用了 VFIO 框架后,QEMU 将 IOMMU Group 作为 Device Passthrough 操作的最小单元,且每个 IOMMU Group 可以具有多个 VFs,这些 VFs 在 Kernel 中属于同一个 Container,支持互相访问。 VFIO 的这一特性在 GPU Passthrough 场景中非常重要,因为一个 GPU 设备实际上由若干个不同的 sub-PCI devices 组成,要想将一个 GPU 完整的进行 Passthrough,就必须将 GPU 设备的 sub-PCI devices 全部 Passthrough,并支持 sub-PCI devices 之间可以互相访问。 另外,与 IOMMU 一样,VFIO 会维护 GuestOS DMA GPA 和 HostOS DMA HPA 之间的映射关系。当 GuestOS 发起 DMA 操作时,访问的是 guest_phy_addr,VFIO 自动完成从 guest_phy_addr 到 host_dma_virt_addr 再到 host_dma_phy_addr 之间的地址转换,然后 Pin(绑定)住。 - END - 关于 “云物互联” 微信公众号: 欢迎关注 “云物互联” 微信公众号,我们专注于云计算、云原生、SDN/NFV、边缘计算及 5G 网络技术的发展及应用。热爱开源,拥抱开源! 技术即沟通 化云为雨,落地成林 |
|