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

sol*_*ols 7 caching mmap pci pci-e

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

这类似于如何阻止MMAP缓存值中描述的内容?

处理器是Sandy Bridge i7,PCIe器件是Altera Stratix IV dev.板.

首先,我尝试在CentOS 5(2.6.18)上进行.我改变了MTRR设置,以确保酒吧是不是不可缓存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 Bank 5:be2000000003110a.

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

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

Joh*_*pin 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来手动保持一致性.由于IO设备无法为MMIO地址生成高速缓存失效事务,因此还需要手动保持FPGA内存中值的变化.

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

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