armv8虚拟化扫盲

虚拟化概述

根据虚拟化实现方式不同,分为软件虚拟化和硬件虚拟化

  1. 软件虚拟化

    1. qemu
  2. 硬件虚拟化

    1. type1虚拟化:xen+
    2. type2虚拟化:kvm
  3. 半虚拟化

    1. virtio+

软件虚拟化之qemu

  • qemu也可以使用type2级别的硬件虚拟化配合,如果没有kvm硬件加速支持,qemu可以纯粹的软件虚拟化

qemu采用TCG中间指令格式,将guest os的指令翻译成TCG指令,然后再将TGC指令翻译成host os的指令

image

硬件虚拟化

type1虚拟化

type1虚拟化是hypervisor直接运行到硬件上,管理所有的硬件资源和虚拟机,

框图如下:

image

这种方式存在一个问题,就是hypervisor需要实现所有设备驱动,开发工作大

type2虚拟化

type2虚拟化中的hypervisor运行在host os上,host os负责管理硬件资源,而hypervisor作为host os的组件

image

这种方式的问题是:

由于host os EL1和hypervisor EL2处于不同异常等级,需要通过异常方式实现系统调用,效率比type1低

解决方案:

目前armv8.1通过vhe扩展支持,使得host os和hypervisor都运行在EL2,通过函数直接调用,提高了效率

半虚拟化

  • 提出原因:

全虚拟化的guest os不需要修改任何代码,执行方式和真实硬件基本一致。但是涉及到IO操作每次都需要返回到hypervisor,效率较低

  • 解决方案:virtio+

定义了guest os驱动与hypervisor中模拟设备之间的io数据通信协议,通过通道的方式管理它们之间的数据传输,从而避免了频繁的IO操作

armv8虚拟化实现支持

虚拟化需要对:cpu 内存 iO设备 中断控制器以及timer等提供虚拟化实现

虚拟化方面 关键技术 作用
CPU 虚拟化 EL2 异常等级、敏感指令捕获、虚拟寄存器 解决特权操作模拟问题,提高性能
内存虚拟化 影子页表、两级页表、VMID 解决内存地址转换问题,提高效率和性能
IO 虚拟化 设备地址模拟、缺页异常处理 实现设备访问模拟
DMA 虚拟化 SMMU 解决 DMA 地址转换问题
中断虚拟化 GICv3 虚拟中断注入 简化中断注入流程,提高效率
定时器虚拟化 虚拟和物理定时器、计数器 确定共享 CPU 下定时器触发时间

cpu虚拟化

armv8提供了4个异常等级,应用程序运行在EL0,guest os运行在EL1,hypervisor运行在EL2,图示如下:

image

对于一般的指令,guest os无须陷入EL2,但是对于硬件状态相关的操作,仍需要陷入EL2进行处理,armv8提供了hcr_el2寄存器进行配置:

hcr_el2控制寄存器:

image

(a) 虚拟化基础配置

  • VM (Virtualization MMU)

    • 当置1时,启用第二阶段地址转换(Stage 2 Translation),即Hypervisor为VM提供独立的内存映射。
  • RW (Register Width)

    • 控制EL1的执行状态:

      • RW=1​:EL1运行在AArch64模式。
      • RW=0​:EL1运行在AArch32模式。

(b) 异常与中断路由

  • TGE (Trap General Exceptions)

    • TGE=1​时,EL0的所有异常(如系统寄存器访问)被路由到EL2。常用于容器化场景。
  • IMO/FMO/AMO (Interrupt Routing)

    • IMO=1:将物理IRQ中断路由到EL2。
    • FMO=1:将物理FIQ中断路由到EL2。
    • AMO=1:将物理SError(系统错误)中断路由到EL2。
  • VI/VF (Virtual Interrupts)

    • VI=1:向VM注入虚拟IRQ中断。
    • VF=1:向VM注入虚拟FIQ中断。

