ARMv8虚拟化基础知识(上)

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介: ARMv8虚拟化基础知识
  • 1 概述
  • 2 虚拟化简介
  • 3 AArch64虚拟化
  • 4 `Stage-2`地址转换
  • 5 指令的陷入和模拟
  • 6 虚拟化异常
  • 7 虚拟化通用定时器
  • 8 虚拟化主机扩展
  • 9 嵌套虚拟化
  • 10 安全空间的虚拟化
  • 11 虚拟化的成本
  • 12 小测验
  • 13 其它参考文章
  • 14 接下来的计划


1 概述


本文描述了ARMv8-64的虚拟化支持。讨论主题包括stage-2地址转换、虚拟异常和陷入。

本文主要介绍基本的虚拟化理论,并给出一些hypervisor如何利用虚拟硬件特性的示例。不会讨论如何写一个具体的hypervisor,或解释如何从头写一个hypervisor

文章的最后,有一些问题可以用来检测你的学习程度。通过本文,首先,你将学习到两种类型的hypervisor,以及它们与ARM架构的异常级别(EL)的关系。其次,你将能够解释陷入操作,以及如何使用它们模拟操作。最后,你将了解hypervisor能够产生哪些虚拟异常,并描述相关机制。


1.1 准备工作


假设你对虚拟化有一个基本的认识,包括虚拟机是什么,以及hypervisor的角色。还应该熟悉内存管理中的异常模型和地址转换。


2 虚拟化简介


首先,我们引入一些hypervisor和虚拟化理论的入门知识。如果,你已经非常熟悉这些概念,请跳过本段。

在本文中,我们使用术语hypervisor来表示负责创建、管理和调度虚拟机(VM)的软件。


2.1 虚拟化为什么重要?


虚拟化是一项使用广泛的技术,支撑着几乎所有的现代云计算和企业基础设施。通过虚拟化,开发人员可以在单个机器上运行多个操作系统,以便可以在不损害主机环境的情况下测试软件。

虚拟化在服务器中很流行,对虚拟化的支持也是大多数服务器级处理器的要求。因为虚拟化带给了数据中心想要的特性,包括:

  • 隔离:虚拟化的核心是为运行在单个物理系统上的多个虚拟机提供隔离。这种隔离允许互不信任的计算环境共享物理系统。例如,两个竞争对手可以在数据中心共享一台物理机器,但不能访问彼此的数据。
  • 高可用性:虚拟化允许在物理机器之间无缝并透明的迁移工作负载。这种常用于将工作负载从故障的硬件平台上迁移出来,以便维护、替换出错的硬件平台。
  • 负载均衡:为了优化数据中心的硬件和电力预算,充分利用硬件平台是非常重要的。这可以通过虚拟机的迁移,或在物理机器上托管合理的工作负载实现。这意味着尽可能地挖掘物理机器的容量。基于此,可以为数据中心提供商提供最好的电力预算,也为算力租户提供最佳性能。
  • 沙箱: 虚拟机可以为应用程序提供沙箱运行环境。比如,旧应用程序或开发中的软件,都可以运行在虚拟机中。运行在虚拟机中,可以阻止程序的漏洞或缺陷、甚至是恶意程序破坏运行在物理机器上的其它应用程序。


2.2 独立或托管hypervisor


hypervisor可以分为两大类:独立hypervisor,也称为Type-1hypervisor;托管hypervisor,也称为Type-2hypervisor

我们首先看一下Type-2hypervisor。在Type-2型的配置中,Host OS完全掌控着硬件平台和它的所有资源,包括CPU和物理内存。下图为一个Type-2hypervisor的示意图:


640.png

Virtual BoxVMware就是这种类型的hypervisor。这种hypervisor的好处是,Host OS可以充分利用已有的OS功能管理硬件,也就是不用再开发大量的驱动程序。运行在被托管的虚拟机中的OS,我们称之为Guest OS

接下来,我们看一下Type-1hypervisor


640.png

从图中可以看出,该设计中没有Host OS的存在。hypervisor直接运行在硬件之上,完全掌控硬件平台及其所有资源,包括CPU和物理内存。与托管型hypervisor一样,独立hypervisor也可以托管虚拟机。这些虚拟机可以运行一个或多个完整的Guest OS

ARM平台上最常用的两个开源hypervisorXen(独立,Type-1型)和KVM(托管,Type-2型)。本文在阐述一些要点时,会用这两个hypervisor作为示例。当然,还有许多其它可用的hypervisor,包括开源或私有的。


