kvm aarch64 原理详解
KVM on AArch64 基于 ARMv8 硬件虚拟化扩展(EL2、两阶段地址翻译、GICv3/v4、VHE),以Trap-and-Emulate为核心,实现 CPU、内存、中断、设备的高效虚拟化,宿主机 Linux 与 KVM 协同提供完整虚拟化能力。
ARMv8 虚拟化硬件基础
异常级别(Exception Level, EL)
ARMv8 定义 4 个异常级别,形成严格权限隔离:
| EL | 名称 | 运行主体 | 权限 | 核心作用 |
|---|---|---|---|---|
| EL0 | User | 应用程序 | 最低 | 执行非特权指令 |
| EL1 | Kernel | Guest OS 内核 | 特权 | 管理 Guest 资源 |
| EL2 | Hypervisor | KVM 核心 | 最高(非安全) | 虚拟化管控、异常捕获 |
| EL3 | Monitor | TrustZone / 固件 | 最高(安全) | 安全世界切换 |
关键:
- Guest 运行在EL1/EL0,KVM 运行在EL2。
- Guest 执行特权 / 敏感操作时,硬件自动Trap 到 EL2,由 KVM 处理。
- EL2 拥有独立寄存器组(如
HCR_EL2、VTTBR_EL2)与异常向量表。
核心虚拟化寄存器(HCR_EL2)
HCR_EL2(Hypervisor Configuration Register)是 AArch64 虚拟化总控开关,决定哪些操作会 Trap 到 EL2:
| 位 | 名称 | 功能 |
|---|---|---|
| IMO | Interrupt Mask Override | 物理 IRQ 路由到 EL2 |
| FMO | FIQ Mask Override | 物理 FIQ 路由到 EL2 |
| AMO | SError Mask Override | 系统错误路由到 EL2 |
| TWI | Trap WFI | 执行WFI触发 EL2 异常 |
| TWE | Trap WFE | 执行WFE触发 EL2 异常 |
| TVM | Trap Virtual Memory | 访问 Stage 1 页表寄存器(TTBR0_EL1)触发 Trap |
| E2H | EL2 Host | VHE 模式使能,Host 运行在 EL2 |
| RW | Register Width | 控制 Guest 运行在 AArch64/AArch32 |
两阶段地址翻译(Stage 1 + Stage 2)
AArch64 内存虚拟化的核心,彻底隔离 Guest 物理地址(IPA)与真实物理地址(PA):
Stage 1(Guest 内部)
- Guest OS 管理:VA → IPA(Guest 虚拟地址 → Guest 物理地址)
- 寄存器:
TTBR0_EL1/TTBR1_EL1(可直接由 Guest 编程,无需 Trap)
Stage 2(KVM 管控)
- KVM 管理:IPA → PA(Guest 物理地址 → 真实物理地址)
- 寄存器:
VTTBR_EL2(每个 VM 独立一套 Stage 2 页表) - 硬件自动完成两阶段 Walk,性能接近原生
VHE(Virtualization Host Extensions, ARMv8.1+)
解决传统 NVHE 模式下 Host(EL1)与 KVM(EL2)频繁切换的开销:
- NVHE(Non-VHE):Host Linux 运行在 EL1,KVM 运行在 EL2;Host 调用 KVM 需通过
HVC异常,开销大。 - VHE:Host Linux 直接运行在EL2,KVM 与 Host 共享 EL2 环境;
- 消除 EL1 ↔ EL2 切换开销
- Host 可直接函数调用 KVM 接口
- 页表格式兼容,简化内存管理
- 现代 AArch64 服务器(如 Neoverse N1/N2)默认启用 VHE。
KVM-AArch64 整体架构
软件栈分层
┌─────────────────────────────────────────────────┐ │ User Space │ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ QEMU │ │ libvirt │ │ 其他管理工具 │ │ │ └──────────┘ └──────────┘ └──────────────┘ │ ├───────────────────┬─────────────────────────────┤ │ Kernel Space │ KVM Module (EL2) │ │ ┌──────────────┐ │ ┌───────────────────────┐ │ │ │ Linux Kernel │◄─┼─►│ CPU/内存/中断虚拟化 │ │ │ │ (EL1/EL2) │ │ │ (Trap 处理、页表管理)│ │ │ └──────────────┘ │ └───────────────────────┘ │ └───────────────────┴─────────────────────────────┘ ▲ ▲ │ │ ▼ ▼ ┌─────────────────────────────────────────────────┐ │ Hardware (AArch64) │ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ CPU │ │ GIC │ │ 其他外设 │ │ │ └──────────┘ └──────────┘ └──────────────┘ │ └─────────────────────────────────────────────────┘核心组件
KVM 内核模块(
kvm.ko、kvm-arm.ko)- 运行在 EL2,负责 CPU 虚拟化、内存虚拟化、中断虚拟化、vCPU 调度。
- 提供
/dev/kvm接口,供 QEMU 等用户态工具使用。
QEMU
- 设备模拟(virtio-net、virtio-blk、串口、显卡等)
- VM 生命周期管理(创建、启动、暂停、销毁)
- 与 KVM 交互,下发虚拟化指令
GICv3/v4(中断控制器)
- 硬件支持虚拟中断(vIRQ、vFIQ)
- KVM 直接配置 GIC 虚拟接口,Guest 可直接访问,减少 Trap。
CPU 虚拟化原理(核心:Trap-and-Emulate)
vCPU 模型
- 每个 vCPU 对应一个 Linux 内核线程(
kvm_vcpu_thread)。 - vCPU 状态(寄存器、PC、SP、标志位)保存在
struct kvm_vcpu中。 - 世界切换(World Switch):Host ↔ Guest 时,硬件 / 软件保存 / 恢复 vCPU 上下文。
执行流程(Guest 运行 → Trap → 处理 → 恢复)
Guest 运行(EL1/EL0)
- 非敏感指令直接在硬件执行,无开销。
- 普通异常(如系统调用、缺页)由 Guest 内核(EL1)处理。
敏感操作触发 Trap(EL2)
- 执行
WFI/WFE、修改TTBR0_EL1、访问协处理器等 → 硬件自动跳转到 EL2 异常向量表。 - KVM 捕获异常,解析异常原因(ESR_EL2 寄存器)。
- 执行
KVM 处理(EL2)
- 模拟指令:如
WFI→ KVM 调度该 vCPU 让出物理 CPU。 - 内存虚拟化:Stage 2 缺页 → KVM 分配物理页、更新 Stage 2 页表。
- 中断注入:将物理中断转为虚拟中断,注入到 vCPU。
- MMIO 模拟:Guest 访问设备寄存器 → KVM 转发给 QEMU 模拟。
- 模拟指令:如
恢复 Guest 执行(EL1/EL0)
- 处理完成后,KVM 执行
eret指令,返回 Guest 继续执行。
- 处理完成后,KVM 执行
关键指令与异常
- HVC 指令:Guest 主动陷入 EL2(类似 x86
vmcall),用于 PV 操作(如 virtio 通知)。 - SMC 指令:陷入 EL3(TrustZone),KVM 可拦截并模拟。
- 异常路由:通过
HCR_EL2.IMO/FMO/AMO控制物理中断是否路由到 EL2。
内存虚拟化原理(两阶段翻译 + 影子页表)
地址空间模型
- Guest VA:Guest 进程虚拟地址(EL0)
- Guest IPA:Guest 物理地址(EL1 看到的 “物理内存”)
- Host PA:真实物理地址(EL2 管理)
Stage 2 页表管理
- 每个 VM 拥有独立的 Stage 2 页表,由 KVM 维护。
VTTBR_EL2指向当前 VM 的 Stage 2 页表基址,VM 切换时更新。- 硬件自动完成 Stage 1(VA→IPA)+ Stage 2(IPA→PA)翻译,无需软件干预。
内存分配与映射
- QEMU 向 KVM 申请 Guest 内存(
KVM_SET_USER_MEMORY_REGION)。 - KVM 分配物理页,建立IPA → PA的 Stage 2 映射。
- Guest 触发 Stage 2 缺页时,KVM 懒分配 / 映射物理页。
大页(Huge Page)支持
- AArch64 支持 2MB/1GB 大页,KVM 可配置 Stage 2 使用大页,大幅降低 TLB miss 率,提升性能。
中断虚拟化原理(GICv3/v4 + 虚拟中断)
GICv3/v4 虚拟化硬件支持
- CPU 接口:物理 CPU 接口(ICC_)+ 虚拟 CPU 接口(ICV_),Guest 直接访问虚拟接口。
- ** redistributor**:每个物理 CPU 对应一个 redistributor,支持虚拟中断路由。
- 中断虚拟化寄存器:
ICH_*(Interrupt Controller Hyp),KVM 用于配置虚拟中断。
中断处理流程
- 物理中断到达:外设发送物理 IRQ → GIC → 路由到 EL2(
HCR_EL2.IMO=1)。 - KVM 处理:
- 识别中断目标 VM/vCPU。
- 将物理中断转换为虚拟中断(vIRQ)。
- 通过 GIC 虚拟接口注入到目标 vCPU(写
ICV_IAR0_EL1等)。
- Guest 接收:vCPU 在 EL1 收到 vIRQ,执行 Guest 中断处理程序。
虚拟定时器
- AArch64 提供虚拟定时器(
CNTVCT_EL0、CNTV_CVAL_EL0),Guest 直接访问,无需 Trap。 - KVM 配置虚拟定时器,实现每个 vCPU 独立时间片。
设备虚拟化原理(MMIO + Virtio)
MMIO 设备模拟(纯软件模拟)
- Guest 访问设备寄存器(IPA 空间)→ Stage 2 无映射 → Trap 到 EL2。
- KVM 解析地址,判断为 MMIO → 转发给 QEMU。
- QEMU 模拟设备行为,返回结果 → KVM 注入到 Guest 寄存器。
- 缺点:每次访问都触发 Trap,性能低。
Virtio 半虚拟化(高性能方案)
- 前端:Guest 内核驱动(virtio-net、virtio-blk 等)。
- 后端:QEMU/KVM 实现的设备后端。
- 共享内存:Guest 与 Host 共享环形缓冲区(virtqueue),减少数据拷贝。
- 通知机制:Guest 通过
HVC指令或 MMIO 通知 Host,Host 通过虚拟中断通知 Guest。 - 优势:接近原生性能,是 AArch64 虚拟化主流设备方案。
KVM-AArch64 启动与初始化流程
- 硬件初始化:Bootloader 启用 EL2,设置
HCR_EL2,进入 EL2 模式。 - Linux 启动:
- VHE 模式:Linux 直接运行在 EL2,检测
ARM64_HAS_VIRT_EXTN。 - NVHE 模式:Linux 运行在 EL1,通过
HVC与 EL2 KVM 交互。
- VHE 模式:Linux 直接运行在 EL2,检测
- KVM 模块加载:
- 检查 EL2 可用、虚拟化扩展支持(
is_hyp_mode_available())。 - 初始化 EL2 异常向量表、Stage 2 页表管理、GIC 虚拟化、虚拟定时器。
- 检查 EL2 可用、虚拟化扩展支持(
- QEMU 创建 VM:
- 打开
/dev/kvm,创建 VM(KVM_CREATE_VM)。 - 设置 Guest 内存(
KVM_SET_USER_MEMORY_REGION)。 - 创建 vCPU(
KVM_CREATE_VCPU),初始化 vCPU 上下文。 - 配置设备(virtio、串口等),启动 vCPU 线程。
- 打开
性能优化关键技术
- VHE 启用:消除 EL1 ↔ EL2 切换开销,Host 与 KVM 同 EL2 运行。
- Stage 2 大页:使用 2MB/1GB 大页,降低 TLB 压力。
- Virtio 全虚拟化:优先使用 virtio 设备,避免 MMIO 模拟。
- 中断亲和性:将物理中断绑定到指定物理 CPU,减少跨 CPU 调度。
- vCPU 绑核:将 vCPU 线程绑定到物理 CPU,提升缓存命中率。
- PV 操作:使用
HVC指令实现高效 PV 接口,减少 Trap。
与 x86 KVM 核心差异
| 特性 | AArch64 KVM | x86 KVM |
|---|---|---|
| 特权模型 | EL0/EL1/EL2/EL3 分层 | Ring 0~3 平面模型 |
| 虚拟化层 | 独立 EL2 异常级别 | VMX root/non-root 模式 |
| 内存虚拟化 | 硬件两阶段翻译(Stage 1+2) | EPT(Extended Page Tables) |
| 中断虚拟化 | GICv3/v4 硬件虚拟中断 | APICv/Posted-Interrupt |
| Host 运行模式 | VHE:Host 运行在 EL2 | Host 运行在 Ring 0(VMX root) |
| 敏感指令处理 | HCR_EL2 位控 Trap | VMCS 配置 Exit 条件 |
总结
KVM-AArch64 深度融合 ARMv8 硬件虚拟化扩展,以EL2 特权隔离、两阶段地址翻译、GIC 硬件中断虚拟化为基石,通过Trap-and-Emulate实现高效、安全的虚拟化。VHE 与 Virtio 进一步消除软件开销,使 AArch64 虚拟化性能接近原生,满足边缘、云原生、服务器等场景需求。