(c) 指令与操作捕获

  • TIDCP (Trap ID Co-processor)

    • 置1时,捕获EL1的某些缓存/TLB维护指令(如IC IVAU​),陷入EL2处理,确保VM隔离性。
  • DC (Data Cache Control)

    • 控制数据缓存操作(如DC CIVAC​)是否被捕获。
  • TID[0-4] (Trap ID Registers)

    • 捕获对特定系统寄存器的访问。例如:

      • TID3=1:捕获CTR_EL0​(缓存类型寄存器)的访问。
      • TID4=1:捕获对调试寄存器的访问(如MDSCR_EL1​)。

(d) 内存与调试

  • PTW (Protected Table Walk)

    • 置1时,禁止页表遍历(Page Table Walk)使用非安全内存,增强安全性。
  • TD (Trap Debug)

    • 置1时,将EL1的调试事件(如断点)路由到EL2。

系统寄存器捕获和虚拟寄存器支持

部分系统寄存器在 hypervisor 和 guest os 视角不同,如 ID_AA64MMFR0_EL1。访问频率低的寄存器,hypervisor 捕获访问并提供虚拟值;访问频率高的寄存器,如为MIDR_EL1定义了VMIDR_EL2,为MPIDR_EL1定义了VMPIDR_EL2。hypervisor在切换到vcpu之前其值写入这些虚拟寄存器中,当guest os访问MIDR_EL1时,其实际获取到的即为VMIDR_EL2中的值。通过以上方式,guest os对这类寄存器的访问将不再需要触发异常

vhe支持

vhe主要是为了支持在type2虚拟化下,将host os和hypervisor都运行在EL2中,以提高hypervisor和虚拟机之间的切换代价。其主要包含以下特性:

vhe提出原因: 在type2虚拟化中,对于没有vhe支持的armv8,host os运行在EL1,hypervisor运行在EL2,处于不同异常等级,切换效率较低

vhe特性如下:

  1. 增加了ttbr1_el2寄存器对ASDI(ASID是Address Space Identifier,每个进程拥有独立的虚拟地址空间,传统上下文切换需清空TLB(否则不同进程的地址映射会冲突)。ASID为每个进程分配唯一标识符,使TLB可同时缓存多个地址空间的条目,切换时仅需更新ASID,无需刷新整个TLB TTBR0_EL1 = [物理页表基址] | (ASID << 48) 进程切换时,仅仅需要更新TTBR0_EL1中的ASID,保留TLB缓存)支持:在不支持vhe情况下,ttbr0_el2映射地址范围较小。进程切换需要刷新TLB,导致开销
  2. 寄存器重定向:硬件支持对EL1的访问重定向到EL2。

如果需要访问真实的EL1寄存器,ARMv8.1引入了一种新的寄存器命名方式:通过_EL12后缀直接访问EL1寄存器,即使VHE已启用。

1
2
3
// 读取EL1的SCTLR寄存器
MRS x0, SCTLR_EL1 // 会被重定向到SCTLR_EL2(若E2H=1)
MRS x0, SCTLR_EL12 // 强制访问真实的EL1寄存器

内存虚拟化

基本概念:

(1)HVA(host virtual address):host视角下的虚拟地址
(2)HPA(host physical address):host视角下的物理地址
(3)GVA(guest virtual address):guest视角下的虚拟地址
(4)GPA(guest physical address):guest视角下的物理地址
(5)IPA(intermediate physical address):它与gpa含义相同,是arm的对guest物理地址的一种命名方式

影子页表(hypervisor为每个vm中的每个进程都维护一张合并了GVA–>GPA和GPA–>HPA两级页表关系的shadow页表。当guest os执行页表切换操作时,hypervisor将截获该操作,并用这张合并后的页表替换掉guest os本身的页表。它就像影子一样覆盖掉了guest os的页表,因此其被称为影子页表)

对于不支持硬件虚拟化的系统,由于只有一个MMU,只能实现一级的VA->PA转换,无法直接实现

影子页表开销较大,为此硬件引入2级页表,通过1级GVA->GPA转换,二级页表完成GPA->HPA转换

armv8两级页表

armv8 两级页表中,第一级页表由 guest os 创建用于 GVA->GPA(IPA)转换,第二级由 hypervisor 创建用于 GPA(IPA)->HPA 转换。armv8 为每个虚拟机提供 VMID,提高虚拟机切换效率和性能,页表转换时选择两级页表中访问限制更严格的属性

