Windows 图形显示驱动开发-WDDM 2.4功能-基于 IOMMU 的 GPU 隔离(三)

帧缓冲区保留

对于必须在电源转换期间将帧缓冲区的保留部分保存到系统内存的驱动程序,Dxgkrnl 会在适配器初始化时对所需内存进行用量认可。 如果驱动程序报告 IOMMU 隔离支持,则 Dxgkrnl 将在查询物理适配器上限后立即调用 DXGKDDI_QUERYADAPTERINFO,内容如下:

  • Type 为 DXGKQAITYPE_FRAMEBUFFERSAVESIZE
  • 输入类型为 UINT,即物理适配器索引。
  • 输出类型为 DXGK_FRAMEBUFFERSAVEAREA,应为驱动程序在电源转换期间保存帧缓冲区保留区域所需的最大大小。

Dxgkrnl 会按驱动程序指定的数量进行用量认可,以确保始终能根据请求获取物理页面。 此操作是通过为每个物理适配器创建一个唯一的区域对象来完成的,该对象为最大尺寸指定了一个非零值。

驱动程序报告的最大大小必须是 PAGE_SIZE 的倍数。

与帧缓冲区之间的传输可以在驱动程序选择的时间进行。 为了帮助传输,Dxgkrnl 向内核模式驱动程序提供了上表中的最后四个回调。 这些回调可用于映射适配器初始化时创建的区域对象的相应部分。

在调用这四个回调函数时,驱动程序必须始终为 LDA 链中的主导设备提供 hAdapter。

驱动程序有两个实现帧缓冲区保留的选项:

  • (首选方法)驱动程序应使用 DXGKDDI_QUERYADAPTERINFO 来调用为每个物理适配器分配空间,以指定每个适配器所需的存储空间。 在电源转换时,驱动程序应每次保存或恢复一个物理适配器的内存。 此内存会被分割成多个区域对象,每个物理适配器一个。
  •  (可选)驱动程序可以将所有数据保存或还原到单个共享区域对象中。 要执行此操作,可在 DXGKDDI_QUERYADAPTERINFO 调用中为物理适配器 0 指定一个较大的最大大小,然后为所有其他物理适配器指定一个零值。 这样,驱动程序就可以将整个区域对象固定下来,供所有物理适配器的所有保存/还原操作使用。 这种方法的主要缺点是需要一次性锁定更多内存,因为它不支持只将内存的子范围固定到 MDL 中。 因此,在内存压力下,这种操作更容易失败。 此外,驱动程序还应使用正确的页面偏移量将 MDL 中的页面映射到 GPU。

 驱动程序应执行以下任务,以完成向帧缓冲区或从帧缓冲区的传输:

  • 在初始化过程中,驱动程序应使用其中一个分配回调例程预先分配一小块 GPU 可访问内存。 如果无法一次性映射/锁定整个区域对象,则使用该内存来帮助确保向前推进。

  • 在电源转换时,驱动程序应首先调用 Dxgkrnl 以固定帧缓冲区。 成功后,Dxgkrnl 会为驱动程序提供一个 MDL,用于锁定映射到 IOMMU 的页面。 然后,驱动程序就可以通过任何对硬件最有效的方式直接向这些页面执行传输。 然后,驱动程序应调用 Dxgkrnl 来解锁/取消映射内存。

  • 如果 Dxgkrnl 无法立即锁定整个帧缓冲区,则驱动程序必须尝试使用初始化时分配的预分配缓冲区来向前推进。 在这种情况下,驱动程序按小块来执行传输。 在每次迭代传输过程中(针对每个区块),驱动程序必须要求 Dxgkrnl 提供一个可将结果复制到其中的区域对象映射范围。 然后,驱动程序必须在下一次迭代之前取消区域对象的映射。

下面的伪代码是实现这种算法的一个示例。

