ARM 虚拟化
从软件开发者视角理解 ARMv7-A 虚拟化扩展的设计思想,以及 Hypervisor 如何借助硬件实现多个 Guest OS 的安全隔离。
1. 引言
现代 Cortex-A 处理器拥有越来越强的计算能力,但很多场景并不满足于”运行一个操作系统”。
例如,在一辆智能汽车中,娱乐系统通常运行 Linux,而制动、转向等安全关键任务则运行实时操作系统(RTOS)。两者需要共享同一套硬件平台,却又必须彼此隔离:Linux 的崩溃不能影响 RTOS,普通应用也不能访问安全关键资源。
类似的需求也广泛存在于工业控制、通信设备和云服务器中。它们希望:
- 在一颗 CPU 上同时运行多个操作系统;
- 每个操作系统拥有独立的地址空间和设备资源;
- 一个系统发生故障,不影响其他系统继续运行。
最直接的办法当然是使用多颗 CPU,但这意味着更高的成本、更大的功耗以及更复杂的硬件设计。
于是,虚拟化提供了另一种思路:
让一颗物理 CPU 看起来像多颗独立的 CPU,每个操作系统都认为自己独占整个系统。
这就是虚拟化(Virtualization)的核心思想。
然而,这里马上会产生一个新的问题。
Linux 内核一直认为自己运行在处理器的最高特权级,可以自由访问所有内存、控制所有外设、响应所有异常。如果现在同时运行两个 Linux,它们都会认为自己拥有整个系统,那么冲突几乎不可避免。
因此,要实现虚拟化,仅仅依靠软件远远不够。处理器必须提供专门的硬件支持,让多个 Guest OS 都能够正常运行,却又始终处于 Hypervisor 的管理之下。
1.1 ARMv7-A 虚拟化扩展
ARMv7-A 虚拟化扩展并不是重新设计处理器,而是在原有架构基础上增加了一系列专门面向虚拟化的硬件能力,使多个 Guest OS 能够在同一套硬件上高效运行,并尽可能无需修改原有代码。
主要新增了以下四项能力:
- Hyp Mode(PL2):新增比 PL1 更高的特权级,专门运行 Hypervisor,负责管理 Guest OS 和系统资源。
- Stage 2 地址翻译:在传统 MMU 的基础上增加第二阶段地址翻译,使 Hypervisor 能够控制 Guest 对物理内存的访问。
- 中断虚拟化:物理中断可以先路由到 Hypervisor,再由 Hypervisor 转发给对应的 Guest,实现多个 Guest 共享同一套中断控制器。
- HVC(Hypervisor Call)指令:Guest OS 可通过 HVC 主动请求 Hypervisor 提供服务,类似于用户程序通过 SVC 调用操作系统。
这些硬件机制共同构成了 ARMv7-A 虚拟化扩展的基础。它们的目标只有一个:
让多个 Guest OS 都认为自己独占整台机器,而实际的资源分配和访问控制则全部由 Hypervisor 负责。
后续章节将分别介绍这些机制的工作原理,其中最核心的便是 Hyp Mode 和 两阶段地址翻译(Stage 2 Translation)。
1.2 Hypervisor 的两种部署方式
Hypervisor 根据自身所处的位置,通常分为两种类型。
- Type 1(Bare Metal Hypervisor):Hypervisor 直接运行在硬件之上,最先接管处理器和外设,再启动各个 Guest OS。由于没有 Host OS 参与,资源控制能力强、开销低,因此广泛应用于服务器、汽车电子和工业控制等场景。
1 | Guest OS |
常见实现包括 Xen、Jailhouse、VMware ESXi 等。
- Type 2(Hosted Hypervisor):Hypervisor 作为普通应用运行在 Host OS 之上,由 Host OS 负责管理硬件资源,再由 Hypervisor 为 Guest OS 构建虚拟机。这种方式开发简单,更适合桌面开发和测试环境。
1 | Guest OS |
典型代表包括 VirtualBox、VMware Workstation。
不过,对于 ARMv7-A 虚拟化扩展来说,这种分类并不是重点。无论 Hypervisor 属于哪一种类型,它们最终都依赖处理器提供的 Hyp Mode、两级地址翻译和虚拟中断等硬件机制来管理 Guest OS。本文后续讨论的内容,同样适用于这两类 Hypervisor。
2. PL2 特权级别
在虚拟化扩展出现之前,ARMv7-A 的 Normal World 中只有两个特权级别:
| 特权级别 | 运行模式 | 典型软件 |
|---|---|---|
| PL0 | User (USR) | 用户态应用程序 |
| PL1 | SVC, FIQ, IRQ, ABT, UND, SYS | 操作系统内核 |
虚拟化扩展新增了一个更高的特权级——PL2,以及对应的 Hyp mode(模式编码 11010)。Hyp mode 仅存在于 Non-secure(Normal)World,专门用于运行 Hypervisor。
它具有以下几个特点:
- 拥有独立的 SP_hyp 和 SPSR_hyp,与 PL1 的寄存器相互隔离。
- 复用 User 模式的 LR 作为函数返回地址,并新增专用的 ELR_hyp 保存异常返回地址。
- 只有 Hyp mode 才能访问虚拟化扩展提供的相关功能。
需要注意两点:
- SP_hyp、SPSR_hyp 是独立的 banked 寄存器,而 ELR_hyp 是 Hyp mode 专用的异常返回寄存器。
- Hyp mode 仅存在于 Normal World。与之对应,Monitor(MON)模式属于 Secure World 的 PL1,负责 TrustZone 的世界切换,两者职责完全不同。
下图展示了 Normal World 和 Secure World 中各特权级别的分布:
2.1 Bare Metal 虚拟化的启动流程
在 Type 1(Bare Metal) 虚拟化中,Hypervisor 是系统启动后运行的最高特权 Non-secure 软件。它首先完成自身初始化,然后为各个 Guest OS 建立运行环境,最后依次启动它们。
典型启动流程如下:
1 | Boot |
从 Guest OS 的视角看,它仍然运行在 PL1,并认为自己独占整台机器;而 Hypervisor 始终运行在 PL2,负责管理所有 Guest 以及底层硬件资源。
3. 两阶段地址翻译
虚拟化最大的挑战在于:Guest OS 认为自己拥有整个物理内存。
例如,Guest Linux 建立了一张页表,将虚拟地址映射到 0x80000000。如果处理器直接把这个地址当作真实物理地址访问,那么多个 Guest 就会读写同一块内存,彼此完全无法隔离。
因此,ARMv7-A 虚拟化扩展在传统 MMU 的基础上增加了第二阶段地址翻译(Stage 2 Translation)。
在传统系统中,地址只需翻译一次:
1 | VA ── Stage 1 ──→ PA |
Stage 1 页表由操作系统维护,MMU 根据页表直接得到物理地址。
而在虚拟化系统中,地址需要经过两次翻译:
1 | VA ── Stage 1 ──→ IPA ── Stage 2 ──→ PA |
其中:
- Stage 1 仍由 Guest OS 管理,将虚拟地址(VA)转换为中间物理地址(IPA)。
- Stage 2 由 Hypervisor 管理,再将 IPA 转换为真正的物理地址(PA)。
Guest OS 始终认为自己得到的是物理地址,实际上它看到的只是 IPA,真正的物理内存布局完全由 Hypervisor 决定。
也正因为如此,多个 Guest 即使都把自己的内核放在 0x80000000,最终仍可以映射到不同的物理内存,而彼此互不干扰。
注意:
- Stage 2 的页表由 Hypervisor 创建和维护,但实际的 IPA → PA 转换由 MMU 硬件在 Guest 运行过程中自动完成,并不会进入 Hyp mode。
3.1 Stage 1 (PL1&0):Guest OS 眼中的”物理地址”
Stage 1 页表完全由 Guest OS 管理。Guest 像运行在裸机上一样,配置 TTBR0/TTBR1、建立页表、设置访问权限,MMU 的工作方式与传统系统没有任何区别。
唯一的不同在于,Stage 1 的输出不再是真正的物理地址(PA),而是中间物理地址(Intermediate Physical Address,IPA)。
1 | VA ── Stage 1(Guest OS)──→ IPA |
虽然称为 IPA,但 Guest 并不知道它的存在。在 Guest 看来,Stage 1 输出的就是”物理地址”,它会像往常一样继续访问内存。
实际上,这个地址还会经过 Hypervisor 控制的 Stage 2 翻译,最终才能得到真正的物理地址(PA)。
因此,可以把 Stage 1 理解为Guest OS 眼中的地址翻译:Guest 始终认为自己控制着整个物理内存,而真正的物理内存布局则完全由 Stage 2 决定。
3.2 Stage 2 (PL1&0):Hypervisor 控制的 IPA → PA
Stage 2 由运行在 PL2 Hyp mode 的 Hypervisor 控制。
Hypervisor 通过 VTTBR 指向 Stage 2 页表:
1 | IPA ── Stage 2 ──→ PA |
Stage 2 的作用是控制:
- Guest 的物理地址空间;
- Guest 可访问的内存范围;
- 不同 Guest 之间的内存隔离。
例如:
1 | Stage 2 |
两个 Guest 可以拥有完全一样的 IPA 地址,但最终映射到不同的物理内存。
3.3 Stage 2 始终由 Hypervisor 控制
Suest OS 运行在 PL1,通过 SCTLR.M 控制自己的 Stage 1:
1 | SCTLR.M = 1 → Stage 1 enabled |
而 Hypervisor 运行在 PL2 Hyp mode,通过 HSCTLR、HCR、VTTBR 等寄存器控制虚拟化环境。Stage 2 的启用和页表映射由 Hypervisor 管理,不受 Guest 的 SCTLR.M 影响。
因此,即使 Guest OS 关闭自己的 MMU,访问仍然需要经过 Hypervisor 控制的 Stage 2 转换。:
1 | Guest Address ── Stage 2 ──> Physical Address |
这正是 ARMv7-A 虚拟化隔离的关键:
- Stage 1 负责 Guest OS 自己的虚拟地址空间;
- Stage 2 负责 Hypervisor 对 Guest 物理地址空间的管理。
两者相互独立:
1 | Guest PL1: SCTLR.M ──> Stage 1 ──> IPA |
因此,Guest OS 虽然拥有完整的内存管理能力,但它管理的只是自己的地址视图;真实物理内存的分配和隔离始终由 Hypervisor 控制。
3.4 PL2 翻译机制:Hypervisor 自己的 VA → PA
Hypervisor 运行在 ARMv7-A 的 PL2 Hyp mode 下,同样需要访问内存。因此,ARM 为 Hyp 模式提供了独立的地址翻译机制。
与 Guest 不同,Hypervisor 不经过 Stage 2:
1 | Hyp VA ── PL2 Translation ──> PA |
PL2 使用 Hypervisor 自己维护的页表,由 HTTBR(Hyp Translation Table Base Register)指向。
因此,地址转换关系为:
1 | Guest: |
Hypervisor 拥有整个系统的资源管理权限,因此不需要像 Guest 一样通过 Stage 2 虚拟化自己的物理地址视图。
3.5 三种翻译机制对比
1 | 模式 地址转换路径 控制者 |
这三种翻译机制共存于同一个 MMU 硬件中。
当处理器运行在不同模式下时,MMU 根据当前特权级别选择对应的页表和翻译路径:
- Guest PL1/0 使用 Guest 的 Stage 1;
- Hypervisor PL2 使用自己的 Hyp 页表;
- Stage 2 只用于 Guest 对物理资源的访问。
因此,Guest OS 只看到自己的 Stage 1 地址空间,并不知道 Hypervisor 在背后额外进行了一次 IPA → PA 转换。
4. Stage 2 故障处理的细节
两级地址转换意味着故障也分属于不同层级。
Stage 1 和 Stage 2 的页表由不同的软件维护,因此对应的异常处理者也不同:
- Stage 1 故障(例如 Guest 页表缺失、访问权限错误)
→ 进入 Guest OS 的 Abort handler,由 Guest 自己处理。 - Stage 2 故障(例如 Hypervisor 未建立对应 IPA 的映射、访问权限不允许)
→ 进入 Hyp 模式,由 Hypervisor 捕获并处理。
例如:
1 | Guest VA ── Stage 1 ──> IPA ── Stage 2 ──X |
Stage 2 fault 对 Guest OS 是不可见的。Guest 只知道自己的内存访问失败,而具体原因(IPA 无映射、权限限制等)由 Hypervisor 决定。
Hypervisor 可以根据故障类型采取不同策略:
- 对于合法场景(例如动态分配 Guest 内存),建立新的 Stage 2 映射后继续执行;
- 对于非法访问或不可恢复错误,可以终止 Guest。
因此,两级翻译机制形成了清晰的故障隔离:
Guest OS 负责管理自己的 Stage 1 地址空间;Hypervisor 负责管理 Stage 2 映射以及对应的资源隔离。
简单来说:
谁维护页表,谁处理对应层级的故障。
5. Hypervisor 软件的职责全景
以”功能清单”的方式逐一列出了 Hypervisor 的职责。我将它们重新组织为六个核心维度来阐述。
5.1 内存管理
内存管理是 Hypervisor 最基础的任务。归纳了三层内存管理:
在 Secure/Non-secure 两套 TTBR 之外,还有 VTTBR(指向当前 Guest 的 Stage 2 页表)和 HTTBR(指向 Hypervisor 自身的 PL2 页表)。
| 寄存器 | 用途 | 格式 |
|---|---|---|
| TTBR (Secure) | Secure 世界 Stage 1 页表 | 短描述符 / 长描述符 |
| TTBR (Non-secure) | Guest OS 使用的 Stage 1 页表 | 短描述符 / 长描述符 |
| VTTBR | 指向当前 Guest 的 Stage 2 页表 | 仅长描述符 |
| HTTBR | 指向 Hypervisor 自身的 PL2 页表 | 仅长描述符 |
两个关键设计点:
- VTTBR 和 HTTBR 强制使用 long-descriptor 格式(短描述符的最大物理地址范围不足以支持虚拟化场景)
- Stage 2 的 Abort 都在 Hyp 模式处理——Hypervisor 可以决定是分配更多物理内存还是终止 Guest
实例:三个 Guest 的 Stage 2 页表共存
1 | 物理内存布局 (1GB total): |
5.2 设备模拟 (Device Emulation)
平台设备通常采用 Memory-mapped I/O(MMIO) 方式访问。Guest 访问设备寄存器地址时,该访问同样会经过 Stage 2 翻译。
如果 Hypervisor 没有在对应 IPA 区域的 Stage 2 页表中建立有效映射,MMU 会触发 Stage 2 Abort,随后陷入 Hyp 模式。
Hypervisor 在 Abort handler 中分析异常原因,识别出这是 Guest 对设备寄存器的访问后,可以通过软件模拟设备行为:
- 返回虚拟寄存器值;
- 模拟写入效果;
- 更新设备状态;
- 触发虚拟中断。
需要注意的是:
Stage 2 fault 并不是设备模拟本身,而是 Hypervisor 利用 Stage 2 fault 作为一种“陷入机制”,主动截获 Guest 对设备的访问。
设备模拟主要解决两个问题:
共享设备仲裁
多个 Guest 都知道并使用同一个平台设备,但不能允许 Guest 直接访问真实硬件。
Hypervisor 截获访问请求,通过软件模拟统一管理设备状态,避免多个 Guest 之间产生冲突。
设备隐藏
某些设备不应该暴露给 Guest,例如:
- 设备已经分配给其他 Guest;
- 设备只允许 Hypervisor 使用;
- 平台安全策略禁止 Guest 访问。
此时 Hypervisor 可以不建立对应 Stage 2 映射,使访问触发 fault,并返回虚拟设备信息。
实例:Hypervisor 用 Stage 2 fault 模拟 UART 设备
1 | 平台 UART 真实地址: PA 0xE000_1000 |
5.3 设备分配 (Device Assignment)
设备模拟功能强大,但代价高昂——每次 Guest 访问设备都必须陷入 Hyp 模式进行软件模拟。描述了另一种选择:
Hypervisor 还可以将设备”赠与”某个 Guest 独占——Guest 可以直接操作设备而无需 Hypervisor 介入,性能接近裸机。挑战在于通过 Stage 2 映射和中断虚拟化隐藏设备的真实物理地址和中断号。
设备分配的思路很简单:把设备”送给”某个 Guest 独占。挑战在于两点:
- 设备的真实物理地址可能与 Guest 预期的不一致 → 通过 Stage 2 映射修正
- 设备产生的中断 ID 可能与 Guest 预期的不一致 → 通过中断虚拟化修正
- 一旦映射建立,Guest 就可以直接访问该设备,无需 Hypervisor 介入——性能接近裸机
通过 Stage 2 的透明映射和虚拟中断,Hypervisor 可以让 Guest 以为设备就在它期望的地址上。
实例:将 NIC 设备”赠与”Guest B 独占使用
1 | 真实 NIC 物理地址: PA 0xE000_2000 |
5.4 异常处理与虚拟异常
ARM 虚拟化扩展引入了 虚拟异常(Virtual Exceptions) 的概念,这是虚拟化环境中隔离 Guest 与真实硬件的重要机制。
物理异常(Physical Exception) 是硬件真实产生的事件,例如:外设产生 IRQ/FIQ、MMU 触发 Abort、执行非法指令产生 Undefined Exception。
虚拟异常(Virtual Exception) 是由 Hypervisor 注入给 Guest 的异常事件。它可能对应真实的物理异常,也可能完全由 Hypervisor 软件模拟产生,例如模拟设备产生的虚拟中断。
关键区别在于:
- 物理异常属于 Hypervisor 管理范围;
- 虚拟异常属于 Guest OS 感知范围。
典型流程如下:
1 | 物理异常 ──> Hypervisor ──> 虚拟异常 ──> Guest OS |
当真实物理异常发生后,Hypervisor 可以根据当前虚拟化策略决定:
- 由自己处理;
- 转换成虚拟异常注入 Guest;
- 完全模拟一个不存在的硬件事件。
因此,Guest OS 看到的只是虚拟异常,并不知道底层真实硬件事件的存在。
例如:
- 真实 UART 产生物理 IRQ;
- Hypervisor 捕获该事件;
- 更新虚拟 UART 状态;
- 通过虚拟 GIC 注入 Virtual IRQ;
- Guest UART 驱动收到中断。
从 Guest 角度看,它只是收到了一个普通设备中断。
实例:Hypervisor 利用 HCR 注入虚拟 IRQ 到 Guest
1 | Hypervisor 收到物理 IRQ #37(以太网控制器) |
同样,HCR.VF(bit 6)对应虚拟 FIQ,HCR.VI(bit 7)对应虚拟 IRQ,HCR.VA(bit 8)对应虚拟 Abort,这些位是 ARMv7-A 虚拟化扩展提供的虚拟异常注入机制。
下图汇总了物理中断从产生、被 Hypervisor 截获、到最终注入虚拟中断的完整路由路径:
5.5 中断虚拟化
虚拟化环境中的中断处理比裸机系统复杂,因为中断目标可能不是当前正在运行的 Guest。
例如:
- 当前核心上正在运行的 Guest → Hypervisor 可以直接注入虚拟中断;
- 另一个核心上的 Guest → Hypervisor 需要进行跨核调度和中断转发;
- 已经挂起的 Guest → Hypervisor 需要保存中断状态,等待 Guest 下次运行时注入。
解决方案:Hypervisor 接管物理中断,并负责虚拟中断分发。
注入流程如下:
- 物理中断触发 → 根据配置进入 Hyp 模式 → Hypervisor 处理;
- Hypervisor 判断该中断属于哪个 Guest,以及 Guest 当前是否正在运行;
- Hypervisor 通过虚拟 GIC 设置对应的 Virtual IRQ/FIQ 状态,恢复 Guest 执行后,由硬件向 Guest 注入虚拟异常。
1 | Physical IRQ ──> Hypervisor ──> Virtual GIC ──> Virtual IRQ ──> Guest OS |
Guest OS 收到的是一个普通的中断事件,处理流程与裸机环境完全一致。它只知道自己收到了一次设备中断,并不知道该中断实际上经过了 Hypervisor 的转换和注入。
5.6 Guest 调度
Hypervisor 负责调度 Guest 的虚拟 CPU(vCPU)到物理 CPU 核心上,这与传统 OS 调度任务类似。
区别在于:
- OS 调度的是进程/线程;
- Hypervisor 调度的是 vCPU。
Guest OS 认为自己的 vCPU 就是真实 CPU,可以像裸机一样运行自己的调度器,管理内部线程和进程,而不知道底层物理 CPU 的分配情况。
调度链如下:
1 | Hypervisor 调度 vCPU(粗粒度) |
这种两级调度结构是虚拟化系统的典型特征:
- Hypervisor 负责物理 CPU 资源分配;
- Guest OS 负责自身任务调度。
Guest OS 只看到自己的 vCPU,并不知道它实际运行在哪个物理核心上。
5.7 上下文切换
当 Hypervisor 将一个 Guest 换出、切换到另一个 Guest 时,需要保存当前 Guest 的运行状态,并恢复目标 Guest 的上下文。
Guest 上下文切换需要保存和恢复:
- 通用寄存器(包括各异常模式下的 banked 寄存器);
- 系统寄存器(MMU、权限控制等配置);
- 虚拟中断状态(pending / active);
- 虚拟定时器状态。
上下文切换流程:
1 | 保存 Guest A 上下文 → 恢复 Guest B 上下文 |
实例:一次完整的 Guest 上下文切换
1 | 切换场景: |
注意:物理内存页本身不参与保存和恢复。
Stage 2 翻译保证不同 Guest 使用不同的物理内存区域,Guest 切换时只需要:
1 | 更新 VTTBR |
而不需要复制或搬移内存内容。
这也是虚拟化高效运行的关键:Hypervisor 切换的是 CPU 状态和地址映射关系,而不是整个 Guest 的内存。
6. 虚拟化与 TrustZone 安全扩展的关系
ARM 系统中存在两条正交的隔离轴:
- 特权级别(Exception Level / Privilege Level)
- 安全状态(Secure / Non-secure)
两者独立工作,共同决定当前代码运行环境。
在 ARMv7-A 中:
- TrustZone 将系统划分为 Normal World 和 Secure World;
- Virtualization Extension 在 Normal World 中增加 PL2 Hyp mode。
两者关系如下:
1 | Normal World Secure World |
其中:
- Hyp mode(PL2)属于 Normal World,用于运行 Hypervisor;
- Monitor mode 属于 TrustZone,用于 Secure / Non-secure 世界切换。
关键结论:
Hypervisor 的控制范围仅限于 Normal World。
它可以管理:
- Guest OS;
- Normal World 内存;
- Normal World 设备;
- 虚拟中断和 CPU 资源。
但它不能直接控制 Secure World:
- 不能访问 Secure World 内存;
- 不能修改 Secure OS 状态;
- 不能替代 Monitor mode。
Secure World 由 Secure Monitor 管理,通过 SMC 指令完成 Normal World 与 Secure World 的切换。
7. LPAE:为虚拟化准备的地址空间扩展
虚拟化扩展要求处理器同时实现 LPAE(Large Physical Address Extension)。
原因有两个:
- 多 Guest 运行会增加物理内存需求;
- 更重要的是,ARMv7-A 的 Stage 2 翻译依赖 LPAE 的 long-descriptor 格式。
传统 ARMv7-A:
1 | VA ── Stage 1 ──→ PA |
物理地址通常限制在 32-bit(最大 4GB)。
而虚拟化环境:
1 | VA ── Stage 1 ──→ IPA ── Stage 2 ──→ PA |
需要 Hypervisor 管理更大的物理地址空间。
LPAE 将物理地址扩展到 40-bit(最大 1TB):
- 虚拟地址仍保持 32-bit;
- 物理地址扩展到 40-bit;
- 支持 long-descriptor 页表格式;
- 支持 Stage 2 地址翻译。
例如:
1 | Guest A: |
不同 Guest 可以拥有相同 IPA,而通过 Stage 2 映射到不同物理地址。
7.1 Long-Descriptor 格式
虚拟化 + LPAE 引入新的页表格式:
long-descriptor(64-bit 描述符)
与传统 short-descriptor 共存。
Long-descriptor 特性:
- 64-bit 页表描述符;
- 最多三级页表;
- 支持 40-bit 物理地址;
- 支持 1GB / 2MB / 4KB 页;
- 支持 Stage 2 翻译;
- 支持 PXN 权限控制;
- 支持 Shareable 属性。
与短描述符类似:
- 使用 TTBR0/TTBR1 指向页表;
- 使用 TTBCR 控制地址空间划分。
区别:
- Stage 1 可以使用 short 或 long descriptor;
- Stage 2 只能使用 long descriptor。
7.2 Long-Descriptor 三级页表结构
对于 32-bit VA + 4KB 页:
1 | VA[31:30] → Level 1 索引 |
页表结构:
1 | Level 1 |
一次 Stage 1 翻译:
1 | VA → L1 → L2 → L3 → PA |
最多需要 3 次页表访问。
如果开启 Stage 2:
1 | VA |
两个阶段都可能需要三级页表查询,因此最坏可能产生 6 次页表访问。
这也是为什么虚拟化系统依赖 TLB 缓存转换结果。
实例:一次 LPAE 地址翻译
1 | VA = 0x0040_1234 |
结果:
1 | 3 次页表查询完成地址翻译 |
7.3 VMID:为虚拟化而生的 TLB 标签
虚拟化扩展在 VTTBR 中引入 VMID(Virtual Machine ID),用于区分不同 Guest 的 Stage 2 地址空间。
传统系统:
1 | ASID + VA → PA |
ASID 用于区分不同进程。
虚拟化后:
1 | Stage 1: |
VMID 用于区分不同 Guest。
例如:
1 | Guest A: |
即使两个 Guest 使用相同地址,TLB 也不会混淆。
因此,切换 Guest 时无需刷新整个 TLB,只需要切换 VTTBR 指向新的 Stage 2 页表。
VMID 是 ARMv7-A 虚拟化能够高效运行的重要硬件支持。
8. 关键要点总结
- PL2 (Hyp mode) 是 ARMv7-A 虚拟化扩展的核心硬件增强——一个高于 Guest OS 的特权级别,仅存在于 Normal World,用于运行 Hypervisor。
- Stage 2 翻译是虚拟化隔离的核心——地址转换流程为:
1 | VA → IPA → PA |
其中 Stage 1 由 Guest OS 控制,将 VA 转换为 IPA;Stage 2 由 Hypervisor 控制,将 IPA 转换为真实物理地址。Guest OS 认为 IPA 就是自己的物理地址,无法感知 Stage 2 的存在。
- Stage 2 不受 Guest 控制——即使 Guest OS 关闭自己的 Stage 1(MMU disabled),Guest 的地址访问仍然受到 Hypervisor 管理的 Stage 2 约束。
- 三种地址翻译机制共存:
- PL1&0 Stage 1:Guest OS 控制,VA → IPA;
- PL1&0 Stage 2:Hypervisor 控制,IPA → PA;
- PL2 翻译:Hypervisor 自身使用,VA → PA。
- 虚拟异常是 Hypervisor 注入的事件——物理异常由 Hypervisor 根据配置进行处理,必要时向 Guest 注入虚拟 IRQ/FIQ/Abort,让 Guest 以为自己直接处理硬件异常。
- 中断虚拟化让 Hypervisor 管理物理中断分发——物理中断可以路由到 Hyp 模式,由 Hypervisor 判断归属,并转换为虚拟中断交付给对应 Guest。
- Guest 上下文切换只保存 CPU 状态,不搬移内存内容——切换时主要保存寄存器、系统寄存器、中断状态和定时器状态;通过切换 VTTBR 指向不同 Stage 2 页表,实现 Guest 内存隔离。
- Hypervisor 与 TrustZone 是两条独立隔离路径——运行在 Normal World PL2 的 Hypervisor 无法控制 Secure World,Secure World 由 Monitor 和 Secure OS 管理。
- LPAE 为虚拟化提供地址空间支持——将物理地址扩展到 40-bit(最大 1TB),并提供 long-descriptor 页表格式。Stage 2、VTTBR 和 HTTBR 使用 long-descriptor 格式。
- VMID 用于区分不同 Guest 的 Stage 2 地址空间——与 ASID 一起帮助 TLB 区分不同虚拟机和进程,使 Guest 切换时无需刷新整个 TLB,提高虚拟化性能。