然后,CPU 调用如dma_map_single 这样的API,将总线地址Z 映射到 虚拟地址X和物理地址Y。 最后,Device 通过总线地址Z,发出DMA读请求(PCIe Memeory Read),接着IOMMU将总线地址翻译为物理地址Y 去 读写物理内存 DMA Buffer. 编程示例: struct device *dev; /* device for DMA mapping */ struct sk_buff *skb...
dma_map_single->dma_map_single_attrs->(ops->map_page)->__swiotlb_map_page-> swiotlb_map_page-> map_single 代码语言:javascript 复制 dma_addr_tswiotlb_map_page(struct device*dev,struct page*page,unsigned long offset,size_t size,enumdma_data_direction dir,unsigned long attrs){//根据页号...
dma from device时,需要先将cache中的数据invalidate掉,避免CPU读取的是原来的数据; dma_map_single函数如下: map操作时存在两种方式,直接映射或使用iommu来完成映射; dma_unmap_single是逆操作: 从上述函数中可以看到,最终都会调用到arch相关的cache操作,这个与体系结构是强相关的,以arm64为例: 最终的代码将调用到...
.map_page = iommu_dma_map_page, ---(2) .unmap_page = iommu_dma_unmap_page, .map_sg = iommu_dma_map_sg, .unmap_sg = iommu_dma_unmap_sg, .sync_single_for_cpu = iommu_dma_sync_single_for_cpu, .sync_single_for_device = iommu_dma_sync_single_for_device, .sync_sg_for_cpu =...
理解了这些底层硬件,你也就知道类似dma_map_single这样的DMA API是在做什么了。驱动在调用dma_map_single这样的接口函数的时候会传递一个虚拟地址X,在这个函数中会设定IOMMU的页表,将地址X映射到Z,并且将返回z这个总线地址。驱动可以把Z这个总线地址设定到设备上的DMA相关的寄存器中。这样,当设备发起对地址Z开始的...
返回设备的映射最大大小。映射函数的大小参数,如dma_map_single()、dma_map_page()等,不应大于返回的值。 size_t dma_opt_mapping_size(structdevice *dev) 返回设备的最大最优映射大小。 在某些情况下,映射更大的缓冲区可能需要更长的时间。此外,对于高速短暂的流式映射,用于映射的前期时间可能占总请求寿命...
互联网、Linux内核书籍上充满了各种关于Linux DMA ZONE和dma_alloc_coherent、dma_map_single等的各种讲解,由于很多童鞋缺乏自身独立的思考,人云亦云,对这些概念形成了很多错误的理解。本文的目的在于彻底澄清这些误解。 当你发现本文内容与baidu到的内容不一致的时候,以本文内容为准。
这通常通过命令行参数iommu=pt来启用。在这样的环境中,当进行DMA操作时,如在e100网卡驱动中所展示的那样,数据的物理地址(PADDR)会通过DMA映射进行处理,最终通过pci_map_single函数进行处理,调用intel_map_page函数。如果存在iommu硬件,那么这个函数最终会调用intel_map_page。在intel_map_page函数中...
我们知道DMA通常需要访问连续的物理内存,除非设备支持iommu,当设备不支持iommu的话可以用以下方式: 在内核启动是为设备保留内存将MMU内嵌到设备中,如GPU 这里GPU MMU的方式算是个例外,不在本篇文章讨论范围内。 我们知道DMA映射有两种方式,一种是一致性映射 dma_alloc_coherent,一种是流式映射 dma_map_single (dma...
dma_addr_t dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction direction); 1. 返回值是总线地址,可以把它传递给设备;如果执行错误,返回NULL。 当传输完毕后,使用下函数删除映射: void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,...