什么是Linux内核上下文中的DMA映射和DMA引擎?什么时候可以在Linux设备驱动程序中使用DMA映射API和DMA引擎API?任何真正的Linux设备驱动程序示例作为参考都会很棒.
什么是Linux内核上下文中的DMA映射和DMA引擎?
内核通常使用虚拟地址.功能如kmalloc()
,vmalloc()
通常返回虚拟地址.它可以存储在void*
.虚拟内存系统将这些地址转换为物理地址.这些物理地址实际上对驱动程序没用.驱动程序必须使用ioremap()
映射空间并生成虚拟地址.
CPU CPU Bus Virtual Physical Address Address Address Space Space Space +-------+ +------+ +------+ | | |MMIO | Offset | | | | Virtual |Space | applied | | C +-------+ --------> B +------+ ----------> +------+ A | | mapping | | by host | | +-----+ | | | | bridge | | +--------+ | | | | +------+ | | | | | CPU | | | | RAM | | | | Device | | | | | | | | | | | +-----+ +-------+ +------+ +------+ +--------+ | | Virtual |Buffer| Mapping | | X +-------+ --------> Y +------+ <---------- +------+ Z | | mapping | RAM | by IOMMU | | | | | | | | +-------+ +------+
如果设备支持DMA,则驱动程序使用kmalloc
或类似的接口设置缓冲区,该接口返回虚拟地址(X).虚拟内存系统将X映射到系统RAM中的物理地址(Y).驱动程序可以使用虚拟地址X来访问缓冲区,但设备本身不能,因为DMA不通过CPU虚拟内存系统.在某些系统中,只有Device可以直接对物理地址执行DMA.在某些系统中,IOMMU硬件用于将DMA地址转换为物理地址.如上图所示,它将Z转换为Y.
什么时候可以在Linux设备驱动程序中使用DMA映射API?
理由使用DMA映射API是驱动器可以返回虚拟地址X到接口等dma_map_single()
,其设置任何所需的IOMMU映射并返回DMA地址然后Z.The驱动告知装置做DMA至Z和IOMMU其映射到系统RAM中地址为Y的缓冲区.
参考来自此链接.
任何真正的Linux设备驱动程序示例作为参考都会很棒.
一个简单的PCI DMA示例
在Linux内核中,您可以查看drivers/dma中的各种真实驱动程序.