16. x86 IOMMU 支持

架构规范可以从厂商网站获取。搜索以下文档以获取最新版本

  • Intel: Intel 面向定向 I/O 的虚拟化技术架构规范 (ID: D51397)

  • AMD: AMD I/O 虚拟化技术 (IOMMU) 规范 (ID: 48882)

本指南提供了一个简要的速查表,帮助您快速了解基础知识。

16.1. 基础知识

ACPI 枚举并列出了平台上的不同 IOMMU,以及设备之间的设备范围关系(即哪个 IOMMU 控制它们)。

一些 ACPI 关键字

  • DMAR - Intel DMA 重映射表

  • DRHD - Intel DMA 重映射硬件单元定义

  • RMRR - Intel 保留内存区域报告结构

  • IVRS - AMD I/O 虚拟化报告结构

  • IVDB - AMD I/O 虚拟化定义块

  • IVHD - AMD I/O 虚拟化硬件定义

16.1.1. 什么是 Intel RMRR?

有些设备是由 BIOS 控制的,例如用于执行 PS2 模拟的 USB 设备。用于这些设备的内存区域在 e820 映射中被标记为保留。当我们在开启 DMA 翻译时,对这些区域的 DMA 将会失败。因此,BIOS 使用 RMRR 来指定这些区域以及需要访问这些区域的设备。操作系统需要为这些区域设置同一映射(unity mappings),以便这些设备能够访问这些区域。

16.1.2. 什么是 AMD IVRS?

该架构定义了一种与 ACPI 兼容的数据结构,称为 I/O 虚拟化报告结构 (IVRS),用于向系统软件传递与 I/O 虚拟化相关的信息。IVRS 描述了平台中包含的 IOMMU 的配置和功能,以及每个 IOMMU 所虚拟化的设备的信息。

IVRS 提供以下方面的信息

  • 平台中存在的 IOMMU,包括其功能和正确配置

  • 与每个 IOMMU 相关的系统 I/O 拓扑

  • 无法通过其他方式枚举的外设

  • SMI/SMM、平台固件和平台硬件使用的内存区域。这些通常是由系统软件配置的排除范围。

16.2. I/O 虚拟地址 (IOVA) 是如何生成的?

行为良好的驱动程序在向需要执行 DMA 的设备发送命令之前,会调用 dma_map_*() 函数。一旦 DMA 完成且不再需要映射,驱动程序就会调用 dma_unmap_*() 函数来取消该区域的映射。

16.3. Intel 专属说明

16.3.1. 图形问题?

如果您遇到图形设备的问题,可以尝试添加选项 intel_iommu=igfx_off 来关闭集成图形引擎。如果这解决了任何问题,请务必提交 Bug 报告此问题。

16.3.2. IOVA 的一些例外情况

中断范围不会进行地址翻译(0xfee00000 - 0xfeefffff)。对等传输(peer-to-peer transactions)也是如此。因此,我们从 PCI MMIO 范围中保留这些地址,以便它们不会被分配用于 IOVA 地址。

16.4. AMD 专属说明

16.4.1. 图形问题?

如果您遇到集成图形设备的问题,可以尝试在内核命令行中添加选项 iommu=pt,为 IOMMU 使用 1:1 映射。如果这解决了任何问题,请务必提交 Bug 报告此问题。

16.5. 故障报告

当报告错误时,IOMMU 会通过中断发出信号。故障原因以及导致该故障的设备会打印在控制台上。

16.6. 内核日志示例

16.6.1. Intel 启动消息

会打印类似以下内容的信息,指示 ACPI 中存在 DMAR 表

ACPI: DMAR (v001 A M I  OEMDMAR  0x00000001 MSFT 0x00000097) @ 0x000000007f5b5ef0

当 DMAR 正在被 ACPI 处理和初始化时,会打印 DMAR 位置以及任何已处理的 RMRR

ACPI DMAR:Host address width 36
ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000
ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000
ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000
ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff
ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff

当 DMAR 启用以供使用时,您会注意到

PCI-DMA: Using DMAR IOMMU

16.6.2. Intel 故障报告

DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
DMAR:[fault reason 05] PTE Write access is not set
DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
DMAR:[fault reason 05] PTE Write access is not set

16.6.3. AMD 启动消息

会打印类似以下内容的信息,指示存在 IOMMU

iommu: Default domain type: Translated
iommu: DMA domain TLB invalidation policy: lazy mode

16.6.4. AMD 故障报告

AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0007 address=0xffffc02000 flags=0x0000]
AMD-Vi: Event logged [IO_PAGE_FAULT device=07:00.0 domain=0x0007 address=0xffffc02000 flags=0x0000]