Armv8-A虚拟化手册(2)
4. Stage2转换4.1 什么是stage2转换Stage2转换允许一个hypervisor控制虚拟机中内存视图。特别的,它允许hypervisor控制一个虚拟机可以访问哪个内存映射的系统资源,这些资源呈现在虚拟机中的地址空间的哪里。控制内存访问的能力对隔离和基础服务很重要。可以使用stage2转换来保证虚拟机可以看到分配给它的资源,而不是分配给其他虚拟机或hypervisor的资源。对于内存
4. Stage2转换
4.1 什么是stage2转换
Stage2转换允许一个hypervisor控制虚拟机中内存视图。特别的,它允许hypervisor控制一个虚拟机可以访问哪个内存映射的系统资源,这些资源呈现在虚拟机中的地址空间的哪里。
控制内存访问的能力对隔离和基础服务很重要。可以使用stage2转换来保证虚拟机可以看到分配给它的资源,而不是分配给其他虚拟机或hypervisor的资源。
对于内存地址转换,stage2转换是转换的第二阶段。为了支持它,要求一组新的转换表即stage2表,如下图所示:
OS控制一组转换表,这组转换表将虚拟地址空间映射到它认为的物理地址空间。但是,这个过程需要经过第二阶段转换才可以转化为真实的物理空间。第二阶段有hypervisor控制。
OS控制的阶段称为stage1转换,hypervisor控制的阶段成为stage2转换。OS认为的物理地址空间即为中间物理地址空间IPA。
NOTE: 可以看内存管理指导来了解地址转换是如何工作的。
Stage2所使用的转换表格式与stage1所使用的类似。但是,一些属性的处理在stage2中不同,且Type/Normal/Device直接放入页表项中而不是通过MAIR_ELX寄存器。
4.2 VMID
每个虚拟机都被赋予一个VMID。VMID用于标识TLB项,区分每个TLB是属于哪个虚拟机。这允许多个不同的虚拟机转换在同一时间内在TLB中存在。
VMID保存在VTTBR_EL2中,可以8位或16位。VMID是由VTCR_EL2.VS位来控制。支持16位的VMID是可选的。
NOTE: EL2和EL3转换区域的转换不需要用VMID标识,因为它们不受限于stage2转换。
4.3 VMID和ASID的交互
TLB项也可以用ASID来标识。OS赋予一个应用ASID,在应用中的所有TLB项都用相同的ASID来标识。这意味着不同应用的TLB项可以同时存在于TLB中,不会一个应用使用属于不同应用的TLB项。
每个VM都有自己的ASID命名空间。比如,两个VM可能同时都用ASID 5,但它们指的是不同的东西。ASID和VMID的合并是非常重要的。
4.4 属性的合并与覆盖
Stage1和stage2映射包含属性,像类型和访问权限。MMU结合两个阶段的属性给出最终有效的值。MMU通过严格的stage的选择来达到此目的。
在这个例子中Device类型比Normal类型更严格。因此,最终类型为Device。如果将例子中的stage1和stage2类型做调换,结果一样。
在大多数情况下结合属性的方法都有效。但是有时候hypervisor可能想要覆盖此行为。比如,在虚拟机早期启动时。在这种情况下,有一些控制位来覆盖正常的行为:
- HCR_EL2.CD:这使得所有stage1属性Non-cacheable。
- HCR_EL2.DC:这强制stage1属性为Normal, Write-Back Cacheable。
- HCR_EL2.FWB:允许stage2覆盖stage1的属性,而不是正常的属性结合。
NOTE: HCR_EL2.FWB由Armv8.4-A引入。
4.5 模拟内存映射的输入输出MMIO
像物理机上的物理地址空间,虚拟机中的IPA空间包含用于访问内存和外设的区域。
虚拟机可以使用外设区域来访问真实的物理外设(通常为直接赋值的外设)和虚拟外设。
虚拟外设是完全由hypervisor软件模拟的,如下图高亮所示:
一个分配的外设是分配给虚拟机的真实物理设备,映射到它的IPA空间。这允许执行在虚拟机上的软件能够直接与外设交互。
一个虚拟外设为hypervisor在软件上模拟的设备。Stage2相关的表项被标记为fault。在虚拟机上的软件认为它可以直接与外设交互,但每次访问都会触发stage2 fault,hypervisor在异常处理里模拟设备的访问。
为了模拟外设,hypervisor需要知道它要访问哪个外设,也要知道在外设中需要访问哪个寄存器,访问是读还是写,访问的大小,传输数据用的寄存器。
从地址开始,异常模式引入FAR_ELx寄存器。当处理stage1 fault时,这些寄存器报告虚拟地址触发了异常。虚拟地址对hypervisor没有帮助,因为hypervisor通常不知道guest OS是如何配置它的虚拟地址空间。对于stage2 fault,另外有个寄存器HPFAR_EL2,它报告abort掉的IPA地址。因为IPA空间由hypervisor控制,它可以通过这个信息来决定它需要模拟的寄存器。
异常模型显示了ESR_ELx寄存器是如何报告异常信息的。对于单个触发stage2 fault的通用目的寄存器,提供了额外的综合信息。这些信息包括访问大小,源和目的寄存器,允许hypervisor决定发送给虚拟外设的访问类型。
下面图描述了ttrap的过程以及模拟访问:
描述的过程包括以下步骤:
(1)虚拟机上的软件尝试访问虚拟外设。在这个例子中,为虚拟UART的接受FIFO;
(2)访问在stage2转换被阻塞,导致路由到EL2的abort;
A. 该abort读取ESR_EL2获取异常的信息,包括访问的bytes数目,目的寄存器和读还是写;
B. 该abort也读取HPFAR_EL2来获取abort访问的IPA;
(3)hypervisor使用来自ESR_EL2和HPFAR_EL2的信息来区分虚拟外设寄存器。这个信息允许hypervisor模拟操作。然后它从过ERET返回给vCPU;
C. 在LDR后重新执行指令。
5. SMMU
到目前为止,我们已经考虑来自处理器的不同类型的访问。在系统中其他master,如DMA控制器,可能被分配给虚拟机使用。我们也需要一些方法来将stage2的保护扩展到这些master。
考虑一个带DMA控制器的系统,不支持虚拟化,如下图所示:
通常在内核空间可以通过驱动对DMA控制器编程。内核空间驱动保证OS级内存保护不会被破坏。这意味着一个应用不能使用DMA来访问它不能看见的内存。
让我们来考虑相同的系统,但在虚拟机中运行OS,如下图所示:
在这个系统中,hypervisor使用stage2来隔离不同虚拟机。软件看见内存的能力受hypervisor控制的stage2表的限制。
允许在虚拟机的驱动直接与DMA控制器交互会造成两个问题:
隔离:DMA控制器不符合stage2表,可能破坏虚拟机的基础服务;
地址空间:由于两阶段转换,内核认为的PA其实是IPA。DMA控制器仍看到的是PA,因此内核和DMA控制器看到不同的内存视图。为了克服此问题,hypervisor在虚拟机和DMA控制器之间的每次交互中陷入,提供必要的转换。当在这个过程中内存碎片化时,这个过程会效率低,且有点问题。
与陷入和模拟驱动访问相反的方案是将stage2区域也扩展到其他master,像我们的DMA控制器。当这发生时,这些master也需要一个MMU,这就是我们提到的SMMU,有时我们也称为IOMMU。
hypervisor负责为SMMU编程,因此上游的master(在我们例子中为DMA),可以看到虚拟机相同的内存视图。
这个过程可以解决我们遇到的两个问题。SMMU会强制不同虚拟机之间的隔离,保证外部的master不能用来破坏基础服务。SMMU也给出内存的连续视图给虚拟机或外部master的软件。
虚拟化不是SMMU唯一的场景。这里还有其他场景不会被覆盖在本指导中。
更多推荐
所有评论(0)