news 2026/5/25 21:55:48

PCIe Direct Memory Access (DMA) - 软硬件工作原理完全手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PCIe Direct Memory Access (DMA) - 软硬件工作原理完全手册

前置知识:

PCIe信号链路架构及其Linux kernel系统软件完全开发指南

Linux kernel中断系统架构及应用

PCIe 中断系统之MSI

基于PCIe doorbell同步的系统软件实现

DMA 允许 PCIe 设备直接与系统内存之间传输数据,而无需 CPU 持续参与,从而显著提升性能。

一、PCIe DMA架构


二、核心组件:

  1. 系统组件架构

图片

  1. DMA Engine

· 内置于 PCIe endpoint设备中(如 NIC、GPU、存储控制器)

· 管理PCIe EP与system memory之间的数据移动

· 包含address、length和控制寄存器

图片

  1. 地址转换

· 设备视角:使用 Bus Mastering 访问系统内存

· 地址类型:

· Physical Addresses:旧式系统,直接访问物理内存

· IOVA:在 IOMMU/SMMU 支持下,设备看到虚拟地址

· DMA Address:用于transaction的最终地址

  1. Descriptor Ring

struct dma_descriptor {
dma_addr_t data_addr;
u32 length;
u32 flags; // 所有权、完成状态、中断
};
// CPU 和设备之间共享的描述符循环缓冲区

图片
4. TLP流程

图片
4. DMA状态机

图片
三、关键工作流程:

  1. 设置阶段(驱动初始化)

// 驱动设置示例

dma_addr_t dma_handle;

void *cpu_buffer = dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL);

device_registers->dma_source_addr = dma_handle;

device_registers->dma_dest_addr = device_buffer_addr;

device_registers->dma_length = size;

  1. DMA 传输类型:

A. Memory-to-Device (写入设备)

CPU 内存 → PCIe 设备

  1. CPU 在系统内存中准备数据

  2. 驱动编程设备的 DMA 寄存器

  3. 设备发起读请求来获取数据

  4. 数据通过 PCIe root complex 流向设备

B. Device-to-Memory (从设备读取)

图片
PCIe 设备 → CPU 内存

  1. 设备数据就绪

  2. 驱动编程目标地址

  3. 设备发起写事务

  4. 数据被直接写入系统内存

  5. Scatter-Gather DMA

· 处理非连续的内存缓冲区

· 描述符链/列表:

timeline

