🗓️Linux x86-64 IOMMU 详解(三)——Intel IOMMU(硬件 IOMMU)的功能与基本原理
2023-10-17
| 2023-10-17
字数 2681阅读时长 7 分钟
type
status
date
slug
summary
tags
category
icon
password
URL

前言

本系列的第一篇文章已经提到,IOMMU 分别有软件和硬件实现方式。软件 IOMMU 就是 SWIOTLB,上一篇文章已经进行过详尽的介绍。而对于硬件 IOMMU,有多个厂商都设计了自己的 IOMMU。由于我的开发机器为 Intel x86 平台,因此接触的是 Intel IOMMU。
刚开始,我也找过网上很多资料,但是它们要么是基于较旧的 Linux 内核版本,要么理解不够深入。因此,即使我并没有深入地掌握 Intel IOMMU 的每一处细节,我还是愿意将自己所了解的知识,以尽可能浅显的形式展现出来。
本文的三张截图,均来自《Intel VT-d SPEC》,它是 Intel IOMMU 的官方文档。
关于 Intel IOMMU,我打算分两篇文章来写。本文介绍 Intel IOMMU 的功能与基本原理,而下一篇文章(不知道咕咕咕到哪天发)将会介绍 Intel IOMMU 的配置及一些核心代码。并且,随着学习的深入,这两篇文章发布之后可能还会更新。

预备知识

如果读者了解如下知识(能深入理解当然更好),你将会更容易理解本文:
  1. 了解 DMA(直接内存访问)的基本原理。
  1. 了解虚拟内存中的页表机制。
  1. 使用过虚拟机(例如 VMWare Workstation)。
  1. 了解 SWIOTLB 原理(可翻阅本系列第二篇文章)。

术语汇总

本文涉及到诸多术语,在此先进行汇总。
  1. Intel IOMMU:全称为 Intel Input/Output Memory Management Unit。根据语境,该术语在本文中,既可表示 IOMUU 的一种实现方式,也可表示 Intel IOMMU 硬件。在《Intel VT-d SPEC》中,这两种含义,都有等价表述——前者的等价表述是 Intel VT-d(全称为 Intel Virtualization Technology for Direct I/O),后者的等价表述是 Remapping Hardware。
  1. 虚拟机(Guest):顾名思义,启用虚拟化(运行虚拟机)时的虚拟机器。
  1. 宿主机(Host):启用虚拟化时,虚拟机运行所基于的物理机器,称为宿主机。
  1. HPA:Host Physical Address,在宿主机上的物理地址。不启动虚拟化时,设备看到的就是 HPA。
  1. GPA:Guest Physical Address,在虚拟机上的物理地址。启用虚拟化时,设备看到的是 GPA。Intel IOMMU 负责将 GPA 映射为 HPA。
  1. Domain:一个虚拟机所拥有的所有资源(在本文中主要是涉及内存和 CPU),称为这个虚拟机的 Domain。
  1. 重映射(Remapping):启用虚拟化时,设备发出的 DMA 和中断请求,不会直接被物理机器接收,而是会被 Intel IOMMU 所截获,而后发送到它对应的 Guest 虚拟机,之后再映射到宿主机的内存或 CPU。这个过程称为重映射。

Intel IOMMU 与 SWIOTLB 的比较

Intel IOMMU 与 SWIOTLB 同为 IOMMU 的实现方式,二者在目的上存在共性——都能够解决 “设备无法直接寻址到内核分配给它的 DMA buffer” 这一问题。
二者的不同点在于:
  1. 功能。Intel IOMMU 最大的功能,并不是用来解决 “设备寻址能力有限” 这一问题——解决上述问题仅仅是 Intel IOMMU 顺便附带的一个功能。事实上,Intel IOMMU 只是我们从功能角度的称谓,它的全称叫做 Intel Virtualization Technology for Direct I/O,简称为 Intel VT-d。其核心功能是重映射(Remapping),指的是在启用虚拟化技术(Virtualization Technology,可以简单理解为开启虚拟机)的机器上,对 I/O 操作(包括 DMA 和中断)进行重映射。关于什么是重映射,后文将会详细介绍。
  1. 实现方式。SWIOTLB 底层是用 memcpy() 实现的,需要 CPU 的参与;而 Intel IOMMU 是通过专门的硬件实现的。

什么是重映射