特性 Stage 1(阶段1转换) Stage 2(阶段2转换)
作用对象 虚拟机(VM)内部的进程 虚拟机(VM)本身
输入地址 → 输出地址 虚拟地址(VA)→ 中间物理地址(IPA) 中间物理地址(IPA)→ 实际物理地址(PA)
管理者 VM的操作系统(EL1) Hypervisor(EL2)
目的 隔离VM内的进程内存空间 隔离不同VM的物理内存空间
启用条件 默认启用(由MMU控制) 需设置HCR_EL2.VM=1​启用
页表寄存器 TTBR0_EL1​/TTBR1_EL1​(VM内) VTTBR_EL2​(Hypervisor设置)
TLB标识 使用ASID区分进程 使用VMID区分虚拟机

IO虚拟化

虚拟机需模拟外设地址空间,对于物理地址,为 IPA 分配物理页框并建立 stage 2 页表;对于共享设备,hypervisor 截获 IO 访问操作并模拟设备功能,通过不创建 IO 空间的 stage 2 页表产生缺页异常实现。

hypervisor捕获到缺页异常后,就可以根据HPFAR_EL2寄存器获取引起异常的地址,并根据ESR_EL2获取产生异常的原因,最后根据这些信息执行实际的设备模拟流程。以下为其流程图:

image

DMA虚拟化

DMA 操作以 IPA 地址为源和目的地址会出错,无硬件扩展时,hypervisor 截获 DMA 地址设置操作并分配物理内存;引入 SMMU ( SMMU的核心功能 地址转换:将设备发起的DMA请求中的虚拟地址(IOVA)转换为物理地址(PA),支持多级页表。 访问控制:检查设备对内存区域的读写权限,防止非法访问。 中断重映射:将设备中断路由到正确的虚拟机或Hypervisor。)后,hypervisor 为 DMA 创建 SMMU 页表实现内存访问

中断虚拟化

无硬件支持时,虚拟机模拟虚拟中断控制器处理中断。GICv3 在硬件层面提供虚拟中断注入功能,包括一组 list register 寄存器、vIRQ 和 vFIQ 中断信号、虚拟 cpu interface 寄存器。

有硬件支持后,hypervisor 模拟虚拟 distributor 和 redistributor,由于虚拟cpu interface已经由硬件支持,因此不再需要hypervisor模拟。hypervisor捕获物理中断注入虚拟中断,调度 vcpu 运行。

中断路由

  • IMO/FMO/AMO:控制物理中断类型(IRQ/FIQ/SError)是否路由到EL2。

    1
    2
    HCR_EL2.IMO = 1;  // 物理IRQ路由到EL2
    HCR_EL2.FMO = 0; // 物理FIQ由VM直接处理
  • VI/VF:向VM注入虚拟中断。

    1
    2
    HCR_EL2.VI = 1;   // 注入虚拟IRQ到VM
    HCR_EL2.VF = 0; // 不注入虚拟FIQ

定时器虚拟化

armv8 每个 CPU 有 generic timer 定时器,虚拟化后物理 CPU 被 vcpu 共享,定时器触发存在问题。armv8 提供虚拟和物理定时器及计数器,虚拟计数器有与物理计数器的 offset 偏移值,由 hypervisor 设置,以此确定定时器触发时间。

ARMv8定时器硬件基础

ARMv8的通用定时器(Generic Timer)为每个CPU核心提供以下关键组件:

  • 系统计数器(System Counter) :全局递增的64位计数器,频率固定(如1GHz)。

  • 物理定时器(Physical Timer) :基于系统计数器的比较寄存器(CNTP_CVAL_EL0​)和控制寄存器(CNTP_CTL_EL0​)。

  • 虚拟定时器(Virtual Timer) :专为虚拟化设计,基于 CNTVOFF_EL2 的偏移值,提供虚拟机独立的计时视图。

    1
    虚拟时间 = 系统计数器值 - CNTVOFF_EL2