前言
dmadev lib顾名思义就是用来使用dma设备的框架,伴随着摩尔定律的失效,现在CPU的性能几乎很难进行提升了。那么提高性能的方式就只能是软件不够硬件来凑了,让许多工作从CPU卸载到硬件去。
dmadev lib库是DPDK中的一个软件库,提供管理和配置DMA poll mode drivers的软件,定义了统一的操作接口。支持一系列不同的DMA操作。
功能介绍
设计约束
库支持物理的(硬件)和虚拟的(软件)DMA设备。
DMA框架的组成如上图所示:
- DMA控制器有多个硬件的DMA通道(队列),每个硬件DMA通道呈现为一个dmadev。
- dmadev可以创建多个虚拟的DMA通道,每个虚拟DMA通道呈现为不通的transfer context, 比如virtual DMA channel 0 用作memory-to-memory场景,而virtual dma channel 1用作 memory-to-device场景。
- DMA操作必须提交给虚拟DMA通道。
设备管理
设备创建
物理的DMA controller在DPDK初始化时,由PCI扫描枚举出来,基于设备的BDF(bus、device、function)。其他物理DMA controller可以在DPDK命令行中指定。
dmadev由rte_dma_pmd_allocate函数根据物理DMA channel的个数创建。
设备标识
每个DMA(不论是物理还是虚拟的)设备由2个id唯一标识。
- 一个唯一的设备索引,用在DMA API接口中指派dma设备。
- 一个设备名,用在串口信息或者管理调试。
设备特性和能力
不同的dma设备可能支持不一样的特性,rte_dma_info_get API可以获取设备信息和支持的特性。
Silent mode是一种特殊的设备能力,这种设备不需要应用调用dequeue APIs。
出入队接口
DPDK主要基于轮询的方式操作,因此所有的pmd都会有出入队的接口。
Enqueue API 可以把操作传递到设备,这样的接口有rte_dma_copy和rte_dma_fill。如果入队成功,会返回一个ring_idx。ring_idx可以让应用知道到其环中定为操作的元信息。如果入队失败ring_idx是一个负值。
rte_dma_submit用于发送一个doorbell通知硬件。也可以在入队的时候,带上RTE_DMA_OP_FLAG_SUBMIT 标记自动发送doorbell通知硬件。
下面的代码描述如何入队多个拷贝操作到设备,并启动硬件进行操作。
1 | struct rte_mbuf *srcs[DMA_BURST_SZ], *dsts[DMA_BURST_SZ]; |
rte_dma_completed 和rte_dma_completed_status接口用于出队获取操作的结果。rte_dma_completed用于获取成功的个数,rte_dma_completed_status返回个数以及每个操作的执行状态(存放到一个status数组中)。这两个接口还会返回最后一个操作的ring_idx。
查询设备统计
使用rte_dma_stats_get()接口获取dmadev的统计信息,包含每个设备的如下数据:
Submitted: 提交的操作数量
Completed:已完成的操作数量(包含成功的和失败的)
Errors:完成发送错误的数量
库也支持调试接口显示相关信息:
注意点
设备使用前需要进行配置,然后再开始使用:
1 | rte_dma_configure() |
修改配置
可以调用rte_dma_configure() or rte_dma_vchan_setup(), 但前提要先调用rte_dma_stop(),配置完后rte_dma_start()开始。设备停止状态下,不要往设备发送操作。
关闭设备
使用完毕需要调用rte_dma_close关闭设备。
提交操作
先入队再发送doorbell给硬件。
1 | rte_dma_copy() |
ring_idx说明
- 每个virtual dma channel的ring_idx是独立的
- ring_idx是单调递增的数,直到UINT16_MAX才回到0
- ring_idx初始时是0,如果设备停止了,需要重置ring_idx
操作地址
操作内部的地址类型为rte_iova_t。
dmadev支持两种类型的地址: 内存地址和设备地址。
- 内存地址:memory-to-memory操作的源目地址,memory-to-device的源地址, device-to-memory操作的目的地址,如果设备支持SVA,那么这种地址可以是VA,否则必须是IOVA。
- 设备地址:memory-to-device的目的地址,device-to-memory操作的源地址
其他
所有的API都是不加锁的,不支持多个线程并发访问,不考虑多个同时调用同一个dmadev。
同一个dmadev的virtual dma channel也不支持同时调用,因为这些channel共用同一个硬件的dma channel。
更多
初步了解一下dma引擎在DPDK中的使用框架。很多公司已经实现了其dma引擎,在大数据、虚拟化等方面开始应用了。
行动,才不会被动!
欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。
博客地址: https://fishmwei.github.io
掘金主页: https://juejin.cn/user/2084329776486919