FPGA 上的 DMA 无法访问使用 GFP_KERNEL 标志分配的内核内存

Posted

技术标签:

【中文标题】FPGA 上的 DMA 无法访问使用 GFP_KERNEL 标志分配的内核内存【英文标题】:DMA on FPGA Cannot Access Kernel Memory Allocated with GFP_KERNEL Flag 【发布时间】:2019-03-18 01:08:45 【问题描述】:

我想先简要描述一下我正在处理的场景。

我想要完成的是从我的用户空间应用程序加载图像数据并通过 PCIe 将其传输到位于 FPGA 板内的自定义加速引擎。

我的主机的规格是:

配备 16G 内存的英特尔至强处理器。 64 位 Debian Linux,内核版本 4.18。

FPGA 是 Virtex 7 KC705 开发板。 FPGA 使用 PCIe 控制器(桥接器)在 PCIe 基础设施和 FPGA 的 AXI 接口之间进行通信。 另外,FPGA配备了DMA引擎,通过PCIe控制器从内核内存中读取数据并转发给加速器。

由于在未来的实现中我希望将多个内核分配最大为 256M,因此我已将内核配置为支持 CMA 和 DMA 连续分配器。 根据 dmesg,我可以验证我的系统在启动时保留了 CMA 区域。

关于加速过程:

    驱动程序最初通过使用带有 GFP_KERNEL 标志的 dma_alloc_coherent() 分配 4M 内核内存。此分配在 CMA 范围内。 然后,我从我的用户空间应用程序中调用带有 READ_PROT/WRITE_PROT 和 MAP_SHARED/MAP_LOCKED 标志的 mmap 来映射先前分配的 CMA 内存并在其中加载图像数据。 加载图像数据后,我转发 CMA 分配内存的 dma_addr_t 物理地址,然后启动 DMA 将数据传输到加速器。加速完成后,DMA 应该将处理后的数据写回同一个 CMA 内核分配的内存。 完成后,用户空间应用程序从 CMA 内存中读取处理后的数据并将其保存到 .bmp 文件中。当我检查“处理过的”图像时,它与原始图像相同。我想处理过的数据从未写入 CMA 内存。

在使用 GFP_KERNEL 标志时,是否有某种内存保护不允许写入 CMA 内存?

一个有趣的事实是,当我使用 dma_alloc_coherent 但使用 GFP_ATOMIC 或 GFP_DMA 分配内核内存时,处理后的数据会正确写入内核内存,但不幸的是分配的内存不属于 CMA 区域的范围。

我的实现有什么问题? 如果您需要更多信息,请告诉我!

【问题讨论】:

一目了然,您做事正确。请显示您的代码 - 如何从用户空间调用 mmap() 以及驱动程序的 mmap 处理程序中的内容。 【参考方案1】:

为了使用 mmap() 我采用了 debugfs 文件操作方法。 最初,我打开一个 debugfs 文件如下:

shared_image_data_file = open("/sys/kernel/debug/shared_image_data_mmap_value", O_RDWR);

shared_image_data_mmap_value 是我在内核驱动程序中创建的 debugfs 文件,shared_image_data_file 只是一个整数。

然后,我从用户空间调用 mmap() 如下:

    kernel_address = (unsigned int *)mmap(0, (4 * MBYTE), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, shared_image_data_file, 0);

当我在用户空间调用 mmap() 函数时,我的 debugfs 文件的 mmap 文件操作会在内核驱动程序中执行以下函数:

dma_mmap_coherent(&dev->dev, vma, shared_image_data_virtual_address, shared_image_data_physical_address, length);

shared_image_data_virtual_address 是 uint_64_t 类型的指针,而 shared_image_data_physical_address 是 dma_addr_t 类型的指针,它们是在我之前使用以下代码在内核空间中分配内存时创建的:

shared_image_data_virtual_address = dma_alloc_coherent(&dev->dev, 4 * MBYTE, &shared_image_data_physical_address, GFP_KERNEL);

我传递给 FPGA 的 DMA 的地址是 shared_image_data_physical_address

希望以上内容对你有帮助。

谢谢!

【讨论】:

以上是关于FPGA 上的 DMA 无法访问使用 GFP_KERNEL 标志分配的内核内存的主要内容,如果未能解决你的问题,请参考以下文章

配置时无法访问STM32 DMA寄存器

Lan9252-FPGA调试笔记

DMA (直接存储器访问)

DMA32映射问题

如何从 Linux 访问 Xilinx Axi DMA?

STM32 MCU 上的 DMA 到 GPIO 的可靠性如何?