我的 PCI 设备驱动程序如何将 PCI 内存重新映射到用户空间?

How can my PCI device driver remap PCI memory to userspace?

我正在尝试为 QEMU 上的虚拟 PCI 设备实现 PCI 设备驱动程序。设备将 BAR 区域定义为 RAM,驱动程序可以对该区域执行 ioremap() 并毫无问题地访问它。下一步是将该区域(或其中的一部分)分配给用户应用程序。 为此,我还实现了一个 .mmap 函数作为我的驱动程序文件操作的一部分。这个mmap只是简单地使用了remap_pfn_range,但是它也传递了之前ioremap()返回的内存指针的pfn。

然而,在 运行 用户 space 应用程序上,mmap 是成功的,但是当应用程序尝试访问内存时,它被杀死并且我得到以下 dmesg 错误。

” a.out:地址 7f66248b8000

处的损坏页面 table

..某些页面 table 信息..

坏页table: 000f [#2] SMP NOPTI

..和核心转储.. “ 有谁知道我做错了什么?我错过了一步吗?或者它可能是 QEMU 特有的错误? 我的 QEMU 配置是 运行 x86_softmmu 内核是 4.14

我已经解决了这个问题并设法通过驱动程序将 PCI 内存映射到用户 space。正如 @IanAbbott 所暗示的那样,我已经更改了我在自定义 ->mmap().

中使用的 remap_pfn_range() 函数的 pfn 输入

原文是:

io_remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot));

其中 pfn 是缓冲区指针 return 来自 ioremap() 的结果。我将 pfn 更改为:

pfn = pci_resource_start(pdev, BAR) >> PAGE_SHIFT;

那基本就是指向BAR实际指向的起始地址了。我的工作 remap_pfn_range() 功能现在是:

io_remap_pfn_range(vma, vma->vm_start, pci_resource_start(pdev, BAR) >> PAGE_SHIFT, vma->vm_end - vma->vm_start,vma->vm_page_prot);

我通过对我的驱动程序中的缓冲区指针进行一些虚拟写入,然后在我的用户 space 应用程序中读取并进行一些写入来确认它可以工作。