2.3 全虚拟化和半虚拟化


虚拟机的经典定义是一个独立的、隔离的计算环境,与真实的物理机器没有区别。尽管可以在ARM平台上完全模拟真实的机器,但这通常不是一种有效的方式。比如,模拟的网卡设备非常慢,因为Guest OS每次访问模拟寄存器,都必须由hypervisor处理。频繁的陷入导致比直接访问物理设备的寄存器,代价高昂的多。

作为替代方案,是修改Guest OS。让运行在虚拟机中的Guest OS意识到,自己是运行在虚拟机中,同时,在hypervisor提供性能更好的虚拟设备,Guest OS可以获得更好的访问性能。(简单地理解,全虚拟化中,每次访问寄存器都需要切换到hypervisor中执行,而半虚拟化中,将多次寄存器访问合并为一次I/O操作,减少hypervisor的切换次数,以提高性能)

Xen就是半虚拟化的代表,也是它推广了半虚拟化这个概念。使用Xen的虚拟化方案,需要修改Guest OS,以便让其可以在虚拟硬件平台上运行,而不是一个物理机器上。这种修改完全是为了提高性能。

在今天,包括ARM在内,大多数架构都支持硬件虚拟化,Guest OS基本上不需要修改就可以运行。除了少数几种I/O设备,比如块存储设备和网络设备,它们使用半虚拟化的设备和驱动程序。这种半虚拟化的I/O设备包括VirtIOXen PV Bus


2.4 虚拟机和虚拟CPU


理解虚拟机(VM)和虚拟CPU(vCPU)的区别是很重要的。虚拟机包含一个或多个vCPU,如下图所示:

640.png


VMvCPU的概念,在我们理解文章中的某些主题时非常有用。比如,一个物理内存页可以被分配给一个VM,那么该VM中所有的vCPU都可以访问这个内存页。但是,一个虚拟中断,只能被传送到目标vCPU上。

严格意义上,应该使用虚拟处理单元(vPE)的概念,而不是vCPU。对于ARM架构实现的机器来说,PE是通用术语。本文使用vCPU的概念而不是vPE,是因为大部分人对此概念比较熟悉。但是,在ARM架构规范中,使用vPE的术语。


3 AArch64虚拟化


运行在EL2或更高异常级别上的软件,可以访问控制虚拟化:

  • Stage-2地址转换
  • EL1/0指令和寄存器访问的捕获
  • 虚拟异常的产生

异常级别(EL),各层上运行的软件以及安全、非安全状态的对应关系,如下图所示:

640.png


值得注意的是,安全状态的EL2是灰色的。这是因为Secure EL2的支持并不总是可用的(ARMv8.4扩展)。这将在安全虚拟化一节中讨论。

ARM架构中一些其它的虚拟化扩展特性,包括:

  • 安全虚拟化
  • 主机虚拟化扩展-支持托管(Type-2型)hypervisor
  • 嵌套虚拟化


4 Stage-2地址转换


4.1 Stage-2地址转换概念


Stage-2地址转换允许hypervisor对虚拟机中的内存有一个全局视角。具体来说,就是hypervisor能够控制VM访问的哪些内存映射的系统资源,以及这些资源在VM地址空间中的位置。

能够控制VM的内存访问,对于隔离和沙箱运行是非常重要的。Stage-2地址转换可以保证VM只能看见分配给它的资源,而无法访问分配给其它VMhypervisor的资源。

对于内存地址转换来说,Stage-2地址转换属于第二阶段。为了支持该功能,需要一组新的地址转换表,称为Stage-2页表。

640.png


操作系统(OS)控制一组地址页表,将自己的虚拟地址空间映射到它认为的物理地址空间上。但是,OS想要访问真正的物理地址,还需要经历第二阶段的地址转换。这个第二阶段的地址转换由hypervisor控制。

OS控制的地址转换称为Stage-1地址转换,hypervisor控制的地址转换称为Stage-2地址转换。OS认为的物理内存空间称为中间物理地址(IPA)空间。

Stage-2阶段使用的页表格式与Stage-1类似。但是,页表中某些属性的处理是不同的,比如内存类型是NormalDevice,是直接编码到页表项中的,而不是通过MAIR_ELx寄存器的标志位进行判断。