#define SMALL_SIZE (PAGE_SIZE)PMDL PHYSICAL_ADAPTER::m_SmallMdl;
PMDL PHYSICAL_ADAPTER::m_PinnedMdl;NTSTATUS PHYSICAL_ADAPTER::Init()
{DXGKARGCB_ALLOCATEPAGESFORMDL Args = {};Args.TotalBytes = SMALL_SIZE;// Allocate small buffer up front for forward progress transfersStatus = DxgkCbAllocatePagesForMdl(SMALL_SIZE, &Args);m_SmallMdl = Args.pMdl;...
}NTSTATUS PHYSICAL_ADAPTER::OnPowerDown()
{    Status = DxgkCbPinFrameBufferForSave(&m_pPinnedMdl);if(!NT_SUCCESS(Status)){m_pPinnedMdl = NULL;}if(m_pPinnedMdl != NULL){        // Normal GPU copy: frame buffer -> m_pPinnedMdlGpuCopyFromFrameBuffer(m_pPinnedMdl, Size);DxgkCbUnpinFrameBufferForSave(m_pPinnedMdl);}else{SIZE_T Offset = 0;while(Offset != TotalSize){SIZE_T MappedOffset = Offset;PVOID pCpuPointer;Status = DxgkCbMapFrameBufferPointer(SMALL_SIZE, &MappedOffset, &pCpuPointer);if(!NT_SUCCESS(Status)){// Driver must handle failure here. Even a 4KB mapping may// not succeed. The driver should attempt to cancel the// transfer and reset the adapter.}GpuCopyFromFrameBuffer(m_pSmallMdl, SMALL_SIZE);RtlCopyMemory(pCpuPointer + MappedOffset, m_pSmallCpuPointer, SMALL_SIZE);DxgkCbUnmapFrameBufferPointer(pCpuPointer);Offset += SMALL_SIZE;}}
}NTSTATUS PHYSICAL_ADAPTER::OnPowerUp()
{Status = DxgkCbPinFrameBufferForSave(&m_pPinnedMdl);if(!NT_SUCCESS(Status)){m_pPinnedMdl = NULL;}if(pPinnedMemory != NULL){// Normal GPU copy: m_pPinnedMdl -> frame bufferGpuCopyToFrameBuffer(m_pPinnedMdl, Size);DxgkCbUnpinFrameBufferForSave(m_pPinnedMdl);}else{SIZE_T Offset = 0;while(Offset != TotalSize){SIZE_T MappedOffset = Offset;PVOID pCpuPointer;Status = DxgkCbMapFrameBufferPointer(SMALL_SIZE, &MappedOffset, &pCpuPointer);if(!NT_SUCCESS(Status)){// Driver must handle failure here. Even a 4KB mapping may// not succeed. The driver should attempt to cancel the// transfer and reset the adapter.}RtlCopyMemory(m_pSmallCpuPointer, pCpuPointer + MappedOffset, SMALL_SIZE);GpuCopyToFrameBuffer(m_pSmallMdl, SMALL_SIZE);DxgkCbUnmapFrameBufferPointer(pCpuPointer);Offset += SMALL_SIZE;}}
}

硬件保留内存

在设备连接到 IOMMU 之前,VidMm 会映射硬件保留内存。

VidMm 会自动处理任何作为带有 PopulatedFromSystemMemory 标记的内存段报告的内存。 VidMm 会根据提供的物理地址来映射该内存。

对于未通过段公开的专用硬件保留区域,VidMm 会调用 DXGKDDI_QUERYADAPTERINFO 驱动程序来查询其范围。 所提供的范围不得与 NTOS 内存管理器使用的任何内存区域相重叠;VidMm 会验证是否存在此类交叉。 此验证可确保驱动程序不会意外报告超出保留范围的物理内存区域,因而违反该功能的安全保证。

调用一次查询是为了查询所需的范围数量,而随后的第二次调用是为了填充保留范围的数组。

测试

如果驱动程序选择使用此功能,HLK 测试将扫描驱动程序的导入表,以确保没有调用以下 Mm 函数:

  • MmAllocateContiguousMemory
  • MmAllocateContiguousMemorySpecifyCache
  • MmFreeContiguousMemory
  • MmAllocatePagesForMdl
  • MmAllocatePagesForMdlEx
  • MmFreePagesFromMdl
  • MmProbeAndLockPages

 所有连续内存和 MDL 的内存分配都应通过 Dxgkrnl 的回调接口,使用列出的函数来进行。 驱动程序也不应锁定任何内存。 Dxgkrnl 会为驱动程序管理锁定的页面。 一旦重新映射了内存,提供给驱动程序的页面逻辑地址可能不再与物理地址一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/76313.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UML之扩展用例

UML用例建模面向业务实现或者系统功能,每一个用例实现一个完整的业务或者功能。而一个完整的用例也可能有一些不是必需的附加功能,或者在该用例已经实现后需要添加一些新功能,此时可以通过UML提供的扩展用例机制描述类似这样的场景。 例如对…

大数据学习(95)-谓词下推

🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…

行式存储(Row-based Storage)与列式存储(Column-based Storage)详细对比

行式存储(Row-based Storage)与列式存储(Column-based Storage)详细对比 1. 数据组织方式 类型行式存储列式存储存储结构按行存储数据,每条记录的所有字段(列)连续存放(如一条订单的…

Seg-Zero:通过认知强化实现的推理链引导分割

文章目录 速览摘要1. 引言2. 相关工作2.1. 大模型中的推理能力2.2. 结合推理的语义分割2.3. 用于分割任务的 MLLMs 3. 方法3.1. 流程建模(Pipeline Formulation)3.2. Seg-Zero 模型3.3. 奖励函数(Reward Functions)3.4. 训练&…

win server2022 限制共享文件夹d

点击配额管理中的配额 然后创建配额 导入要配额的文件即可 然后确定即可

Docker容器部署Java项目(详细版)

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Docker容器部署Java项目1. 环境及准备2. 项目…

C语言深度解析:从零到系统级开发的完整指南

一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性,成为系统级开发的首选语言。例如,Linux内核通过C语言直接操作内存和硬件寄存器,实现高效进程调度。 关键点: malloc/free直接管理内存&#…

Pytorch实现之基于GAN+序列后向选择的情绪识别增强方法

简介 简介:在WGAN-GP+CGAN的基础上利用了序列后向选择方法来挑选优质样本补充到训练集当中,丰富训练数据集。 论文题目:基于生成对抗网络的情绪识别数据增强方法 期刊:传感技术学报 摘要:使用深度学习方法构建高准确率的情绪识别模型需要大量的情绪脑电数据。 生成对抗…

软件工程面试题(十九)

1、十六进制的216转换十进制是多少: 216是16进制,转10进制: =2*16^2+1*16^1+6*16^0 =512+16+6 =536 2、Java中的XML解析方式: dom和jdom解析 Java中处理XML文档的标准API有两种,即XML的简单API(SAX,Simple API for XML)和文档对象模型(DOM,…

大模型AI Agent的工作原理与安全挑战

大模型AI Agent的工作原理与安全挑战 0x00 引言 智能体(AI Agent)作为大语言模型技术(LLM)的具体应用形式,突破了传统语言模型仅限于文字输入与输出的局限性。其通过感知环境、规划决策及执行行动的闭环机制&#xf…

腻子刮的遍数越多越好?刮的越厚墙面越平?

很多业主对刮腻子存在误区,感觉腻子刮的越厚越好,遍数越多越好。同时认为腻子有找平的作用,感觉墙面不平,就是腻子刮的不行。 有一位业主给我留言,说家里的腻子刮了两遍,然后油工师傅就开始打磨刷漆了&…

「深入解析 Chromium Message Pump:消息循环的核心驱动」

MessagePump 是 Chromium 中 消息循环(Message Loop) 的核心组件之一,负责在不同平台上管理和分发消息、事件,并协调任务调度。 在浏览器这样的 GUI 应用中,事件循环(Event Loop)是非常重要的&…

3d pose 指标和数据集

目录 3D姿态估计、3维重建指标: 数据集 EHF数据集 SMPL-X 3D姿态估计、3维重建指标: MVE、PMVE 和 p-MPJPE 都是用于评估3D姿态估计、三维重建等任务中预测结果与真实数据之间误差的指标。 MVE (Mean Vertex Error):是指模型重建过程中每个顶点的预测位置与真实位置之间…

大智慧大数据面试题及参考答案

目录 MySQL 的事务隔离级别是什么? MySQL 的覆盖索引是怎样的? MySQL 常用的存储引擎有哪些,它们之间的区别是什么? 在 MySQL 中,如果读取很大的数据集,同时进行一边 select 一边写入操作,结果会怎样? 当 ES 出现分词错误的情况时,应该如何处理? Kafka 如何保证…

微服务的简单认识

目录 一、微服务架构简介 二、微服务架构风格和分布式系统架构的关系 三、微服务组成 一、微服务架构简介 微服务是一种构建分布式系统的架构风格,它将一个大型的应用程序拆分成多个小型的、独立部署的服务单元,每个服务单元都专注于特定的业务功能,并通过轻量级的通信机…

Spring的 @Conditional @ConditionalOnProperty 注解 笔记250330

Spring的 Conditional ConditionalOnProperty 注解 Spring 的 Conditional 与 ConditionalOnProperty 注解详解 在 Spring 框架中,Conditional 和 ConditionalOnProperty 是用于动态控制 Bean 注册的重要注解。虽然它们都服务于条件化配置,但定位和使用…

电路学习——MOS栅极驱动电阻取值(2025.03.30)

参考链接1: 驱动芯片的驱动电流的选型和计算 参考链接2: NMOS栅极驱动电阻Rg阻值和功率的计算,NMOS栅极驱动电阻Rg的作用,如何防止NMOS误开通 单片机直接驱动NMOS的方法 RLC谐振电路 智能车BLDC 在此感谢各位前辈大佬的总结,写这个只是为了记…

mysql JSON_ARRAYAGG联合JSON_OBJECT使用查询整合(数组对象)字段

父表数据(表名:class) idname1一年级2二年级3三年级 子表数据(表名:students) idnameclassId11张三112李四113小明3 关联子表sql查询(推荐使用方法一) 方法一 (使用IFNull判断子…

张量-pytroch基础(2)

张量-pytroch网站-笔记 张量是一种特殊的数据结构,跟数组(array)和矩阵(matrix)非常相似。 张量和 NumPy 中的 ndarray 很像,不过张量可以在 GPU 或其他硬件加速器上运行。 事实上,张量和 Nu…

marked库(高效将 Markdown 转换为 HTML 的利器)

文章目录 前言使用基本使用自定义渲染器例子 代码高亮 前言 最近尝试了一下通过星火大模型将ai引入到项目上,但是ai返回的数据可以显而易见的发现是markedown语法的,那么就需要一个工具,将类似这种的格式转换为markdown格式 Marked 是一个用…