gpu驱动中的MMIO和CP
在 GPU 驱动(尤其是现代图形驱动,如 Linux DRM 驱动中的 amdgpu、i915 等)中,MMIO 和 CP 是两种关键的与 GPU 通信和控制的方式。
它们分别代表不同的硬件交互机制,适用于不同场景。下面将深入浅出地解释这两个概念。
一、MMIO(Memory-Mapped I/O)
1. 什么是 MMIO?
MMIO 全称是 Memory-Mapped Input/Output(内存映射输入/输出)。它是一种 CPU 与外设(如 GPU)通信的方式:
把设备的寄存器地址映射到 CPU 的内存地址空间中,CPU 通过读写这些“内存地址”来控制硬件。
换句话说,GPU 的控制寄存器(比如启动引擎、设置状态、读取中断标志等)被“挂”在系统的物理内存地址上。驱动程序通过 mmap() 或内核的 ioremap() 将这些物理地址
映射到虚拟地址,然后像访问普通内存一样读写它们。
2. MMIO 的特点
- 低延迟、直接控制:适合配置寄存器、查询状态、触发小操作。
- 由 CPU 主动发起:每次读写都消耗 CPU 周期。
- 带宽有限:不适合传输大量数据(如纹理、顶点)。
- 同步操作:写入后通常立即生效(或在 GPU 的寄存器流水线中很快处理)。
3. 在 GPU 驱动中的用途
- 初始化 GPU(设置时钟、电源域、中断使能等)
- 启动命令处理器(CP)
- 查询 GPU 状态(是否空闲、错误状态等)
- 提交小型命令或 fence 信号
- 控制显示引擎(配合 KMS 设置分辨率等)
示例(伪代码):
// 映射 GPU 寄存器基地址 void __iomem *mmio = ioremap(gpu_mmio_base, mmio_size); // 写入寄存器:启动某个引擎 writel(0x1, mmio + ENGINE_START_REG_OFFSET);
二、CP(Command Processor / Command Processor Ring)
1. 什么是 CP?
CP 是 GPU 内部的一个专用硬件单元,全称通常是 Command Processor(命令处理器),有时也叫 Graphics Command Processor。
它的作用是:从内存中读取预先准备好的命令流(command buffer),并逐条解析、分发给 GPU 的各个引擎(如 3D 引擎、视频解码器、DMA 引擎等)执行。
驱动并不直接通过 MMIO 发送每一条绘图命令,而是:
- 在系统内存或显存中构建一个“命令缓冲区”(command buffer);
- 通过 MMIO 通知 CP 去读取这个缓冲区;
- CP 自动 fetch & execute 这些命令,无需 CPU 干预。
这类似于“批处理”模式,极大提升效率。
2. CP 的工作方式(Ring Buffer 模型)
大多数现代 GPU 使用 环形缓冲区(Ring Buffer) 作为 CP 的命令队列:
- 驱动向 ring buffer 的“尾部”写入新命令;
- GPU 的 CP 单元从“头部”读取并执行;
- 通过两个寄存器(HEAD / TAIL)协调进度(通常 TAIL 由 CPU 写,HEAD 由 GPU 更新);
- 当 TAIL 更新后,CP 自动开始处理新命令。
这种方式实现了 异步、批量、高吞吐 的 GPU 控制。
3. CP 的优势
- 高吞吐量:一次提交成百上千条命令,避免频繁 MMIO 开销。
- 降低 CPU 占用:命令执行期间 CPU 可以去做其他事。
- 支持复杂操作:如 draw call、纹理上传、同步 fence、上下文切换等。
- 天然支持多任务/多上下文:不同应用的命令可排队执行。
4. 在驱动中的体现
- Mesa(用户空间)生成 OpenGL/Vulkan 命令 → 打包成 GPU 原生指令(IB: Indirect Buffer);
- 内核 DRM 驱动将 IB 放入 ring buffer;
- 驱动通过 MMIO 写 TAIL 寄存器,通知 CP 有新工作;
- GPU 执行完成后,可能触发中断通知 CPU。
示例流程(AMD GPU):
用户程序 → Mesa → 提交 IB 到 amdgpu 驱动
↓
amdgpu 驱动将 IB 地址写入 GFX ring buffer
↓
写 MMIO 寄存器更新 TAIL 指针
↓
CP 单元自动 fetch IB 并 dispatch 给 shader engines
↓
执行完成,触发 IRQ,驱动回收资源
三、MMIO vs CP:对比总结
| 特性 | MMIO | CP(Command Processor) |
|---|---|---|
| 通信方式 | CPU 直接读写 GPU 寄存器 | CPU 提交命令缓冲区,GPU 自主执行 |
| 粒度 | 单个寄存器操作 | 批量命令(draw calls、state changes 等) |
| 性能 | 低延迟,但高 CPU 开销 | 高吞吐,低 CPU 占用 |
| 用途 | 初始化、控制、状态查询、启动 CP | 实际图形/计算 workload 执行 |
| 同步性 | 同步(写即生效) | 异步(提交后 GPU 后台执行) |
| 类比 | “手动拧螺丝” | “把图纸交给机器人流水线” |
四、实际例子:AMD GPU 中的 CP
在 amdgpu 驱动中:
- 存在多个 ring(GFX ring、Compute ring、DMA ring 等),每个对应一类工作负载;
- 每个 ring 都由一个 CP 单元管理;
- 驱动通过
amdgpu_ib_schedule()提交 indirect buffer; - 最终通过写
mmio + mmGRBM_CP_RB_CNTL等寄存器更新 TAIL。
而在 Intel i915 驱动中,类似机制称为 execlist 或 ringbuffer submission,也是基于命令缓冲区 + MMIO 触发。
五、为什么需要两者结合?
- MMIO 是“控制通道”:用于 setup、teardown、紧急干预;
- CP 是“数据通道”:用于高效执行实际 workload;
没有 MMIO,无法启动 CP;
没有 CP,GPU 只能做非常简单的操作,无法发挥现代 GPU 的并行能力。
总结
- MMIO:CPU 通过内存映射直接操控 GPU 寄存器,适合精细控制和初始化。
- CP:GPU 的命令处理器,通过 ring buffer 异步执行大批量命令,是高性能渲染的核心。
二者相辅相成,构成了现代 GPU 驱动与硬件交互的“双轮驱动”模型。
posted on 2025-12-05 14:41 lh03061238 阅读(3) 评论(0) 收藏 举报
浙公网安备 33010602011771号