3. IOMMU/SMMU基础:IOMMU/SMMU的作用、基本架构与地址翻译流程
在驱动开发中,IOMMU(I/O Memory Management Unit)与SMMU(System Memory Management Unit)是实现设备隔离与DMA重映射的核心硬件单元。它们位于设备与内存总线之间,为每个设备提供独立的虚拟地址空间,从而阻止恶意或故障设备直接访问物理内存。
3.1 IOMMU/SMMU的核心作用
IOMMU/SMMU的主要职责包括:
- 地址翻译与重映射:将设备发出的DMA地址(I/O虚拟地址,IOVA)转换为物理地址(PA),实现设备地址空间的虚拟化。
- 访问权限控制:为每个设备或设备域配置读写权限,防止设备越权访问其他进程或内核的内存区域。
- 中断重映射:将设备产生的中断请求重映射到指定的CPU向量,配合中断隔离。
- DMA隔离:确保设备只能访问其被授权的物理内存区域,是实现驱动IO隔离的基石。
关键概念:在ARM架构中,SMMU是IOMMU的具体实现;在x86架构中,IOMMU通常指VT-d(Intel)或AMD-Vi。两者功能等价,本课程统一使用IOMMU指代。
3.2 IOMMU基本架构
IOMMU通常由以下几个关键组件构成:
| 组件 | 功能描述 | 典型寄存器/结构 |
|---|---|---|
| 上下文缓存 | 缓存设备上下文(Device Context),包含设备ID与页表基址的映射关系 | Context Table、Device Table Entry |
| I/O页表缓存 | 缓存最近使用的I/O页表项(类似CPU的TLB),加速地址翻译 | IOTLB、PASID Table |
| 翻译控制单元 | 执行地址翻译、权限检查、异常处理的核心逻辑 | Translation Control Register |
| 故障记录单元 | 记录翻译失败或权限违规的详细信息,供驱动或系统软件处理 | Fault Record Register、Event Queue |
| 中断重映射单元 | 将设备中断请求重映射到指定CPU及中断向量 | Interrupt Remapping Table |
下图展示了IOMMU在系统总线中的位置及其内部核心模块:
3.3 地址翻译流程详解
当设备发起DMA操作时,IOMMU执行以下地址翻译流程:
- 设备标识获取:IOMMU从总线事务中提取设备标识(如PCIe的BDF号、PASID)。
- 上下文查找:根据设备标识在上下文缓存中查找对应的设备上下文,获取页表基址(如STE、CD)。
- I/O页表遍历:使用IOVA(设备发出的DMA地址)作为输入,遍历I/O页表(多级页表结构),逐级查找物理地址。
- 权限检查:在翻译过程中检查页表项中的权限位(读/写/执行),确认设备是否被允许访问该物理地址。
- 地址输出与缓存:翻译成功后,将物理地址输出到内存总线,并将翻译结果缓存到IOTLB中,加速后续访问。
- 故障处理:若翻译失败或权限违规,IOMMU记录故障信息并触发中断,由驱动或系统软件处理。
性能优化:IOTLB的命中率直接影响DMA性能。驱动开发时应合理配置页表层级(如4KB/2MB/1GB页),减少页表遍历深度,并利用PASID实现进程级地址隔离。
下图展示了IOVA到PA的完整翻译路径:
3.4 多级页表与地址翻译示例
IOMMU通常使用多级页表结构来管理大地址空间。以ARM SMMUv3为例,典型的页表层级如下:
| 页表级别 | 输入地址位宽 | 页大小 | 描述 |
|---|---|---|---|
| L0(根页表) | bits[47:39] | 512GB | 指向下一级页表或大页映射 |
| L1 | bits[38:30] | 1GB | 支持1GB大页,减少TLB压力 |
| L2 | bits[29:21] | 2MB | 支持2MB大页,适合批量DMA |
| L3 | bits[20:12] | 4KB | 标准页粒度,灵活但遍历深度大 |
驱动开发注意:在配置IOMMU页表时,应优先使用大页(2MB或1GB)以减少页表遍历次数和IOTLB压力。但大页映射要求物理内存连续,需在驱动初始化时通过DMA API申请连续内存。
3.5 IOMMU与CPU MMU的对比
IOMMU与CPU MMU在功能上高度相似,但存在关键差异:
| 对比维度 | CPU MMU | IOMMU / SMMU |
|---|---|---|
| 服务对象 | CPU核心(进程/线程) | I/O设备(PCIe、GPU、网卡等) |
| 地址空间 | 虚拟地址(VA)→ 物理地址(PA) | I/O虚拟地址(IOVA)→ 物理地址(PA) |
| 页表管理 | 操作系统内核(如Linux的页表) | IOMMU驱动或内核DMA子系统 |
| 缓存 | TLB(Translation Lookaside Buffer) | IOTLB(I/O TLB) |
| 上下文切换 | 进程切换时刷新TLB | 设备切换或PASID切换时刷新IOTLB |
| 故障处理 | 缺页异常(Page Fault) | IOMMU故障中断(Fault Interrupt) |