跳到主要内容
主页代理入口联系客服

地址模型

DMA 地址、物理地址与 IOVA:设备真正使用的是哪一个地址?

讨论 DMA 时,“虚拟地址”“物理地址”和“总线地址”常被混用。驱动写入设备描述符的地址,应该来自操作系统的 DMA 映射接口;在启用 IOMMU 的系统上,它通常是设备可见的 I/O Virtual Address(IOVA),不应假定等于 CPU 物理地址。

最后审核: 2026-09-05发布:Heino HMA Hardware Lab

先分清三个地址空间

CPU 虚拟地址供软件使用,系统物理地址描述内存位置,DMA 地址供设备使用。它们可能数值相同,也可能经过 IOMMU 或平台映射而完全不同。

软件使用CPU 虚拟地址
内存位置物理地址
设备使用DMA 地址 / IOVA
建立者OS DMA API

三个地址空间分别服务谁

应用和驱动通常通过 CPU 虚拟地址访问内存;处理器页表把它转换为系统物理地址。设备则使用由 DMA 子系统返回的设备地址。

当平台没有额外转换时,DMA 地址有时可能与物理地址数值相近;一旦存在 IOMMU、总线窗口或设备寻址限制,这个假设就不再可靠。代码不应依赖偶然相等。

IOVA 如何连接设备与内存

驱动向操作系统提交一个缓冲区和传输方向,DMA 子系统建立设备可以使用的映射,并返回 DMA 地址。IOMMU 可以把该 IOVA 转换到一页或多页实际内存,同时执行访问权限检查。

映射只应覆盖当前操作需要的范围和时长。完成传输后释放映射,是避免失效地址继续被设备使用的重要部分。

为什么需要 Scatter/Gather

一个逻辑连续的网络包或文件缓冲区,在物理内存中可能由多段不连续页面组成。Scatter/Gather 列表向设备描述这些可传输片段,避免为了连续物理内存而进行额外复制。

Windows 的 map registers 和 Linux DMA API 都把这类地址转换交给平台 DMA 层。驱动应使用返回的列表和长度,而不是自行把 CPU 指针当作设备地址。

方向、所有权与缓存一致性

DMA 映射还包含传输方向和缓冲区所有权。CPU 与设备在错误时机同时修改同一缓冲区,或忽略平台缓存一致性要求,可能得到旧数据、部分更新或内存损坏。

正确实现会在提交设备前完成必要同步,在硬件完成后再把缓冲区交回软件,并保留可复核的错误与超时路径。

评审驱动时应检查什么

检查设备地址是否全部来自受支持的 DMA API,映射和取消映射是否配对,Scatter/Gather 长度是否受硬件限制约束,以及错误恢复后是否仍引用旧描述符。

日志应固定操作系统、IOMMU 状态、驱动、设备固件和硬件版本。单次传输成功只能证明一条路径工作,不能证明所有边界条件安全。

  • 不把普通指针或未经映射的物理地址直接交给设备
  • 不在设备仍拥有缓冲区时释放或复用内存
  • 在映射失败、取消、超时和复位路径同样回收资源

常见问题

01IOVA 一定不同于物理地址吗?

不一定。某些平台可能产生相同数值,但驱动必须把它视为独立的设备地址,不能依赖数值相等。

02应用程序的指针可以直接写进 DMA 描述符吗?

不可以这样假定。应用指针属于进程虚拟地址空间,必须经过操作系统和驱动的固定、授权与 DMA 映射流程。

03Scatter/Gather 是否会绕过 IOMMU?

不会。它描述多个可传输片段;每个设备地址仍应受平台 DMA 映射和权限控制。

04映射完成后可以永久复用 DMA 地址吗?

只有专门设计的长期一致性映射才有相应生命周期。流式映射在取消后不得继续使用。

官方参考资料

  1. Microsoft:Map Registers 与 DMA 地址空间
  2. Linux Kernel:DMA API 使用指南
  3. Intel:VT-d 架构规范
  4. AMD:IOMMU 概念与地址转换
HMA 安装支持