DMAR
DMAR(DMA Remapping Reporting)表,是ACPI表中的一张子表。在系统上电时,BIOS/UEFI负责检测并初始化重定向硬件,为这些设备分配相应的物理地址,并在DMAR表上注册对应的信息。其也是操作系统和VTD重定向硬件交互控制的桥梁,所以理解表上对应的结构含义对于使用VTD技术来说至关重要。
目前对于VTD技术的详细文档以及DMAR表结构与上面的子结构,主要依赖Intel发布的VTD白皮书:《Intel Virtualization Technology for Directed I/O》,本文为笔者学习VTD相关知识所记录的一些随笔
解析DMAR相关的结构可以用RWEverything工具
Rw.exe运行后会自动加载其驱动并读取相关的物理地址并解析出结构展示。比如我们要看DMAR表需要先打开 ACPI Table 然后在下面的标签中打开DMAR标签,rw工具会输出本机DMAR表的物理地址并给出hex dump以及解析出的结构信息
我们可以在 《Intel Virtualization Technology for Directed I/O》chapter8.1: DMA Remapping Reporting Suructure 查到DMAR表的结构
我们也可以对照这个结构,自己在内存页面手动解析对应的结构
DRHD
在DMAR表上我们主要要关注的是 Remapping Structure[] 结构,这是一个数组结构(不是指针数组)。其中每一个结构都是联合体,第一个字段是Type,决定这个成员是什么类型:DRHD、RMRR、ATSR、RHSA等,并且不同的类型大小也不一样,所以第二个字段通常是length,决定这个成员的大小。在遍历时候就从下表0开始取type和length向下解析获得整个数组的结构。
在这些类型中需要重点关注的是 DRHD(DMA Remapping Hardware Unit Definition) 结构,这个结构唯一的标识平台中存在的重映射硬件单位。DRHD的结构如下
重点需要关注的是 Flags 和 Register Base Address 两个字段:
- Flags : 只有0或1两种情况,简单来说如果是0的话里面的设备只有部分设备,为1的话里面会有指定节区的全部设备。所以我们需要关注的是Flags=1的DRHD
- Register Base Address : VT-D重定向硬件寄存器基地址
Register Descriptions
Register Base Address 指向的就是重映射寄存器组,其管理重映射功能的相关属性,也是软件通过读写这些寄存器控制VTD重映射机制。虽然说是寄存器,但这里可以把它当作内存来理解(但又不是真的内存,在Intel上用直接内存访问是访问不到这块区域的,应该将其理解为寄存器在内存空间的映射)。值得注意的是开启VBS后这块区域会被HyperV接管保护,届时Guest将无法访问这块区域。
我们可以在 《Intel Virtualization Technology for Directed I/O》chapter11.4: Register Descriptions 查到重映射寄存器组的结构
主要用到的是前0x40的部分,其中我们重点要关注的是+0x20的 Root Table Address Register(RTADDR_REG),它里面存储了 Root-Table 的地址。然后我们要注意,并非 RTADDR_REG 直接就是 Root-Table 的地址,其低位被BIOS复用作为标识其他的一些信息,只有 63:12 位才是 Root Table Address
我们可以在 《Intel Virtualization Technology for Directed I/O》chapter11.4.5: Root Table Address Register 查到 Root Table Address Register 的结构
其中我们要重点关注的是 11:10 位,TTM: Translation Table Mode。该位标识当前使用的DMA Remapping所用的转化模式。其有四种值:
- 00b: Legacy Mode : 标准传统模式,使用Root-Table和Context-Table两级结构
- 01b: Scalable Mode : 可拓展模式
- 10b: Reserved : 保留值
- 11b: Abort-DMA Mode : 中止所有的DMA操作
LegacyMode是目前主流的转化模式,后面的内容也均在此模式上介绍
Root-Table & Context-Table
在介绍 Root-Table 之前还需要介绍一个概念,就是 PCI Source Identifier, 相关内容在 《Intel Virtualization Technology for Directed I/O》chapter3.4.1: Source Identifier 中介绍。VTD要求每一个参与地址转换的硬件设备需要有一个唯一的 source-id 标识。在PCIE设备中使用 Bus:Device:Function 作为这个唯一标识,该标识的分配方式和系统对设备的遍历相关。
VTD使用Domains管理各个设备映射的内存,而作为顶层结构的根表(Root-Table)的作用就是将这些设备映射到各自的domains上。根表本质是一个4KB的内存页,其中包含256个根条目(root-entries),(即每个root-entry占用16Bytes=4*1024/256),覆盖PCI总线号空间(0-255),而每一个root-entry包含上下文表(Context-Table)的指针,
Context-Table的结构也是类似的,每个Context-Table表包含256个条目对应于 Bus:Device:Function 的 Device 和 Function,即通过设备号和功能号组成index索引得到 Second-Stage Page Table(SSPT) 指针, 该指针指向顶级页表。不同的设备可以配置相同的指针,这样这些设备就会被分配到同一个域,使用相同的地址转化关系。
总结其实就是,通过Root-Table和Context-Table这二级表完成了每一个 Bus:Device:Function 到Domain的映射
PS:我们可以看到 3:0:0 的SSPT指针(其实是Context Entry)是 00000009,00000002,这是什么意思呢?这需要了解一下 Context Entry 结构
Context Entry
不仅是 00000009,00000002,我们看到一些SSPT指针的低位是有值的,但寻址时我们会忽略低位的值。比如 335AC001, 00000001 这样一个ContextEntry我们会找到其SSPT指针值为 0x1335AC000。这是因为BIOS复用了Entry的低位标识一些属性。具体参考 《Intel Virtualization Technology for Directed I/O》chapter9.3: Context Entry
这里讲两个比较关键的位
- P: Present : 有效位,只有该位被设置才标识该Entry是有效的
- TT: Translation Type : 这里需要注意的是 10b,也就是PassThrough直通模式,因为untranslated请求直接通过不进行地址转化,此时SSPT会被忽略,相当于直接内存访问不走VTD的SSDT页表了,所以也就是我们所说的“全允许访问”。在上一节中我们看到 3:0:0 的ContextEntry是 00000009,00000002,即 1001b,对应P位为1、TT为 10b,也就是 3:0:0 这个设备当前为PassThrough直通模式,对所有内存全允许访问。
- SSPTPTR : 这个就很好理解了,12位到63位是真正的SSPT指针值,所以在寻址的时候要忽略低位的属性值
地址转换流程
通过Root-Table和Context-Table将每一个设备精确的指向一个 Second-Stage Page Table 结构,根据该结构的信息将I/O设备的DMA请求地址转化为物理地址(PA->PA, 类似于EPT的转化)。SSPT和内存页表一样,支持N级结构,其具体是几级取决于硬件支持的 Guest Address Width(GAW),
比如我的电脑在 2:0:0 的位置是NVM Express存储控制器,可以用RWEveryThing整理出整个寻址关系
地址转化关系的详细图文介绍在 《Intel Virtualization Technology for Directed I/O》chapter3.5: Hierarchiacal Translation Structures,这边做个速记摘要
转换为4KB页:
- 使用输入地址的bits 47:39索引PML4表
- 使用bits 38:30索引PDPT
- 使用bits 29:21索引PDT
- 使用bits 20:12索引PTT
- 组合PTE中的物理页帧号和输入地址的bits 11:0得到最终物理地址
转换为2MB大页
- 使用输入地址的bits 47:39索引PML4表
- 使用bits 38:30索引PDPT
- 使用bits 29:21索引PDT
- 当PD条目中PS=1时,直接组合PD条目中的21位页帧号和输入地址的bits 20:0
转换为1GB大页
- 使用输入地址的bits 47:39索引PML4表
- 使用bits 38:30索引PDPT
- 当PDP条目中PS=1时,直接组合PDP条目中的30位页帧号和输入地址的bits 29:0
Reference
- 《Intel Virtualization Technology for Directed I/O》 chapter3: DMA Remapping
- 《Intel Virtualization Technology for Directed I/O》 chapter8: BIOS Considerations
- 《Intel Virtualization Technology for Directed I/O》 chapter9: Translation Structure Formats
- Introductory Study of IOMMU (VT-d) and Kernel DMA Protection on Intel Processors
- https://zhuanlan.zhihu.com/p/51110851
- https://geekdaxue.co/read/u2321266@lb7ty6/vizldy