我们先举例说明重映射的应用场景。以最常见的虚拟机软件 VMWare Workstation 为例,经常使用它的用户一定会有这样的经历:你在一台 Windows 机器上,使用 VMWare Workstation,开启了一台 Linux 虚拟机。为了方便表述,本文称此时的物理机(Host,Windows 机器)为宿主机,而虚拟机(Guest,Linux 机器)仍称为虚拟机
然后,你往机箱上插入一个 U 盘。U 盘就是一个设备,它将会进行 I/O 操作。这时,系统将会弹出对话框,询问你要把 U 盘连接到哪台机器,你可以选择连接到 Windows 机器(宿主机)或是 Linux 机器(虚拟机)。如果你选择连接到虚拟机,那么该 U 盘之后的 I/O 操作,就会触发重映射。
为了理解重映射,我们首先考虑没有启用虚拟化(即没有启动虚拟机)的机器。对于这样的机器,设备发起 DMA 请求,得到的就是机器物理地址;设备的中断请求,也会被 CPU 直接接收,而后通过中断向量表,找到对应的中断服务程序,处理该中断请求。这个过程是没有重映射的。
现在,假设一台宿主机上开启了虚拟机(甚至可以开启多个虚拟机),并且设备连接到其中某一台虚拟机。这就意味着,设备能访问到的,只有它所连接的虚拟机的所有资源(一个虚拟机的所有资源,称为一个 Domain),而不会访问到其他虚拟机,更不能直接访问宿主机。因此,我们必须确保:
  1. 设备发起 DMA 请求时,操作系统返回给它的,不能是宿主机物理地址(Host Physical Address,HPA),而只能是虚拟机物理地址(Guest Physical Address,GPA)。Intel IOMMU 维护从 GPA 到 HPA 的映射关系。
  1. 设备的 DMA 和中断请求,只能被它所连接的虚拟机接收,而不能被其他虚拟机接收,也不能被宿主机直接接收。
这个过程对于设备来说应当是透明的。从设备的视角来看,它发起 DMA 请求,得到一个内存物理地址,并向该地址读写内容;或者,它发起中断请求,最终得到某个中断服务程序的响应。这一切都应该正常发生,与设备所连接的是虚拟机还是宿主机无关——事实上,设备只知道自己连接的是一台 “机器”,而根本不知道自己连接的机器是虚拟机还是宿主机。
在这个过程中,Intel IOMMU 完成如下功能:
  1. DMA 重映射:Intel IOMMU 截获设备的 DMA 请求,将它重定位到设备所连接的虚拟机。而后,该虚拟机将 DMA 请求传递给宿主机,宿主机分配 DMA Buffer,并返回用于 DMA Buffer 的 HPA。Intel IOMMU 将 HPA 转换为 GPA,而后返回 GPA 给设备。之后,设备向 GPA 进行 DMA 操作,Intel IOMMU 又将 GPA 映射为 HPA。
  1. 中断重映射:Intel IOMMU 截获设备的中断请求,将它重定位到设备所连接的虚拟机。而后,找到该虚拟机所占有的 CPU,将中断请求转发给这些 CPU,而后这些 CPU 找到适用于该虚拟机的中断重映射表(Interrupt Remapping Table,IRT,原理与中断向量表相同,只是每个虚拟机都有一份),通过中断号索引到对应的中断服务程序并执行。

DMA 重映射中的 I/O 页表

对于 DMA 重映射,我们完全可以仿照虚拟内存机制(将内存虚拟地址转换为内存物理地址)来理解。事实上,Intel IOMMU 硬件维护了一套用于 DMA 重映射的 I/O 页表机制,它与虚拟内存机制中的多级页表原理基本一致,只有一点不同——其中的顶级 I/O 页表,并不是直接用于寻址(Address Translation),而是用于将 DMA 请求映射到不同的虚拟机 Domain。从次级 I/O 页表开始,才是真正的寻址过程。
具体来说,在虚拟化环境下,设备发起 DMA 请求时,除了常规参数以外,还需要附带一系列标识符(称为 Request Identifier 或 Source ID),包括 Bus/Device/Function(具体含义笔者也不是很了解…)。标识符的作用就是让 Intel IOMMU 确定该设备需要将 DMA 请求发送到哪个虚拟机 Domain。
notion image
Intel IOMMU 根据这些标识符,在顶级 I/O 页表中进行索引,找到对应的次级 I/O 页表。事实上,顶级 I/O 页表又可分为两部分——Root Table 和 Context Table,如下图所示。Intel IOMMU 先根据 Request Identifier 的 Bus 区段,在 Root Table 中索引;而后,再根据 Device 和 Function 区段,在 Context Table 中索引,从而找到对应的次级页表(下图中的 Second-Level Page Table)。
从次级页表开始,寻址过程就与内存虚拟地址转换为物理地址的过程,完全相同了。
此外,下图中,有两个 Context Table 都指向了同一个 Domain——Domain A。这表明,不同的设备最终连接到同一个虚拟机,这也是合情合理的——一台机器当然可以连接多个设备,不是吗?
notion image
如果上述解释还不够详细,请看《Intel VT-d SPEC》中的原文截图,其中重要语句已用红色下划线标注:
notion image
 
  • 内存管理
  • iommu
  • dma
  • Linux x86-64 IOMMU 详解(二)——SWIOTLB(软件 IOMMU)Linux x86-64 IOMMU 详解(四)——启用 Intel IOMMU 的配置
    Loading...