我正在尝试编写一个自定义驱动程序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()
with _PAGE_PCD
and _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,尽管代码不同。
我不知道有任何 x86 硬件支持 MMIO 地址的 WriteBack (WB) 内存类型,并且您几乎肯定会看到这种不兼容的结果。
我已在我的博客上发表了对此主题的讨论:http://blogs.utexas.edu/jdm4372/2013/05/29/ and http://blogs.utexas.edu/jdm4372/2013/05/30/
在这些帖子中,我讨论了一种适用于某些处理器的方法 - 将 MMIO 范围映射两次 - 一次用于使用写入组合 (WC) 内存类型从处理器到 FPGA 的存储操作,一次用于从处理器读取使用写保护 (WP) 或直写 (WT) 类型写入 FPGA。当您写入“只写”区域中该行的别名时,您需要通过在“只读”区域中的缓存行上使用 CLFLUSH 来手动保持一致性。您还需要手动维护 FPGA 内存中值变化的一致性,因为 IO 设备无法为 MMIO 地址生成缓存失效事务。
几年前,当我在 AMD 工作时,我的团队就这样做了,现在正在尝试找出如何使用较新的 Linux 内核和 Intel 处理器来做到这一点。 Linux 不直接支持 WP 或 WT 内存类型及其预定义的映射函数,因此需要一些黑客攻击......覆盖某个区域的 MTRR 相当容易,但我在找到正确的位置时遇到了更多麻烦( s) 在 remap_pfn_range() 函数的后代中,我需要更改它,以便获取该范围的 PAT 条目中设置的 WP 或 WT 属性。
这种方法可能比其他(预定义的)类型的 IO 设备更适合 FPGA,因为 FPGA 的可编程性允许灵活地定义 PCI BAR 以在这种双映射模式下运行并与处理器配合。维持缓存一致性的侧驱动程序。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)