如何为可缓存的PCIe BAR执行mmap

时间:2012-06-28 22:52:23

标签: caching mmap pci pci-e

我正在尝试为PCIe BAR编写一个带有自定义mmap()函数的驱动程序,目标是使这个BAR可以在处理器缓存中缓存。我知道这不是实现最高带宽的最佳方式,并且写入顺序是不可预测的(在这种情况下也不是问题)。

这类似于How would one prevent MMAP from caching values?

中描述的内容

处理器是Sandy Bridge i7,PCIe设备是Altera Stratix IV dev。板。

首先,我试图在CentOS 5(2.6.18)上进行。我更改了MTRR设置以确保BAR不在无法缓存的MTRR中,并使用io_remap_pfn_range()并清除了_PAGE_PCD_PAGE_PWT位。读取按预期工作:读取返回正确的值,第二次读取到同一地址不一定导致读取到PCIe(在FPGA中检查读取计数器)。但是,写入导致系统冻结,然后重新启动,而日志或屏幕上没有任何消息。

其次,我试图在拥有PAT支持的CentOS 6(2.6.32)上进行。结果是一样的:读取工作正常,写入会导致系统冻结并重新启动。有趣的是,非时间/写入组合完整高速缓存行写入(AVX / SSE)按预期工作,即它们总是进入FPGA并且FPGA观察到完整的高速缓存行写入,读取之后返回正确的值。但是,简单的64位写入仍会导致系统冻结/重启。

我还尝试在驱动程序代码中ioremap_cache()然后iowrite32()。结果是一样的。

我认为这是一个硬件问题,但如果有人能分享有关正在发生的事情的任何想法,我将不胜感激。

编辑:我能够在CentOS 6上捕获MCE消息:机器检查异常:5银行5:be2000000003110a。

我也尝试在2插槽Sandy Bridge(Romley)上使用相同的代码:读取和非临时写入行为是相同的,简单写入不会导致MCE /崩溃,但对系统状态没有影响,即内存中的值不会改变。

另外,我在旧的2插槽Nehalem系统上尝试了相同的代码:简单的写入也会导致MCE,尽管代码不同。

1 个答案:

答案 0 :(得分:7)

我不知道任何支持MMIO地址的WriteBack(WB)内存类型的x86硬件,你几乎肯定会看到这种不兼容的结果。 我已在我的博客http://blogs.utexas.edu/jdm4372/2013/05/29/http://blogs.utexas.edu/jdm4372/2013/05/30/

上发布了有关此主题的讨论

在这些贴子中,我讨论了一种适用于某些处理器的方法 - 将MMIO范围映射两次 - 一次用于使用写入组合(WC)存储器类型从处理器到FPGA的存储操作,一次用于读取使用写保护(WP)或写通(WT)类型从处理器到FPGA。当您在“只写”区域中写入该行的别名时,您需要通过在“只读”区域中的高速缓存行上使用CLFLUSH来手动保持一致性。您还需要手动维护FPGA内存中值的变化,因为IO设备无法为MMIO地址生成缓存失效事务。

几年前,当我在AMD时,我的团队做到了这一点,现在我正试图弄清楚如何使用更新的Linux内核和英特尔处理器。 Linux不直接支持WP或WT内存类型及其预定义的映射函数,因此需要进行一些黑客攻击....对于某个区域覆盖MTRR相当容易,但是我找到正确的位置时遇到了更多麻烦( s)在remap_pfn_range()函数的后代中,我需要更改以便在范围的PAT条目中设置WP或WT属性。

这种方法可能更适合FPGA而不是其他(预定义)类型的IO设备,因为FPGA的可编程性允许灵活地定义PCI BAR以在这种双映射模式下操作并与之配合处理器端驱动程序维护缓存一致性。