4.2 虚拟机标识符(VMID


每个虚拟机都有一个标识符,称为VMIDVMID用来给TLB项进行标记,这样就可以知道相应的项属于哪个VM。通过这种标记的方法,就可以允许同时在TLB中存在不同VM的地址转换。

VMID存储在VTTBR_EL2寄存器中,可以是8位或16位。由VTCR_EL2.VS标志位控制。16位的VMID是在ARMv8.1-A架构扩展中引入的。

EL2EL3的地址转换不需要使用VMID进行标记,因为它们不属于Stage-2地址转换。


4.3 VMIDASID的组合使用


我们知道,TLB表项也可以使用地址空间标识符(ASID)进行标记。应用进程由OS指定ASID,该进程中的所有TLB表项都会被该ASID标记。这意味着属于不同应用进程的TLB表项可以在TLB中共存,从而不存在一个应用进程使用了不属于它的TLB表项。

每个VM都有自己的ASID命名空间。比如,两个VM可能都使用了ASID=5,但是对于它们来说,是不同的事物。所以,ASIDVMID的结合是非常重要的。


4.4 内存属性的组合和覆盖


Stage-1Stage-2地址映射都包含了属性,像内存类型访问权限。内存管理单元(MMU)会组合两个阶段的属性,给出最终的属性结果。MMU从两者之中选择更严格的属性,如下图所示:


640.png


在本示例中,内存的Device类型比Normal类型更严格。因此,最终要访问的就是Device类型内存。如果,我们颠倒两个阶段的内存类型指定,也就是Stage-1NormalStage-2Device,那么,结果是一样的。

这种属性结合方法适用于大部分情况,但是,有时候,hypervisor可能想要覆盖这种行为。比如,在VM的早期引导启动阶段,

  • HCR_EL2.CD:强制所有Stage-1阶段的属性都是非缓存的(Non-cacheable)。
  • HCR_EL2.DC:强制Stage-1阶段的属性为回写可缓存的正常内存(NormalWrite-Back Cacheable)。
  • HCR_EL2.FWB:允许Stage-2覆盖Stage-1阶段的属性,而不是前面的常规属性结合方式。(这样,hypervisor可以阻止虚拟机访问某些关键的外设,以防该虚拟机中的Guest OS被恶意破坏后,进一步访问关键设备)。

HCR_EL2.FWBARMv8.4-A扩展的引入的。


4.5 模拟MMIO


同真实的物理地址空间一样,一个VMIPA空间,包含内存和外设,如下图所示:


640.png

VM使用IPA地址中的外设区域,访问真实的物理外设(通常是直接分配的外设,也称为直通设备)和虚拟外设

虚拟外设完全是由hypervisor使用软件模拟的,如下图所示:


640.png


已分配的外设是已经分配给VM的真实物理设备,映射到其IPA地址空间中。这就允许运行在VM中的软件可以直接与外设进行交互。

虚拟外设是hypervisor使用软件模拟的一个设备。相应的Stage-2页表项标记为faultVM中的软件认为它在直接跟外设交互,实际上,每次访问都会触发一个Stage-2fault异常,hypervisor在异常处理程序中模拟外设的访问。

为了模拟外设,hypervisor不仅需要知道要访问哪个外设,而且需要知道访问外设中的哪个寄存器,是读还是写寄存器,访问的大小,以及传输数据的寄存器。

为了处理异常,异常模型引入了FAR_ELx寄存器。当处理Stage-1fault异常时,该寄存器会报告触发异常的虚拟地址。但是,此时的虚拟地址对hypervisor是没有用的,因为通常hypervisor不知道Guest OS如何配置它的虚拟地址空间。对于Stage-2阶段的fault异常,有一个额外的寄存器HPFAR_EL2,它将报告发生abortIPA地址。因为hypervisor可以控制IPA地址空间,所以,它可以使用这个信息确定需要模拟的寄存器。

异常模型展示了ESR_ELx寄存器如何报告异常的信息。对于通用目的寄存器loadstore触发的Stage-2阶段的fault异常,会提供额外的信息。这些信息包括访问的大小,源还是目的寄存器,以及允许hypervisor决定对虚拟外设的访问类型。

下图展示了捕获异常,并模拟访问的过程:


640.png

这个过程分为三步:

  1. VM尝试访问虚拟外设。在本示例中,访问虚拟UART的接收FIFO
  2. 这次访问会被阻塞在stage-2地址转换阶段,产生abort,陷入到EL2
  • abort异常会将异常的信息,比如访问的字节数目标寄存器以及它是load还是store,写入到寄存器ESR_EL2
  • abort异常还会将异常的IPA地址,写入到寄存器HPFAR_EL2中。
  1. hypervisor读取ESR_EL2HPFAR_EL2,识别要访问的虚拟外设寄存器。根据这些信息,hypervisor模拟相应的操作。然后,通过ERET指令返回到vCPU
  • 之后的执行从LDR之后的指令开始。


4.6 系统内存管理单元(SMMU


到目前为止,我们已经考虑了来自处理器的不同访问类型。系统中的其它主控制器,比如DMA控制器也会被分配给VM使用。我们还需要一些方法,将Stage-2阶段的保护扩展到这些主控制器上。

先考虑不使用虚拟化的系统,和其DMA控制器布局,如下图所示:

640.png


DMA控制器通过内核空间的驱动程序进行访问。该内核驱动程序因为与内核在同一个地址空间中,能够保证OS内存访问不被破坏。也就是,应用程序不能通过DMA访问它不应该访问的内存。

再来考虑相同的系统,但是OS运行在VM中,如下图所示:

640.png


在该系统中,hypervisor使用Stage-2地址转换为VM提供隔离。也就是说,虚拟机能够访问的内存完全是由hypervisor控制的Stage-2页表决定的。

如果直接允许VM中的驱动与DMA控制器交互,将会产生两个问题:

  • 隔离DMA控制器不属于Stage-2页表,可以破坏VM的沙箱。
  • 地址空间:由于存在两个阶段的地址转换,导致内核相信PA就是IPA。而DMA控制器仍然能够看见真实的PA,因此,内核和DMA控制器就有了不同的内存视角。为了解决这个问题,hypervisor可以捕获VMDMA的每次交互,提供必要的模拟行为。当内存碎片化时,这个过程非常低效且是有问题的。

一个替代方案是,扩展Stage-2地址转换机制,让其也能够对其它主控制器对内存的访问进行管理,比如,DMA控制器。也就是为这些主控制器也提供一个MMU管理单元,我们称之为系统内存管理单元(简称为SMMU,有时也称IOMMU)。


640.png

hypervisor负责对SMMU进行编程,这样,其它主控制器,比如本例中的DMA,就和VM具有一样的内存视角了。

这个方案解决了我们上面提出的两个问题。SMMU能够增强VM之间的隔离,保证独立的主控制器不会破坏沙箱环境。而且,SMMU也给了VM和分配给VM的主控制器一致的内存视角。

当然了,虚拟化不是SMMU的唯一使用场景。对于其它使用情况不再本文的讨论范围,后续再专门写文章讨论。


5 指令的陷入和模拟


有时候,hypvervisor需要模拟VM中的操作。比如,VM中的软件想要配置跟电源管理或cache一致性有关的一些底层的处理器控制。通常,我们不想VM直接访问这些控制寄存器,因为,它们可能被用来破会隔离,或者影响系统中的其它VM

当执行给定的操作时,比如读取一个寄存器,陷入会产生异常。hypervisor需要这种能力去捕获VM的操作,就像配置底层的一些控制寄存器一样,而不会影响其它VM

ARMv8架构提供了这种捕获VM操作并模拟它们的陷入控制标志位。当配置了某种陷入异常之后,VM执行某个特定的操作,将会造成异常,从而陷入到更高级别的异常级(EL)中。进而,hypervisor能够利用这些陷入异常模拟VM中的操作。

比如,执行等待中断(WFI)指令,会将CPU置入低功耗状态。如果设置了HCR_EL2.TWI==1,在EL0EL1执行WFI指令,就会在EL2产生一个异常。

注意:陷入(Trap)不仅仅是给虚拟化使用的。在EL3EL1一样可以控制陷入。但是,陷入对虚拟化软件特别重要。本文仅讨论与虚拟化相关的陷入操作。

WFI例子中,OS通常在idle循环中执行执行WFI指令。对于虚拟机中的Guest OShypervisor能够捕获这种操作,然后调度不同的vCPU执行,如下图所示:


640.png


5.1 表示某些寄存器的虚拟值


另一个使用陷入的例子是表示某些寄存器的虚拟值。比如,ID_AA64MMFR0_EL1,表示处理器支持的内存相关的一些特性。尤其是在启动阶段,OS可能会读取这些值,判断内核是否应该使能某些功能。对此,hypervisor可能想给Guest OS表达一个不同的值,称为虚拟值

为此,hypervisor使能相关陷入标志位。当VM读取该寄存器时,发生陷入异常,hypervisor确定是哪种陷入触发的,然后,模拟该操作。在本例中,hypervisor使用ID_AA64MMFR0_EL1的虚拟值填充目的寄存器,如下图所示:


640.png

陷入异常,也可以用于懒惰上下文切换(lazy context switching)。比如,通常情况下,OS在引导启动阶段初始化MMU配置寄存器(TTBR<n>_EL1TCR_EL1MAIR_EL1),之后,不会再重新设置。hypervisor可以利用这个习惯优化上下文切换,仅仅在上下文切换时恢复这些寄存器,而不用保存它们。

但是,启动之后,OS也可能会对其重新编程。为了避免造成问题,hypervisor可以设置HCR_EL2.TVM这个陷入使能位。设置之后,任何尝试写MMU相关的寄存器都会产生陷入异常到EL2中,允许hypervisor检测是否需要更新它保存的这些寄存器的副本。

注意:我们使用陷入trapping)和路由routing)表示独立,但是相关的概念。回忆一下,陷入是当执行特定的操作造成异常。路由是指一旦异常产生就会被带到的异常级别。


