首页 > 解决方案 > 如何在 x86 上读取过时的值

问题描述

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

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

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

标签: linuxcachingx86dmapersistent-memory

解决方案


我还没有玩过这个,但我从文档中得到的理解是,对于加载(与 NT 存储不同),没有什么可以绕过缓存或覆盖像普通 WB(回写)这样的内存类型的强排序。甚至 NT 也存储了已经缓存的数据,因此它们不能破坏这个或另一个为你正在编写的行缓存数据的内核的一致性。

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

@MargaretBloom 评论

IIRC Intel 警告开发人员关于不同缓存类型的多个映射,在这种情况下这可能确实很好。

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


我不知道是否仍然可以使用 PCI / PCIe 设备进行非连贯 DMA,但这可能是您在不通过缓存的情况下获取实际 DRAM 内容的唯一希望。(现代 x86 系统上的大多数(?)DMA 是缓存一致的,这对性能有好处,并且可能因为内存控制器内置在 CPU 中。因此在 Intel CPU 上,系统代理可以窥探 L3 标签以查看是否存在行缓存在芯片上的任何位置,与将请求发送到内存控制器并行。)


一条INVD指令会在不先进行回写的情况下使所有缓存无效,但我认为这包括共享的 L3 缓存,可能还有所有其他核心的私有缓存。因此,您实际上无法在其他内核可能正在执行操作的 Linux 系统上使用它;您可能会通过使用它来破坏内核数据结构,以及在具有NVDIMM的机器上为您感兴趣的进程模拟电源故障。

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

  • 您可以wbinvd(回写+无效)刷新所有缓存
  • 然后运行一些被测代码
  • 然后invd看看是什么使它成为DRAM

然后重新启用中断。如果wbinvdinvd.

更新:有人确实尝试过这个:


推荐阅读