linux - 如何读取 x86 上的过时值

标签 linux caching x86 dma persistent-memory

我的目标是在没有缓存一致性的情况下读取陈旧和过时的内存值。我尝试使用 prefetchnta 执行非临时加载,但未能获取过时的值。我正在考虑执行某种流式内存到内存直接内存访问,但由于继续我当前的项目所需的大量背景知识,我遇到了一些麻烦。目前我正在尝试搞乱 udmabuf但即便如此,进展也很缓慢。应该注意的是,理想情况下我想忽略所有 CPU 缓存的内容,包括当前的 CPU。

提供我的理由:我正在开发可用于证明为非 volatile 存储器编写的程序的正确性的软件。由于CPU缓存是 volatile 的,CPU的回写式缓存仍然是 volatile 的,并且需要观察它们如何写回内存的任意性质。

如果有人能给我一些如何继续的指示,我将不胜感激。我不介意深入研究 Linux 内核,因为事实上我现在正在这样做,也不介意修改它,我只是需要一些正确方向的指导。

最佳答案

我还没有尝试过这个,但我从文档中了解到,对于加载(与 NT 存储不同),没有任何东西可以绕过缓存或覆盖内存类型的强排序,如正常的 WB(回写)。甚至 NT 存储也会逐出已缓存的数据,因此它们不能破坏此核心或另一个已缓存您正在写入的行的数据的核心的一致性。

您可以从 WC(写入组合)内存区域(使用 prefetchnta 或 SSE4 movntdqa)执行弱顺序加载,但它们在物理地址级别可能仍然是一致的。

@MargaretBloom 评论了

IIRC Intel warns the developer about multiple mapping with different cache types, which may indeed be good in this case.

所以也许您实际上可以通过同一物理页面的多个虚拟映射来绕过缓存一致性。

<小时/>

我不知道是否可以使用 PCI/PCIe 设备进行非相干 DMA,但这可能是您在不通过缓存的情况下获取实际 DRAM 内容的唯一希望。

通常(总是?)现代 x86 系统上的 DMA 是缓存一致的,这对性能有好处。为了保持与没有缓存的 386 及更早版本 CPU 的向后兼容性,第一批带有缓存的 x86 CPU 具有缓存一致性 DMA,直到后来的几代才引入缓存控制指令,因为现有操作系统不使用它们。在现代系统中,内存 Controller 内置于 CPU 中。因此,在 Intel CPU 上,系统代理可以监听 L3 标签,以查看某行是否缓存在芯片上的任何位置,同时将请求发送到内存 Controller 。或者,Xeon 可以直接 DMA 进入 L3 缓存,而无需数据通过 DRAM 反弹,这对于高带宽 NIC 很有好处。

<小时/>

an INVD instruction这会使所有缓存失效而不首先进行写回,但我认为这包括共享的L3缓存,可能还包括所有其他核心的私有(private)缓存。因此,您实际上无法在 Linux 系统上使用它,因为其他内核可能正在执行任务;使用它以及使用 NVDIMMs 模拟机器上的电源故障可能会损坏内核数据结构。对于您感兴趣的过程。

也许如果您以某种方式使所有其他 CPU 核心脱机,并禁用仍在运行的一个核心上的中断

然后重新启用中断。如果在 wbinvdinvd 之间处理任何中断,中断处理程序最终可能会缓存一些内核数据,而另一些则存储在内存中,或者导致设备驱动程序与硬件不同步。 .

更新:有人确实尝试过这样做:

关于linux - 如何读取 x86 上的过时值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53142617/

相关文章:

assembly - 汇编程序 xbegin 引发非法指令

linux - RStudio 服务器仅因 1 个用户挂起

java - 半透明 JPanel 不清除背景/在 Linux 中显示背景伪像

linux - 操作系统在丢弃传入网络流量之前会将其存储多长时间?

java - 在不使用太多内存的情况下加快搜索缓存

caching - ColdFusion 客户端变量间歇性地显示过时的值

x86 - 如何用SSE3实现符号功能?

android - 是否有任何基于 Java 的 C/C++ 编译器?

asp.net-mvc-3 - 使用 Reponse.Cookies 时 OutputCache 不工作

c++ - 为什么从多个线程使用相同的缓存行不会导致严重的速度下降?