5.2 MIDRMPIDR


使用陷入模拟一些操作需要大量的计算。VM的操作产生陷入异常到EL2hypervisor确定、模拟该操作,然后,返回到Guest OS中。表示特性的寄存器,像ID_AA64MMFR0_EL1,OS不常访问。这意味着,hypervisor模拟这种操作所执行的代码而带来的性能损失是可以接受的。

对于那些需要频繁访问的寄存器,或者性能关键代码中访问的寄存器,就需要避免这种计算负载。这类寄存器和其可能值的示例,如下所示:

  • MIDR_EL1:处理器类型,比如Cortex-A53
  • MPIDR_EL1:亲和力寄存器,比如处理器2的核1。

hypervisor希望Guest OS能够看见这些寄存器的虚拟值,但是每次访问都陷入。对于这些寄存器,ARMv8架构提供了代替方案:

  • VPIDR_EL2EL1读取MIDR_EL1时返回的值。
  • VMPIDR_EL2EL1读取MPIDR_EL1时返回的值。

hypervisor可以在进入VM之前,设置这些寄存器。如果VM中的软件读取MIDR_EL1MPIDR_EL1,硬件自动返回虚拟值,而无需陷入到EL2处理。


注意:VMPIDR_EL2VPIDR_EL2没有定义复位值。所以,在第一次进入到EL1之前,启动代码必须初始化这几个虚拟寄存器。这在裸机程序中尤为重要。

