1.概述
IOMMU全称为 Input-Output Memory Management Unit,即输入输出内存管理单元。IOMMU是连接在系统I/O总线和主内存之间的一个硬件单元,其主要功能是将设备DMA访问请求中的虚拟地址转换为物理内存地址,并在此过程中执行访问权限检查。
2.发展历程
IOMMU的发展与虚拟化、安全需求和硬件架构演进紧密相连。
2.1.早期(2000年代前):无IOMMU时代
在IOMMU出现之前,外设(如网卡、磁盘控制器)进行DMA操作时,驱动软件必须为其分配连续的物理内存,并将这个物理地址直接告知设备。但存在下面的问题:
- 安全风险:一个设备通过DMA可以读写系统任意物理内存,恶意或存在漏洞的设备可能破坏内核或其它关键数据,这被称为DMA攻击。
- 内存管理困难:驱动需要处理物理内存的分配和碎片问题,且无法方便地使用如内存交换等高级功能。
- 虚拟化障碍:在虚拟机中, Guest OS以为自己拥有连续的物理内存,但实际在物理机上是离散的。没有IOMMU,设备DMA无法正确访问到Guest的实际物理内存,虚拟机性能极差,甚至无法运行。
2.2.萌芽与标准化(2000年代初-中期):
这个阶段,IOMMU的核心目标是解决 I/O虚拟化 问题,让虚拟机能够高效、直接地使用物理设备(即设备直通)。
- AMD和Intel为支持CPU虚拟化(AMD-V/Intel VT-x),分别提出了自己的I/O虚拟化解决方案,这成为了现代IOMMU的雏形。
- AMD 于2006年在其AMD-V技术中引入了 IOMMU(当时也称为GART的扩展,但功能更强)。
- Intel 于2007年左右在其VT-d技术中提供了类似的DMAR功能。
2.3.成熟与普及(2010年代至今):
- 功能扩展:IOMMU的作用超越了虚拟化,成为系统安全的基石。它被用于:
- 隔离设备内存访问,阻止DMA攻击(如利用雷电接口的DMA攻击工具)。
- 支持SVM/SVA,让用户态进程可以直接、安全地与设备通信,绕过内核。
- 架构广泛采用:
- x86:AMD-Vi和Intel VT-d成为服务器和高端PC的标配。
- ARM:在其系统架构中定义了SMMU,其设计理念与x86 IOMMU类似,广泛应用于移动设备、嵌入式系统和服务器(如ARM服务器芯片)。
- 操作系统支持:Linux内核的VFIO框架完全依赖于IOMMU来实现安全高效的设备直通和用户态驱动。Windows也有相应的支持。
3.作用
IOMMU的核心作用可以归结为以下三点:
3.1.地址翻译
IOMMU维护一个类似CPU MMU的页表(I/O页表),将设备发出的"设备地址"(可以是Guest物理地址、进程虚拟地址或专门的IOVA)转换为主机的物理地址。
IOMMU允许设备使用不连续的物理内存进行DMA,系统可以像为进程分配内存一样,为设备分配分散的物理页,然后通过IOMMU页表将其映射为连续的设备地址(IOVA)。
3.2.访问控制与隔离
IOMMU页表项中包含读、写等权限位。系统可以为每个设备(或设备组)配置独立的页表,严格限定其只能访问被授权的内存区域。这样可以防止恶意或故障设备进行越界DMA访问,保护内核和关键数据。这是应对DMA攻击的唯一硬件机制。同样一个设备的驱动程序bug不会通过DMA破坏其他设备或系统的内存。
3.3.I/O虚拟化
在虚拟化环境中,IOMMU使得:
- 设备直通:可以将一个物理设备直接分配给一个虚拟机。IOMMU负责将虚拟机看到的物理地址(GPA)翻译为真实的物理地址(SPA),并确保设备只能访问该虚拟机的内存,无法触及宿主机或其他虚拟机。
- 性能提升:避免了传统软件模拟(如QEMU)或半虚拟化(如virtio)带来的大量上下文切换和模拟开销,获得近乎原生的I/O性能。
3.4.高级功能
- 中断重映射:将设备产生的中断安全地路由到正确的虚拟机或CPU核心。
- 共享虚拟地址:允许设备和CPU使用相同的虚拟地址空间,使得用户态程序可以与设备更高效地协作(SVM/SVA)。
4.技术实现
- AMD-Vi和Intel VT-d是x86世界的两大支柱,理念相似,共同支撑了Linux VFIO等生态。
- ARM SMMU作为后来者,设计更为模块化和灵活,尤其适应了ARM架构从移动端到服务器端的全场景需求。
AMD-Vi、Intel VT-d和ARM SMMU的特点如下表所示。
| 特性/厂商 | AMD | Intel | ARM |
|---|---|---|---|
| 技术名称 | AMD-Vi | VT-d (Directed I/O) | SMMU (System MMU) |
| 核心架构 | 基于设备和页表的多级翻译结构。 | 基于根条目、上下文条目和页表的多级翻译结构。 | 设计上更灵活,遵循 ARM System Architecture,与CPU MMU(ARM的S/NS位)深度集成,支持Stage 1和Stage 2两级翻译。 |
| 地址翻译 | 支持多种页大小,采用"设备ID"查找对应的页表。 | 同样支持多种页大小,采用"Bus/Device/Function"来查找对应的页表结构。 | Stage 1: VA → IPA(类似CPU MMU) Stage 2: IPA → PA(针对虚拟机) 可单独或组合使用。 |
| 中断重映射 | 支持,称为 IRT。 | 支持,功能强大,是VT-d的重要组成部分。 | 中断虚拟化通常由独立的 GIC 处理,但SMMUv3与系统一致性关联更紧密。 |
| 虚拟化支持 | 通过将Guest的IO页表嵌套在Host的IO页表中实现。 | 通过 Extended Context 等结构支持虚拟机域标识(PASID),实现更细致的地址空间分离。 | 天生为虚拟化设计:Stage 2翻译专为虚拟机设计,支持PASID,可实现单个设备多个进程或虚拟机服务。 |
| 与CPU集成 | 独立单元,但通过HT总线与CPU紧密连接。 | 集成在北桥或现在的平台控制器中。 | 深度集成,SMMU与CPU共享一致的页表格式和属性(如内存类型、共享性)。 |
| 主要应用场景 | 服务器、工作站、消费级平台。 | 从服务器到客户端PC全覆盖,尤其在数据中心占主导。 | 无处不在:从手机、物联网设备(使用SMMU-500等)到数据中心服务器(如NVIDIA Grace、Ampere Altra,使用SMMUv3)。 |
| 特点与差异 | 设计相对简洁直接。在Linux内核中与Intel共用大部分驱动框架。 | 功能丰富,文档详尽,在虚拟化生态中部署最广。其VT-d已成为x86平台I/O虚拟化的代名词。 | 最具现代性和可扩展性。其Stage 1 + Stage 2模型清晰分析了进程地址空间和虚拟机物理地址空间。SMMUv3支持命令队列和事件队列,更像一个可编程设备,而非单纯硬件单元。 |