通过 Linux user-space 中的 /dev/mem 与 PCIe 设备的双向通信?

Two-way communication to PCIe device via /dev/mem in Linux user-space?

很确定我已经知道这个问题的答案,因为已经有关于 SO 的相关问题(here, here, and here,, and this 很有用),但是我想在深入内核之前绝对确定-space driver land(之前没去过)

我有一个 PCIe 设备,我需要通过 linux 用户 space 中的应用与之通信(反之亦然)。通过打开 /dev/mem,然后 mmap'ing,我已经能够编写一个基于 pciutils 的用户 space 驱动程序,它允许我 mmap BAR 并成功将数据写入设备。现在,我们需要从 PCIe 设备到 linux 用户应用程序的另一个方向进行通信。为了让它工作,我们相信我们将需要一大块 (~100MB) 的物理连续内存,永远不会 paged/swapped。分配后,该地址将需要传递给 PCIe 设备,以便它知道将其数据写入何处(因此我看不出这怎么可能是虚拟的、可交换的内存)。如果没有内核 space 驱动程序,有没有办法做到这一点?这里提出了一个想法,也许我们可以打开 /dev/mem 然后给它一个 ioctl 命令来分配我们需要的东西?如果可能的话,我还没有在网上找到任何例子,需要更深入地研究它。

假设我们需要一个内核 space 驱动程序,最好在启动期间分配我们的大卡盘,然后使用 ioremap 获取内核虚拟地址,然后 mmap 从用户-space,对吗?根据我在 kmalloc 上阅读的内容,使用该调用我们不会获得接近 100MB 的空间,并且 vmalloc 也不好,因为那是虚拟内存。为了在启动时分配,驱动程序应该静态链接到内核中,对吗?这基本上是一个嵌入式应用程序,所以可移植性对我来说不是一个大问题。一个模块而不是静态链接的驱动程序可能可以工作,但我担心内存碎片可能会阻止找到物理上连续的区域,所以我想在开机后尽快分配它。有任何反馈吗?

EDIT1:我的 CPU 是 ARM7 架构。

Hugepages-1G

目前x86_64-processors不仅支持4k和2M,还支持1G-pages(/proc/cpuinfo中的flag pdpe1gb表示支持)。

这些 1G 页面必须在内核启动时保留,因此必须指定 boot-parameters hugepagesz=1GB hugepages=1

然后,必须挂载 hugetlbfs:

mkdir /hugetlb-1G
mount -t hugetlbfs -o pagesize=1G none /hugetlb-1G

然后打开一些文件并映射它:

fd = open("/hugetlb-1G/page-1", O_CREAT | O_RDWR, 0755);
addr = mmap(NULL, SIZE_1G, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

您现在可以在 addr 访问 1G 的物理连续内存。为确保它不会被换出,您可以使用 mlock(但这对于大页面来说甚至根本没有必要)。

即使你的进程崩溃了,巨大的页面也会像上面一样被保留用于映射它,所以pci-e设备不会将流氓写入系统或进程内存。

您可以通过阅读/proc/pid/pagemap找到物理地址。

实际上,Ctx 关于 memmap 的评论让我走上了正确的道路。为了保留内存,我将引导加载程序参数设置为 memmap=[size]$[location],我发现它是 here。不同的符号表示不同的事物,而且它们并不完全直观。只是另一个轻微的更正,标志是 CONFIG_STRICT_DEVMEM,我的内核没有用它编译。

还有一些未解之谜。例如,memmap 参数中的 [location] 似乎没有意义。无论我为该位置设置什么,linux 将所有未与 [size] 保留的内容放在一个连续的块中,而我保留的 space 在最后。唯一的迹象是查看 /proc/iomem。我保留的 space 数量与 linux 内存末尾 space 和系统内存末尾 space 之间的间隙相匹配。我在任何地方都找不到 linux 说 "I see your reserved chunk and I won't touch it" 的迹象,除了它不是 linux 在 /proc/iomem 中使用的。但是 FPGA 已经写入 space 好几天了,对 linux 没有明显的不良影响,所以我想我们都很好!我可以直接映射到那个位置并读取数据(这让我感到惊讶,因为 linux 并不表示它存在,但很高兴它确实存在)。谢谢您的帮助! Ian 如果我转到内核驱动程序 space.

,我会回复你的评论