我有一个基于7000赛灵思ZYNQ板与在具有DMA能力的FPGA架构的外围(上赛灵思/ ARM的SoC(ZYNQ 7000)DMA缓冲区AXI总线)。我们开发了一个电路并在ARM内核上运行Linux。硬件填充后,我们遇到性能问题,从用户空间访问DMA缓冲区。需要帮助映射预先保留** **缓存上
摘要:
在启动时我们已预先保留DRAM的部分用作大DMA缓冲区。我们显然使用错误的API来映射此缓冲区,因为它看起来没有缓存,并且访问速度很糟糕。
使用它,甚至作为一个反弹缓冲是慢难以维持,由于可怕的性能。 IIUC,ARM高速缓存不连贯的DMA,所以我会很感激关于如何做到以下一些见解:
- 地图DRAM的一个区域到内核的虚拟地址空间,但确保它是缓存。
- 确保将它映射到用户空间并不会产生不良影响,即使这需要我们通过我们自己的驱动程序提供mmap调用。
- 在执行DMA之前,从缓存层次结构中显式地使物理内存区域无效,以确保一致性。
更多信息:
我一直在试图询问之前仔细研究这个。不幸的是,这是一个ARM SoC/FPGA,这方面的信息很少,所以我必须直接询问专家。
因为这是一个系统级芯片,很多东西是硬编码的u-boot。例如,在将控制交给内核之前,内核和ramdisk被加载到DRAM中的特定位置。我们利用这个优势为DMA缓冲区预留了64MB的DRAM部分(它的确需要那么大,这就是我们预先保留它的原因)。没有任何担心内存类型冲突或内核在内存中跺脚,因为引导参数告诉内核哪个区域的DRAM可以控制。
最初,我们尝试使用ioremap将此物理地址范围映射到内核空间,但似乎标记区域不可缓存,并且访问速度非常糟糕,即使我们试图使用memcpy使其成为反弹缓冲区。我们使用/ dev/mem将其映射到用户空间中,并将memcpy的时间定义为70MB/sec左右。
基于对这个主题的大量搜索,似乎有一半的人希望像这样使用ioremap(这可能是我们从中得到的想法),ioremap不应该用于这个目的以及应该使用DMA相关的API来代替。不幸的是,似乎DMA缓冲区分配是完全动态的,我还没有想出如何告诉它,“这是一个已经分配的物理地址 - 使用它。”我看着
一号文件是这一个,但它的方式太x86和PC为中心的: https://www.kernel.org/doc/Documentation/DMA-API-HOWTO.txt
而且这个问题也是在我的搜索上面来了,但没有真正的答案: get the physical address of a buffer under Linux
望着标准要求,dma_set_mask_and_coherent和家人不会采取预先定义的地址,并希望为PCI设备结构。我没有这样的结构,因为这是没有PCI的ARM SoC。我可以手动填充这样的结构,但是这对我来说就像滥用API一样,而不是按照预期使用它。
BTW:这是一个环形缓冲区,我们DMA数据块到不同的偏移,但我们对齐缓存行边界,所以没有虚假分担风险。
非常感谢您为您提供的任何帮助!
更新:看来,如果以正常方式进行操作,ARM上不存在可缓存的DMA缓冲区。也许如果我不进行ioremap调用,该区域不会被标记为不可缓存,但是我必须弄清楚如何在ARM上进行缓存管理,这是我无法弄清楚的。其中一个问题是用户空间中的memcpy显得非常糟糕。是否有一个memcpy实现为我可以使用的未缓存内存进行了优化?也许我可以写一个。我必须弄清楚这个处理器是否有Neon。
您正在使用哪个版本的Linux内核?您是否尝试过使用**连续内存分配器**?... – TheCodeArtist
@ TheCodeArtist“Linux(none)3.17.0-xilinx-dirty#13 SMP PREEMPT Mon Aug 3 12:10:57 MDT 2015 armv7l GNU/Linux” 另外,我没有看过CMA。如果我能正确映射这个缓冲区,它不应该要求CMA,除非完全不可能从预保留的物理地址指定DMA缓冲区。 –
获取Linux下的缓冲区的物理地址(这是来自用户空间)http://stackoverflow.com/a/28987409/1163019。对于DMA/uncached东西afaik,老实说我不记得所有的细节,并且我没有成功完成我的不同任务,但是我能从代码中看到的是我正在尝试“dma_alloc_coherent” - >“update vma-> vm_page_prot作为写通过“ - > dma_mmap_from_coherent - > remap_pfn_range。也可能是这个演示文稿的帮助? http://events.linuxfoundation.org/sites/events/files/slides/20141015-dma.pdf – auselen