概述
直到 WDDM 3.0,Dxgkrnl 仅支持通过 1:1 物理重新映射实现 IOMMU 隔离,这意味着 GPU 访问的逻辑页被转换为相同的物理页码。 IOMMU DMA 重新映射允许 GPU 通过不再以 1:1 映射的逻辑地址访问内存。 相反,Dxgkrnl 能够提供逻辑上连续的地址范围。
Dxgkrnl 对 GPU 施加限制:GPU 必须能够访问所有物理内存才能启动设备。 如果 GPU 的最高可见地址不超过系统上安装的最高物理地址,则 Dxgkrnl 将无法初始化适配器。 即将推出的服务器和高端工作站可以配置超过 1 TB 的内存,突破了许多 GPU 常见的 40 位地址空间限制。 DMA 重新映射用作允许 GPU 在此环境中工作的机制。
在启动时,Dxgkrnl 通过将设备的最高可访问物理地址与系统上安装的内存进行比较来确定是否需要逻辑重新映射。 如有必要,DMA 重新映射用于将 GPU 可见边界内的逻辑地址范围映射到系统上的任何物理内存。 例如,如果 GPU 限制为 1 TB,则 Dxgkrnl 将从 [0, 1 TB) 分配逻辑地址,然后可以通过 IOMMU 映射到系统上的任何物理内存。
逻辑适配器与物理适配器
Dxgkrnl 区分逻辑适配器和物理适配器的概念。 物理适配器代表一个单独的硬件设备,它可能与 LDA 链中的其他设备链接。 逻辑适配器表示一个或多个链接的物理适配器。
每个逻辑适配器创建一个 IOMMU DMA 域,并将其连接到所有链接的物理适配器。 因此,所有物理适配器共享相同的域和相同的物理内存视图。
集成 GPU 与离散 GPU 支持
由于 IOMMU DMA 重新映射对集成 GPU 几乎没有价值,因此,根据定义,集成 GPU 应该已经被设计为访问系统中的所有物理内存,因此在集成部件上实现支持是可选的,但建议这样做。
离散 GPU 必须支持 IOMMU DMA 重新映射,这是 WDDM 3.0 认证的要求。
DDI 更改
为了支持 IOMMU DMA 重新映射,进行了以下 DDI 更改。
驱动程序功能
需要两组驱动器上限来支持线性重新映射:
- 驱动程序必须通知 Dxgkrnl 其物理内存限制;即,通过 DXGKQAITYPE_PHYSICAL_MEMORY_CAPS 及其关联的 DXGK_PHYSICAL_MEMORY_CAPS 结构,可以获得其最高可见物理地址。
- 驱动程序必须通过 DXGKQAITYPE_IOMMU_CAPS 及其关联的 DXGK_IOMMU_CAPS 结构表示其对 IOMMU 线性重新映射的支持。 通过指示支持,驱动程序指示支持和使用稍后介绍的所有 DDI。
在 Dxgkrnl 通过 DXGKDDI_START_DEVICE 启动设备之前,必须提供这两个上限,以便可以在访问任何内存之前创建设备并将其连接到 IOMMU 域。 只有当设备不引用任何现有物理内存时,才能进行线性重新映射。
独占访问
IOMMU 域的连接和分离速度极快,但目前还不是原子的。 这种情况意味着,在交换到具有不同映射的 IOMMU 域时,不能保证通过 PCIe 发出的事务能够正确转换。
为了处理这种情况,从 Windows 10 版本 1803 (WDDM 2.4) 开始,KMD 必须实现以下 DDI 对,以便 Dxgkrnl 调用:
- 将调用 DxgkDdiBeginExclusiveAccess,以通知 KMD IOMMU 域切换即将发生。
- DxgkDdiEndExclusiveAccess 在 IOMMU 域切换完成后调用。
每当设备切换到新的 IOMMU 域时,驱动程序必须确保其硬件保持无提示。 也就是说,驱动程序必须确保在这两次调用之间不会从设备读取或写入系统内存。
在这两个调用之间,Dxgkrnl 做出以下保证:
- 计划程序已挂起。 所有活动工作负载都被刷新,并且不会向硬件发送或在硬件上计划新的工作负载。
- 没有进行其他 DDI 调用。
作为这些调用的一部分,驱动程序可以选择在独占访问期间禁用和禁止中断(包括 Vsync 中断),即使没有 OS 的明确通知。