title PCIe DMA Scatter-Gather传输时间线 section 准备阶段 t0: Driver准备scatter list : ┌───────┬───────┬───────┬───────┐ : │ 页 0 │ 页 1 │ 页 2 │ ... │ : ├───────┼───────┼───────┼───────┤ : │ PA0 │ PA1 │ PA2 │ PAn │ : │ 4KB │ 4KB │ 8KB │ ... │ : │ 有效 │ 有效 │ 有效 │ ... │ : └───────┴───────┴───────┴───────┘ : scatterlist初始化完成 section DMA传输阶段 t1: DMA引擎获取第一个描述符 : ┌─────────────────────────────┐ : │ DMA描述符读取 │ : ├─────────────────────────────┤ : │ DMA Addr = PA0 (0x1000) │ : │ Length = 4KB (0x1000) │ : │ Flags = 有效 │ 链式 │ : │ Next = 描述符1地址 │ : └─────────────────────────────┘ : 从描述符环读取第一个描述符 t2: 传输第一个页面 : ┌─────────────────────────────┐ : │ PCIe TLP: 传输页0数据 │ : ├─────────────────────────────┤ : │ Type: MWr (内存写) │ : │ Addr: 0x1000 (IOVA) │ : │ Length: 4KB │ : │ Tag: 0x01 │ : │ Data: 页0内容 │ : └─────────────────────────────┘ : 生成TLP包并通过PCIe链路传输 t3: DMA引擎获取下一个描述符 : ┌─────────────────────────────┐ : │ DMA描述符读取 │ : ├─────────────────────────────┤ : │ DMA Addr = PA1 (0x2000) │ : │ Length = 4KB (0x1000) │ : │ Flags = 有效 │ 链式 │ : │ Next = 描述符2地址 │ : └─────────────────────────────┘ : 自动获取下一个描述符 t4: 传输第二个页面 : ┌─────────────────────────────┐ : │ PCIe TLP: 传输页1数据 │ : ├─────────────────────────────┤ : │ Type: MWr (内存写) │ : │ Addr: 0x2000 (IOVA) │ : │ Length: 4KB │ : │ Tag: 0x02 │ : │ Data: 页1内容 │ : └─────────────────────────────┘ : 第二个TLP包传输 ...: 继续后续页面传输 : 循环处理所有scatterlist条目 t5: 传输最后一个页面 : ┌─────────────────────────────┐ : │ DMA描述符读取 │ : ├─────────────────────────────┤ : │ DMA Addr = PAn │ : │ Length = 页n大小 │ : │ Flags = 有效 │ 结束位 │ : │ Next = NULL │ : └─────────────────────────────┘ : 最后一个描述符,结束位被置位 section 完成阶段 t6: 全部传输完成 : ┌─────────────────────────────┐ : │ DMA状态更新 │ : ├─────────────────────────────┤ : │ 所有描述符完成 │ : │ 传输字节数累计完成 │ : │ 错误状态位清零 │ : │ 完成标志位置位 │ : └─────────────────────────────┘ : DMA引擎停止工作 t7: 触发中断 : ┌─────────────────────────────┐ : │ MSI/MSI-X中断产生 │ : ├─────────────────────────────┤ : │ 中断向量: 0x20 │ : │ 消息地址: 0xFEE00000 │ : │ 消息数据: 0x0001 │ : │ 优先级: 高 │ : └─────────────────────────────┘ : 向CPU发送完成中断信号

描述符 0: [地址1, 长度1, 下一个]

描述符 1: [地址2, 长度2, 下一个]

描述符 2: [地址3, 长度3, 结束]

· 设备按顺序处理描述符

通过 IOMMU 进行地址转换:

设备请求 → IOMMU 转换 → 物理内存

IOVA 页表 实际 RAM

IOMMU 优势:

  1. 隔离性(设备无法任意访问内存)

  2. 在 32 位系统上使用 64 位地址

  3. 支持无需连续物理内存的 scatter-gather

四、传输过程示例:

逐步说明:设备到主机传输

  1. 驱动准备:

    · 分配接收缓冲区

    · 用缓冲区地址编程设备 DMA 寄存器

    · 启用 DMA 引擎

  2. 设备动作:

    · 生成 PCIe Memory Write TLP

    · 数据包包含目标地址和数据

    · 通过 PCIe 层级结构路由

  3. Root Complex 动作:

    · 接受来自设备的 TLP

    · 需要时执行地址转换

    · 转发给内存控制器

  4. 完成:

    · 设备触发中断(MSI/MSI-X)

    · 驱动处理已完成的传输

    · 回收缓冲区以供下次传输使用

五、同步机制:

  1. 完成机制

· 轮询:驱动检查状态寄存器

· 中断:MSI/MSI-X 用于低延迟通知

· Completion Queues:独立的ring用于完成状态

  1. 高级特性

· 描述符聚合:批量处理多个描述符

· Header/Data Splitting:分离元数据和有效载荷

· SR-IOV:具有独立 DMA 引擎的 Virtual Functions

同步注意事项:

缓存一致性

DMA 方向 | 所需操作

---------------------|-------------------

DMA_TO_DEVICE | DMA 前刷新缓存

DMA_FROM_DEVICE | DMA 后使缓存失效

DMA_BIDIRECTIONAL | DMA 前刷新 & DMA 后失效

图片
3. 内存屏障

// 确保设备开始前 DMA 设置完成

wmb(); // 写内存屏障

device_registers->dma_start = 1;

