我有一个带有用户空间驱动程序的 PCIe 设备。我通过 BAR 向设备写入命令,这些命令对延迟敏感并且数据量很小(~64 字节),因此我不想使用 DMA。
如果我使用以下命令重新映射内核中 BAR 的物理地址ioremap_wc
然后将64字节写入BAR内核内部,我可以看到 64 字节被写入 PCIe 上的单个 TLP。如果我允许我的用户空间程序mmap
该地区与MAP_SHARED
标志,然后写入 64 字节 我在 PCIe 总线上看到多个 TPL,而不是单个事务。
根据内核PAT 文档 https://www.kernel.org/doc/Documentation/x86/pat.txt我应该能够将写入组合的页面导出到用户空间:
想要将某些页面导出到用户空间的驱动程序可以使用 mmap 来实现
接口和组合
1) pgprot_noncached()
2) io_remap_pfn_range()
or remap_pfn_range()
or vm_insert_pfn()
借助 PAT 支持,新的 APIpgprot_writecombine
正在添加中。所以,
驱动程序可以继续使用上述顺序,或者pgprot_noncached()
or pgprot_writecombine()
在步骤 1 中,然后是
第2步。
根据此文档,我的 mmap 处理程序中的相关内核代码如下所示:
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
return io_remap_pfn_range(vma,
vma->vm_start,
info->mem[vma->vm_pgoff].addr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
我的 PCIe 设备显示在 lspci 中,其中 BAR 按预期标记为可预取:
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 11
Region 0: Memory at d8000000 (64-bit, prefetchable) [size=32M]
Region 2: Memory at d4000000 (64-bit, prefetchable) [size=64M]
当我打电话时mmap
从用户空间我看到一条日志消息(已设置 debugpat 内核启动参数):
Reserve_memtype 添加了 [mem 0xd4000000-0xd7ffffff]、track write-combining、req write-combining、ret write-combining
我还可以看到/sys/kernel/debug/x86/pat_memtype_list
PAT 条目看起来正确并且没有重叠区域:
write-combining @ 0xd4000000-0xd8000000
uncached-minus @ 0xd8000000-0xda000000
我还检查了没有与 PAT 配置冲突的 MTRR 条目。据我所知,所有内容都已正确设置,以便在用户空间中发生写入组合,但是使用 PCIe 分析器观察 PCIe 总线上的事务,用户空间访问模式与从内核执行的相同写入完全不同后ioremap_wc
call.
为什么写组合不能按用户空间的预期工作?
我可以做什么来进一步调试?
我目前在单插槽 6 核 i7-3930K 上运行。