相关文章
|
Cloud Native 虚拟化 云计算
《Docker基础知识解析:容器与虚拟化的区别与优势,选择最佳方案优化云计算应用》
《Docker基础知识解析:容器与虚拟化的区别与优势,选择最佳方案优化云计算应用》
434 0
|
存储 持续交付 虚拟化
Docker 基础知识解析:容器与虚拟化的区别与优势
Docker 基础知识解析:容器与虚拟化的区别与优势
590 0
|
Go 虚拟化 云计算
Docker 基础知识解析:容器与传统虚拟化对比:资源利用、启动时间、隔离性和部署效率
Docker 基础知识解析:容器与传统虚拟化对比:资源利用、启动时间、隔离性和部署效率
414 0
|
存储 负载均衡 监控
六、分享优秀的Armv8 虚拟化技术地址
六、分享优秀的Armv8 虚拟化技术地址
207 0
|
Rust 安全 搜索推荐
ARMv8虚拟化基础知识(下)
ARMv8虚拟化基础知识(下)
|
Linux 虚拟化 KVM
虚拟化学习笔记-基础知识
版权声明:转载请注明出处:http://blog.csdn.net/dajitui2024 https://blog.csdn.net/dajitui2024/article/details/79396678 ...
1396 0
|
数据可视化 Linux 虚拟化
《循序渐进Linux(第2版) 基础知识 服务器搭建 系统管理 性能调优 虚拟化与集群应用》——4.7 文本编辑工具vi
vi是Linux下标准的文本编辑程序,也是Linux系统命令行下最经常使用的文本文件可视化编辑器,类似于DOS命令edit。那么什么是可视化呢?其实就是让用户在编辑文本文件的时候能够看到它们。这听起来似乎很普通,但是在命令行的字符界面下,可视化编辑确实起了很大的作用。
2108 0
|
JavaScript 前端开发 网络协议
《循序渐进Linux(第2版) 基础知识 服务器搭建 系统管理 性能调优 虚拟化与集群应用》——4.6 网络设置与维护
interface:网络接口名,Linux下的网络接口名类似于eth0、eth1和lo等(在CentOS 7.x版本中,网络接口名变为类似enp0s1、enp0s2这样的标识),分别表示第1块网卡、第2块网卡和回环接口。
2839 0