4. SMMU 页表结构:Stage-1、Stage-2 与混合转换

SMMU 的页表结构是 IOMMU 地址转换的核心,它直接决定了系统如何将设备发起的 I/O 虚拟地址(IOVA)转换为最终的物理地址(PA)。ARM SMMUv3 支持两种独立的转换阶段:Stage-1 和 Stage-2,以及它们的组合——混合转换。理解这三种模式是进行页表隔离选型的基础。

4.1 Stage-1 页表:虚拟地址到中间物理地址

Stage-1 转换类似于 CPU 的 MMU 页表,负责将设备使用的 I/O 虚拟地址(IOVA) 转换为 中间物理地址(IPA)。在虚拟化场景中,IPA 通常是 Guest OS 看到的物理地址空间。

  • 输入:IOVA(设备发起的地址)
  • 输出:IPA(中间物理地址)
  • 典型用途:非虚拟化场景下的地址映射,或虚拟化场景中 Guest OS 的页表管理。
  • 页表格式:支持 4KB、16KB、64KB 页面粒度,支持 4 级页表(L0-L3)或 3 级页表(L1-L3),具体取决于配置。
关键点:Stage-1 页表由 Stream Table Entry (STE) 中的 Config[1:0] 字段控制。当配置为 0b01 时,启用 Stage-1 转换。
Stage-1 页表转换流程 Stage-1 页表转换流程 IOVA (虚拟地址) Stage-1 页表遍历 (L0-L3 多级查找) IPA (中间地址) 说明: • 输入:设备发起的 IOVA,例如 0x7F00_0000。 • 输出:经过 Stage-1 页表转换后的 IPA,例如 0x8000_0000。 • 页表基址由 STE 中的 S1ContextPtr 字段指定。

4.2 Stage-2 页表:中间物理地址到物理地址

Stage-2 转换是 ARM 虚拟化扩展的核心,它负责将 中间物理地址(IPA) 转换为最终的 物理地址(PA)。这个阶段通常由 Hypervisor/VMM 管理,用于隔离不同虚拟机的物理内存访问。

  • 输入:IPA(来自 Stage-1 的输出,或直接来自设备)
  • 输出:PA(最终的物理地址)
  • 典型用途:虚拟化场景中,Hypervisor 控制 Guest OS 对真实物理内存的访问。
  • 页表格式:与 Stage-1 类似,但使用独立的页表基址寄存器(VMID 相关)。
隔离价值:Stage-2 页表是实现 内存隔离 的关键。即使 Guest OS 的 Stage-1 页表被攻破,Stage-2 页表仍能阻止恶意设备访问其他 VM 或 Hypervisor 的内存。
Stage-2 页表转换流程 Stage-2 页表转换流程 IPA (中间地址) Stage-2 页表遍历 (VMID 关联页表) PA (物理地址) 说明: • 输入:来自 Stage-1 的 IPA,例如 0x8000_0000。 • 输出:经过 Stage-2 转换后的 PA,例如 0x9000_0000。 • 页表基址由 VTTBR_EL2 寄存器(与 VMID 关联)指定。

4.3 混合转换:Stage-1 + Stage-2 同时生效

混合转换是 SMMU 最强大的特性之一,它允许 Stage-1 和 Stage-2 页表同时生效,形成完整的 IOVA → IPA → PA 转换链。这种模式在虚拟化场景中至关重要,因为它同时提供了 Guest OS 的灵活映射和 Hypervisor 的强制隔离。

  • 转换链:IOVA → (Stage-1) → IPA → (Stage-2) → PA
  • 配置方式:STE 中的 Config[1:0] 设置为 0b11。
  • 性能影响:两次页表遍历会增加 TLB 压力,但 SMMUv3 的 TLB 支持两阶段缓存(Combined TLB 或 Split TLB)。
注意事项:混合转换模式下,Stage-1 和 Stage-2 的页表属性(如内存类型、可缓存性)会进行组合。如果两者冲突,SMMU 的行为由架构定义,通常以更严格的属性为准。务必确保两阶段属性兼容。
混合转换(Stage-1 + Stage-2)完整流程 混合转换(Stage-1 + Stage-2)完整流程 设备 (Device) IOVA Stage-1 页表 (Guest OS 管理) IPA Stage-2 页表 (Hypervisor 管理) PA 转换链: IOVA → [Stage-1 页表] → IPA → [Stage-2 页表] → PA 配置:STE.Config[1:0] = 0b11

4.4 三种模式对比与选型建议

下表总结了 Stage-1、Stage-2 和混合转换三种模式的核心差异,帮助你在实际项目中做出选择。

特性 Stage-1 仅用 Stage-2 仅用 混合转换 (Stage-1 + Stage-2)
转换路径 IOVA → IPA IPA → PA IOVA → IPA → PA
管理方 OS / Guest OS Hypervisor Guest OS + Hypervisor
隔离粒度 进程级(ASID) VM 级(VMID) 进程级 + VM 级
典型场景 非虚拟化、DPDK 虚拟化(直通设备) 虚拟化(嵌套虚拟化、GICv4)
TLB 压力 低 低 高(需两阶段缓存)
配置复杂度 低 中 高
选型建议:
  • 裸机场景:优先使用 Stage-1 仅用,简化配置,性能最优。
  • 虚拟化场景(设备直通):使用 Stage-2 仅用,由 Hypervisor 统一管理物理内存隔离。
  • 嵌套虚拟化或高级隔离需求:使用 混合转换,实现 Guest OS 灵活映射 + Hypervisor 强制隔离的双重保障。

4.5 页表配置代码示例

以下代码展示了如何通过配置 STE 来启用不同的转换模式。代码基于 SMMUv3 驱动框架(Linux 内核)。

/* SMMUv3 Stream Table Entry (STE) 配置示例 */
struct arm_smmu_ste ste = {0};

/* 配置 Stage-1 仅用 */
ste.data[0] |= FIELD_PREP(STE_CONFIG, 0b01);  // Config[1:0] = 01
ste.data[0] |= FIELD_PREP(STE_S1CTXPTR, s1_cfg->ptr); // Stage-1 页表基址
ste.data[0] |= FIELD_PREP(STE_S1CDMAX, s1_cfg->cdmax); // Context Descriptor 数量

/* 配置 Stage-2 仅用 */
ste.data[0] |= FIELD_PREP(STE_CONFIG, 0b10);  // Config[1:0] = 10
ste.data[0] |= FIELD_PREP(STE_S2VMID, s2_cfg->vmid); // VMID
ste.data[0] |= FIELD_PREP(STE_S2TTB, s2_cfg->vttbr); // Stage-2 页表基址

/* 配置混合转换 (Stage-1 + Stage-2) */
ste.data[0] |= FIELD_PREP(STE_CONFIG, 0b11);  // Config[1:0] = 11
ste.data[0] |= FIELD_PREP(STE_S1CTXPTR, s1_cfg->ptr);
ste.data[0] |= FIELD_PREP(STE_S2VMID, s2_cfg->vmid);
ste.data[0] |= FIELD_PREP(STE_S2TTB, s2_cfg->vttbr);
关键字段说明:
  • STE_CONFIG:控制转换模式(0b01=Stage-1, 0b10=Stage-2, 0b11=混合)。
  • STE_S1CTXPTR:Stage-1 页表基址指针(指向 Context Descriptor 表)。
  • STE_S2VMID:Stage-2 的 VMID,用于标识所属虚拟机。
  • STE_S2TTB:Stage-2 页表基址(VTTBR_EL2 格式)。