六、错误处理:

  1. PCIe 错误报告

    · Poisoned TLP 检测

    · Completer abort/timeout

    · ECRC 错误

  2. DMA 超时

    · 用于卡住传输的看门狗定时器

    · 设备复位序列

七、示例:网卡 RX 路径

  1. 驱动预分配 RX 缓冲区,将 DMA 地址提供给 NIC

  2. NIC 接收数据包,通过 DMA 写入下一个可用缓冲区

  3. NIC 更新描述符状态,触发中断

  4. 驱动处理数据包,向 NIC 提供新缓冲区

  5. 循环继续

八、总结与扩展:

  1. 降低 CPU 负载 - CPU 仅设置传输,不复制数据

  2. 更高带宽 - 设备可饱和 PCIe 链路

  3. 更低延迟 - 到内存的直接数据路径

  4. 并行性 - 多个设备可同时进行 DMA

· Peer-to-Peer DMA:设备到设备的直接传输

· CXL.mem:具有缓存一致性的连贯 DMA

· ATS:设备管理的地址转换缓存

这种架构实现了现代高性能 I/O,GPU、NVMe SSD 和 NIC 都利用 DMA 来达到最大吞吐量。

谢谢关注,后续会持续分享关于AI,GPU,Linux开发,操作系统,图形学,高性能计算,芯片行业讯息。欢迎感兴趣的伙伴关注微信公众号参与讨论沟通:
请关注公众号获取完整系统资料*********************请关注微信公众号:颇锐克科技共享*********************

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 4:35:57

FanFicFare终极指南:3步快速上手网络小说下载神器

FanFicFare终极指南:3步快速上手网络小说下载神器 【免费下载链接】FanFicFare FanFicFare is a tool for making eBooks from stories on fanfiction and other web sites. 项目地址: https://gitcode.com/gh_mirrors/fa/FanFicFare FanFicFare是一款强大的…

作者头像 李华
网站建设 2026/5/26 4:39:08

计算机毕业设计|基于Java + vue水果商城系统(源码+数据库+文档)

水果商城系统 目录 基于springboot vue水果商城系统 一、前言 二、系统功能演示 详细视频演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取: 基于springboot vue水果商城系统 一、前言 博主介绍…

作者头像 李华
网站建设 2026/5/26 4:36:33

Cloudflare防火墙拦截谷歌爬虫|导致收录失败怎么解决?

许多站长发现网站突然从谷歌搜索结果中“消失”,背后很可能是Cloudflare防火墙误拦截了谷歌爬虫(Googlebot),导致搜索引擎无法正常抓取页面。由于Cloudflare默认的防护规则较为严格,尤其是针对高频访问的爬虫IP&#x…

作者头像 李华
网站建设 2026/5/26 5:39:10

揭秘Wan2.2-T2V-A14B背后的MoE混合专家架构优势

揭秘Wan2.2-T2V-A14B背后的MoE混合专家架构优势 你有没有想过,一段简单的文字——比如“一只红狐狸在雪地中奔跑,镜头缓缓拉远”——是如何变成一段流畅、光影自然、动作真实的720P视频的?这可不是魔法,而是AI视觉生成技术的一次巨…

作者头像 李华
网站建设 2026/5/26 5:43:47

理解LoadRunner,基于此工具进行后端性能测试的详细过程(上)

1、LoadRunner 的基本原理 后端性能测试工具通过虚拟用户脚本生成器生成基于协议的虚拟用户脚本,然后根据性能测试场景设计的要求,通过压力控制器控制协调各个压力产生器以并发的方式执行虚拟用户脚本,并且在测试执行过程中,通过系…

作者头像 李华
网站建设 2026/5/25 8:42:58

AI大模型+Agent终极指南!从入门到落地,三大行业案例让你一篇看透!

本文将从AI Agent和大模型的发展背景切入,结合51Talk、哈啰出行以及B站三个各具特色的行业案例,带你一窥事件驱动架构、RAG技术、人机协作流程,以及一整套行之有效的实操方法。具体包含内容有:51Talk如何让智能客服“主动进攻”&a…

作者头像 李华