iommu概述

kernel iommu

Posted by icecube on September 27, 2023

本文翻译自 An Introduction to IOMMU Infrastructure in the Linux Kernel

概述

The Input-Output Memory Management Unit (IOMMU)
是内存控制器中的一个硬件组件,用于将设备虚拟地址(也可以称为I/O地址或设备地址)转换为物理地址。
这种硬件辅助的I/O地址转换显著提高了虚拟环境中的系统性能。

IOMMU的概念类似于内存管理单元(MMU)。
IOMMU和MMU之间的区别在于,IOMMU将设备虚拟地址转换为物理地址,而MMU将CPU虚拟地址转换为物理地址。

在虚拟化环境中,客户操作系统的I/O设备的I/O操作由虚拟机监控程序(基于软件的I/O地址转换)进行翻译。
这种行为会导致性能受到负面影响。

本文涵盖以下内容:

  • PCI设备:虚拟化环境中的两种PCI设备虚拟化模型:仿真模型和透传模型。
  • Linux内核中的IOMMU子系统。
  • IOMMU DMA转换模式和IOMMU透传模式之间的区别。
  • 使用实验配置演示在客户操作系统中使用IOMMU与直通设备的使用:I/O操作将由IOMMU进行翻译。

PCI设备虚拟化模型

两种PCI设备虚拟化模型分别是仿真模型和透传模型。

仿真模型

是基于虚拟机监控程序的设备仿真
虚拟机监控程序需要控制客户操作系统与相关物理设备之间的交互。
这意味着虚拟机监控程序需要翻译设备地址(从设备可见虚拟地址到设备可见物理地址,反之亦然),
这需要更多的CPU计算能力,并在大量I/O操作时影响系统性能。
图1展示了PCI设备虚拟化的仿真模型。

透传模型

图2右侧展示了虚拟机监控程序被绕过的模型,客户操作系统与物理设备之间的交互不需要经过虚拟机监控程序。
虚拟机监控程序无需部署专用软件来仿真物理设备和翻译设备地址。这种模型通过硬件辅助组件来提高系统性能。

英特尔将这种硬件辅助组件称为“英特尔面向I/O的虚拟化技术(VT-d)”,
而AMD则称其为“AMD I/O内存管理单元(IOMMU)或AMD I/O虚拟化技术(AMD-Vi)”。

MMU和IOMMU

MMU(内存管理单元)的目标是将CPU可见的虚拟地址翻译为物理地址。
IOMMU的目的与MMU类似。IOMMU翻译的虚拟地址是设备可见的虚拟地址,而不是CPU可见的虚拟地址。
图3利用IOMMU硬件来说明PCI透传模型。

IOMMU硬件包括两个功能:

  • DMA重映射功能用于操作PCI设备的地址转换。
  • 中断重映射功能用于将PCI设备的中断路由到相应的客户操作系统。

本文重点关注DMA重映射功能。

Linux内核中的IOMMU子系统

操作系统需要了解IOMMU硬件信息,因此系统固件通过ACPI表提供了IOMMU的描述信息。

图4展示了I/O请求在Linux内核中是如何传播的。为了理解I/O地址翻译过程,将详细介绍I/O页表和数据结构。

IOMMU子系统包含三个层次:

  1. IOMMU DMA层:
    这一层接收来自I/O设备的DMA请求并将请求转发给IOMMU通用层。
    它充当DMA-API和IOMMU-API之间的粘合层。
  2. IOMMU通用层(或IOMMU-API层):
    该层提供通用的IOMMU API,用于与IOMMU DMA层和硬件特定的IOMMU层进行交互。
  3. 硬件特定的IOMMU层:
    这是一个硬件特定的驱动程序,用于与底层IOMMU硬件进行交互。
    它还根据请求的DMA地址配置适当的I/O页表,以便IOMMU硬件可以正确地转换DMA地址。
    如果请求的DMA地址无法成功翻译,IOMMU硬件会报告异常事件。

