附录 E. 使用 IOMMU 组
Red Hat Enterprise Linux 7 中引入了虚拟功能 I/O(VFIO)是一组提供用户空间驱动程序框架的 Linux 内核模块。这个框架使用输入输出内存管理单元(IOMMU)保护来启用用户空间驱动程序的安全设备访问。VFIO 启用用户空间驱动程序,如 Data Plane Development Kit(DPDK) 以及更常见的 PCI 设备分配。
VFIO 使用 IOMMU 组隔离设备,并防止在同一主机物理机器上运行的两个设备之间进行无意 直接内存访问(DMA),这会影响主机和客户机功能。Red Hat Enterprise Linux 7 提供了 IOMMU 组,它比 Red Hat Enterprise Linux 6 中的旧 KVM 设备分配有显著提高。本附录突出显示了以下内容:
- IOMMU 组概述
- 设备隔离的重要性
- VFIO 的好处
E.1. IOMMU 概述
IOMMU 为设备创建一个虚拟地址空间,其中每个 I/O 虚拟地址(IOVA)可能会转换为物理系统内存中的不同地址。转换完成后,设备会连接到物理系统内存中的不同地址。如果没有 IOMMU,所有设备都具有物理内存的共享平面视图,因为它们缺少内存地址转换。使用 IOMMU 时,设备会接收 IOVA 空间作为一个新的地址空间,对于设备分配非常有用。
不同的 IOMMU 具有不同的功能级别。过去,IOMMUs 已有限,仅提供翻译,并且通常仅针对地址空间的小窗口提供转换。例如,IOMMU 只保留在内存中的 IOVA 空间小窗口(1 GB 或更少),此空间由多个设备共享。AMD 图形地址重新映射表(GART)用作通用 IOMMU,就是此模型的一个示例。这些典型 IOMMU 主要提供两种功能: 退回缓冲区和 地址合起来。
- 当设备的寻址功能低于平台中的功能时,需要 退回缓冲区。例如,如果设备的地址空间限制为 4GB(32 位),并且驱动程序被分配给超过 4 GB 的缓冲区,则该设备将无法直接访问缓冲区。这种情况需要使用反转缓冲区;一个位于较低的内存中的缓冲空间,其中设备可以执行 DMA 操作。在完成该操作时,缓冲区中的数据仅复制到驱动程序分配的缓冲区中。换句话说,缓冲区将从较低的内存地址退回到更高的内存地址。IOMMU 可避免通过在设备的地址空间内提供 IOVA 转换来避免反转缓冲。这允许设备直接执行 DMA 操作到缓冲区,即使缓冲区已超过设备的物理地址空间。过去,IOMMU 功能通常是 IOMMU 的独占用例,但在采用 PCI-Express (PCIe)时,所有非传统端点都需要支持上述 4GB 的能力。
- 在传统内存分配中,根据应用程序的需求分配和释放的内存块。使用此方法可造成在物理地址空间中分散的内存空白。如果内存差距相结合,最好使用,以便更高效地使用,如果收集了内存差距,则最好在基本术语中使用。IOMMU 将这些分散内存列表与 IOVA 空间一致,有时被称为 scatter-gather 列表。这样,IOMMU 可创建连续的 DMA 操作,并最终提高 I/O 性能的效率。在最简单的示例中,驱动程序可以分配在物理内存空间中不连续的两个 4KB 缓冲区。IOMMU 可以为这些缓冲区分配连续范围,以便 I/O 设备能够执行单个 8KB DMA,而不是两个独立的 4KB DMA。
虽然内存耦合和退回的缓冲对于主机上的高性能 I/O 来说非常重要,但虚拟化环境的 IOMMU 功能是现代 IOMMU 的隔离功能。在 PCI-Express 前面无法进行隔离,因为传统 PCI 不用请求设备的 ID 标记事务(请求 ID)。虽然 PCI-X 包括请求者 ID 的一些程度,但具有事务所有权的互连设备规则也不提供对设备隔离的全面支持。
借助 PCIe,每个设备的事务都会使用对设备的唯一请求者 ID 进行标记(PCI 总线/设备/功能号,通常简写为 BDF),用于引用该设备的唯一 IOVA 表。现在,可以使用隔离功能,IOVA 空间只能用于转换操作,如卸载无法访问内存和 coalesing 内存,但也可以用于限制该设备中的 DMA 访问。这允许将设备相互隔离,防止重复分配内存空间,这对于适当的客户机虚拟机设备管理来说至关重要。在客户机虚拟机中使用这些功能,涉及为虚拟机使用 guest-physical-to-host-physical memory 映射为分配的设备填充 IOVA 空间。完成后,该设备会在客户机虚拟机地址空间中透明执行 DMA 操作。