2012-06-28 83 views
6

我想写一个PCIe BAR自定义mmap()函数的驱动程序,其目的是使这个BAR可以在处理器缓存中缓存。我知道这不是实现最高带宽的最佳方式,并且写入顺序是不可预测的(在这种情况下也不是这样)。mmap如何缓存PCIe 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,但代码不同。

回答

6

我不知道任何支持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的读取一次。当您在“只写”区域中写入该行的别名时,您需要在“只读”区域的缓存行上手动维护一致性。由于IO设备无法为MMIO地址生成缓存失效事务,所以您还需要手动维护FPGA内存中值的更改。

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

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