linux - 如何在 x86 上读取过时的值
问题描述
我的目标是在没有缓存一致性的情况下读取过时和过时的内存值。我试图用来prefetchnta
执行非临时加载,但它无法获取过时的值。我正在考虑执行某种流式内存到内存直接内存访问,但由于继续我当前的项目所需的大量背景知识,我遇到了一些麻烦。目前我正试图弄乱udmabuf,但即使这样也进展缓慢。应该注意的是,理想情况下我想忽略所有CPU 缓存的内容,包括当前的 CPU。
提供我的理由:我正在开发可用于证明为非易失性存储器编写的程序的正确性的软件。由于 CPU 缓存是易失的,CPU 的回写缓存仍然是易失的,需要观察它们如何写回内存的任意性质。
如果有人能给我一些关于如何进行的指示,我将不胜感激。我不介意深入研究 Linux 内核,事实上我现在正在这样做,也不介意修改它,我只需要一些正确方向的指导。
解决方案
我还没有玩过这个,但我从文档中得到的理解是,对于加载(与 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
然后重新启用中断。如果wbinvd
在invd
.
更新:有人确实尝试过这个:
- 如何在禁用 SMP 支持的情况下运行“invd”指令?
- 如何将结构显式加载到 L1d 缓存中?-
invd
工作得非常好,它printk
在错误设计的尝试中记录了一些关于它的内容。
推荐阅读
- sharepoint - SharePoint 中的可配置静态选项卡
- simulation - 到达特定补丁后如何让乌龟执行特定任务?
- loops - Ansible with_items loop over groups, defined as a list
- python - How can I insert image to Google spreadsheets using Python?
- javascript - Javascript减去双数
- php - 如果使用优惠券,则删除一个支付网关
- pdf - 如何将 OCR 文本从一个 PDF 传输到另一个 PDF?
- javascript - 获取请求 API 的跨域请求被阻止错误
- javascript - 在不重新加载的情况下更改 HTML 页面的 lang 属性
- vba - 运行时错误“13”类型不匹配 MS Access VBA Dlookup