在图4中,一些字段被配置为0或1。有关详细信息,请参阅“AMD I/O虚拟化技术(IOMMU)规范”的第2.2.6节“用于客户翻译的I/O页表”,可从以下链接获取: (https://www.amd.com/system/files/TechDocs/48882_IOMMU_3.05_PUB.pdf)

IOMMU硬件特定层何时更新I/O页表取决于两种情况:

  1. 在高级配置与电源接口(ACPI)表中定义的直接映射(或身份映射)。
    当探测/初始化IOMMU硬件时,IOMMU硬件特定层会解析存储在ACPI表中的直接映射信息,并根据ACPI表配置I/O页表。
  2. 来自I/O设备的DMA请求。
    当从I/O设备发起DMA请求时,Linux内核会将它们转发并在设备驱动程序、DMA子系统和IOMMU子系统中处理,如图5所示。

图5中的步骤1至5如下所示:

  1. 设备驱动程序调用pci_map_page()或dma_map_page() API以获取物理地址。
    请注意,如果运行的操作系统处于虚拟化环境中,则物理地址指的是客户物理地址。
  2. 如果DMA请求是直接映射的,DMA子系统直接将计算得到的物理地址返回给设备驱动程序。
  3. 如果DMA请求不是直接映射的,DMA请求将被转发到IOMMU子系统。
  4. DMA子系统调用iommu_dma_map_page()请求IOMMU子系统将虚拟地址映射到物理地址。
  5. IOMMU子系统将虚拟地址映射到物理地址,并配置相应的I/O页表,以便IOMMU硬件可以正确进行地址转换。

双层地址转换

IOMMU硬件支持双层地址转换:

  1. 客户翻译,将客户虚拟地址(GVA)映射到客户物理地址(GPA)。
  2. 主机翻译(或嵌套翻译),将GPA映射到系统物理地址(SPA)。

图6说明了使用4级I/O页表进行4K字节页面转换。这将GVA转换为GPA。
GCR3表和第4级表地址的地址是SPA,而PM4E、PDPE(页目录指针项)、PDE(页目录项)和PTE(页表项)的地址是GPA。
这意味着这些GPA需要转换为SPA,以便从物理内存获取页表数据。嵌套地址转换(或主机转换)满足这一要求。
Linux IOMMU子系统构建了I/O页表和GCR3表,以便IOMMU硬件可以正确处理DMA翻译。

图7说明了使用4K字节页面转换的GPA到SPA的转换。
示例展示了3级页面表转换。第3级表的地址和所有PDE的地址都是SPA。
每个页面表条目中配置了指示到下一级页面表的PDE或指向系统物理内存地址的PTE。
PDE或PTE的第9-11位(下一级字段)指示了页面表的下一级。
PTE的下一级字段可以是0或7,表示地址转换过程的结束。

IOMMU在ACPI中的描述

系统平台固件定义了一个描述I/O虚拟化的数据结构。
Intel将此结构命名为DMA Remapping Reporting (DMAR),
而AMD将其命名为I/O Virtualization Reporting Structure (IVRS)。
它位于ACPI表中,用于通知操作系统软件有关平台上IOMMU功能和配置的信息。

有关详细信息,请参阅AMD和Intel的规范:
AMD I/O Virtualization Technology (IOMMU) Specification
Intel Virtualization Technology for Directed I/O Architecture Specification

在Linux IOMMU子系统中初始化IOMMU硬件时,IOMMU驱动程序会从ACPI表中解析IVRS。
如果系统中不存在IVRS,IOMMU驱动程序将忽略初始化流程。
相反,如果IVRS包括一个或多个I/O虚拟化定义块(IVDB),IOMMU驱动程序将基于IVRS初始化IOMMU硬件。

IVDB有两种类型:

  • I/O虚拟化硬件定义(IVHD):IVHD描述了IOMMU硬件的功能和配置,以及与每个IOMMU硬件相关的系统I/O拓扑结构。
  • I/O虚拟化内存定义(IVMD):IVMD描述了特定设备的特殊内存约束。

图8说明了AMD IOMMU硬件描述,称为IVHD。
图中显示了系统中的两个IVHD,并显示了每个IVHD连接的设备。
有关IVHD的详细信息在AMD IOMMU规范中有详细描述。

Linux内核中的IOMMU:DMA转换模式与透传模式

在虚拟化环境中广泛启用了IOMMU透传模式。
本节描述了Linux内核中IOMMU DMA转换模式和IOMMU透传模式之间的差异。
本节还列出了Linux操作系统的默认IOMMU操作模式,并提供了一个内核参数来更改IOMMU模式。
图9显示了左侧的DMA转换模式和右侧的透传模式。

这两种模式如下所示:

  • IOMMU DMA转换模式
    图9左侧显示了IOMMU DMA转换模式。
    这意味着托管操作系统(虚拟机监控程序)应用了IOMMU支持的操作进行DMA转换。
    换句话说,托管操作系统的IOMMU驱动程序会检查所有DMA请求,并配置相应的IOMMU硬件,以便IOMMU硬件可以正确地转换这些请求。

  • IOMMU透传模式
    图9右侧说明了IOMMU透传模式。从虚拟机监控程序的角度来看,它绕过了DMA转换,这意味着DMA地址等于系统物理地址。
    正如图10所示,这种模式与启用PCI透传模型一起被广泛采用,如第12页的“透传模型”中所示。以下常见问题解答解释了关于IOMMU透传模式的相关问题。

PCI透传和IOMMU透传之间有什么区别?
PCI透传模型绕过虚拟机监控程序的干预,使客户操作系统可以直接控制物理设备。
IOMMU透传模式绕过了虚拟机监控程序对DMA的翻译。
在Linux中启用IOMMU透传模式时,虚拟机监控程序不需要处理DMA请求。
PCI透传和IOMMU透传协同工作,使客户操作系统能够直接控制物理设备。

IOMMU透传模式和在BIOS设置中禁用IOMMU选项之间有什么区别?
在BIOS设置中禁用IOMMU选项意味着IOMMU硬件未被导出给操作系统软件,因为IOMMU相关的数据结构未嵌入到ACPI表中。
因此,操作系统软件无法与IOMMU硬件进行交互。在这种情况下,DMA地址等于在虚拟机监控程序中的系统物理地址(不需要DMA翻译)。

IOMMU透传模式和禁用IOMMU在操作症状上是相同的-DMA地址等于系统物理地址。
主要区别在于,在IOMMU透传模式下,客户操作系统可以通过IOMMU透传模式的帮助直接访问设备,而在禁用BIOS设置中的IOMMU选项时,客户操作系统无法直接访问设备。
多亏了IOMMU透传模式和PCI透传模型,客户操作系统可以在不进行任何软件更改的情况下直接访问物理设备。显然,托管操作系统需要一个特定的组件来在客户操作系统和物理设备之间进行交互。

在虚拟机监控程序上运行的虚拟函数I/O(VFIO)框架旨在提供用于直接设备访问的用户空间应用程序。
QEMU是一个用户空间应用程序,利用VFIO框架将物理设备的直接访问暴露给客户操作系统。
图11说明了VFIO框架如何与客户操作系统、PCI驱动程序和IOMMU驱动程序协同工作。

Linux操作系统的默认IOMMU模式

趋势表明,新的操作系统使用透传模式而不是DMA转换模式,因此这些操作系统的虚拟机监控程序可以为客户操作系统提供直接设备访问,无需重新配置默认的IOMMU模式。 可以通过附加内核参数来更改默认的IOMMU模式:

iommu.passthrough=0 或 iommu=nopt(DMA转换)
iommu.passthrough=1 或 iommu=pt(透传)

虚拟化环境中直接设备访问的先决条件如下:

  • 在系统设置(UEFI)中启用IOMMU
  • 通过内核参数在Linux内核中启用IOMMU透传模式

总结

IOMMU硬件已经在虚拟环境中广泛采用,以提高系统性能。
本文描述了PCI设备虚拟化模型、Linux内核中的IOMMU子系统、Linux IOMMU DMA转换模式和透传模式,以及如何在客户操作系统中直接使用PCI设备。
欲了解更多有关IOMMU的信息,请参阅以下文章:
在Linux和Xen中利用IOMMU进行虚拟化
为PCI透传配置主机

缩略词

ACPI Advanced Configuration and Power Interface
AMD-Vi AMD I/O Virtualization Technology
BDF Bus Number/Device Number/Function Number
DMA Direct Memory Access
DMAR DMA Remapping Reporting
DTE Device Table Entry
GCR3 Guest Control Register 3
GPA Guest Physical Address
GVA Guest Virtual Address
IOMMU Input Output Memory Management Unit
IVDB I/O Virtualization Definition Block
IVHD I/O Virtualization Hardware Definition
IVMD I/O Virtualization Memory Definition
IVRS I/O Virtualization Reporting Structure
MMU Memory Management Unit
SPA System Physical Address
VMM Virtual Machine Monitor
VT-d Intel Virtualization Technology for Directed I/O