8

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

这类似于如何防止 MMAP 缓存值?

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

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

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

我也试过ioremap_cache()iowrite32()里面的驱动代码。结果是一样的。

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

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

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

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

4

1 回答 1

10

我不知道有任何 x86 硬件支持 MMIO 地址的 WriteBack (WB) 内存类型,您几乎肯定会看到这种不兼容的结果。我已经在我的博客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 属性。

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

于 2013-06-06T17:52:43.333 回答