首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >需要帮助在Xilinx/ARM SoC (Zynq 7000)上映射预保留的**可缓存的** DMA缓冲区

需要帮助在Xilinx/ARM SoC (Zynq 7000)上映射预保留的**可缓存的** DMA缓冲区
EN

Stack Overflow用户
提问于 2016-01-19 18:27:25
回答 4查看 2.4K关注 0票数 2

我有一个基于Xilinx 7000的板,在FPGA结构中有一个外设,它具有DMA功能(在AXI总线上)。我们已经开发了一个电路,并在ARM内核上运行Linux。在DMA缓冲区被硬件填充后,从用户空间访问它的性能出现问题。

摘要:

我们在启动时预先预留了一段DRAM,作为一个大型DMA缓冲区使用.显然,我们使用了错误的API来映射这个缓冲区,因为它似乎是未被缓存的,而且访问速度很差。

使用它甚至作为一个弹跳缓冲器是无法持久的慢,因为可怕的表现。IIUC,ARM缓存不具有DMA一致性,因此我非常感谢您对如何做以下工作的一些见解:

  1. 将DRAM的一个区域映射到内核虚拟地址空间,但确保它是可缓存的
  2. 确保将它映射到用户空间不会产生不良影响,即使这需要我们自己的驱动程序提供mmap调用。
  3. 在进行DMA之前,显式地使缓存层次结构中的物理内存区域失效,以确保一致性。

更多信息:

在问之前我一直在仔细研究这个问题。不幸的是,这是一个ARM SoC/FPGA,这方面的信息非常少,所以我必须直接询问专家。

因为这是一个SoC,所以很多东西都是硬编码的。例如,在将控制权交给内核之前,内核和ramdisk被加载到DRAM中的特定位置。我们利用这一点为DMA缓冲区预留了一个64 be的DRAM部分(它确实需要那么大,这就是我们预先保留它的原因)。对于冲突的内存类型或内核对此内存的践踏没有任何担心,因为引导参数告诉内核它控制了DRAM的哪个区域。

最初,我们尝试使用ioremap将这个物理地址范围映射到内核空间,但这似乎表明该区域是不可缓存的,而且访问速度非常糟糕,即使我们试图使用memcpy使其成为一个弹跳缓冲区。我们使用/dev/mem将其映射到用户空间,我将memcpy的时间设置为大约70 mem/秒。

基于对这个主题的大量搜索,似乎有一半的人想要像这样使用ioremap (这可能是我们的想法),但是ioremap不应该用于这个目的,而且应该使用与DMA相关的API。不幸的是,DMA缓冲区分配似乎是完全动态的,我还没有弄清楚如何告诉它,“这是一个已经分配的物理地址--使用它。”

我看过的一个文档是这个,但它也是以x86和PC为中心的:https://www.kernel.org/doc/Documentation/DMA-API-HOWTO.txt

这个问题也出现在我搜索的顶部,但是没有真正的答案:获取Linux下缓冲区的物理地址。

从标准呼叫来看,dma_set_mask_and_coherent和家庭不会采用预先定义的地址,而是希望为PCI提供一个设备结构。我没有这样的结构,因为这是一个没有PCI的ARM SoC。我可以手动填充这样的结构,但这对我来说就像是滥用API,而不是按预期使用它。

顺便说一句:这是一个环形缓冲区,在这里,我们将DMA数据块分成不同的偏移量,但是我们对齐缓存行边界,因此不存在错误共享的风险。

感谢你能提供的任何帮助!

UPDATE: --如果您按照正常的方式这样做的话,手臂上似乎没有可缓存的DMA缓冲区。也许如果我不进行ioremap调用,这个区域就不会被标记为不可缓存,但是我必须弄清楚如何在ARM上进行缓存管理,而这一点我是找不出的。其中一个问题是用户空间中的memcpy看起来非常糟糕。是否有一个对我可以使用的非缓存内存进行优化的memcpy实现?也许我可以写一个。我得弄清楚这个处理器是否有霓虹灯。

EN

回答 4

Stack Overflow用户

发布于 2016-01-26 04:11:27

您是否尝试过用mmap()方法实现自己的char设备,将缓冲区重新映射为可缓存(通过remap_pfn_range())?

票数 1
EN

Stack Overflow用户

发布于 2016-02-02 15:14:56

我相信,如果希望缓存映射,就需要一个实现mmap()的驱动程序。

我们为此使用了两个设备驱动程序: portalmem和zynqportal。在连接项目,中,我们将用户空间软件与FPGA逻辑之间的连接称为“门户”。这些驱动程序需要dma-buf,自从Linux内核版本3.8.x以来,dma-buf对我们来说一直是稳定的。

门窗驱动程序提供一个ioctl来分配引用计数的内存块,并返回与该内存关联的文件描述符。这个驱动程序实现了dma-buf共享。它还实现了mmap(),以便用户空间应用程序可以访问内存。

在分配时,应用程序可以选择缓存的或非缓存的内存映射。在x86上,映射总是缓存的。我们的mmap()的实现目前从portalmem驱动程序第173行开始。如果映射是未缓存的,则使用pgprot_writecombine()修改vma->vm_page_prot,启用写入缓冲,但禁用缓存。

portalmem驱动程序还提供了一个ioctl来使数据缓存行失效,并且可以选择地回写数据缓存行。

portalmem驱动程序不了解FPGA。为此,我们使用zynqportal驱动程序,它提供了一个ioctl,用于将转换表传输到FPGA,这样我们就可以在FPGA上使用逻辑上连续的地址,并将它们转换到实际的DMA地址。portalmem使用的分配方案旨在生成紧凑的转换表。

我们对PCI附带的FPGA使用相同的带有pcieportal的portalmem驱动程序,对用户软件没有任何更改。

票数 0
EN

Stack Overflow用户

发布于 2017-07-20 16:04:24

Zynq有霓虹灯指令,使用neon指令,使用对齐缓存边界(32字节)实现memcpy的组装代码将达到300 MB/s或更高的速率。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34884313

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档