如何在x86上读取过时的值

时间:2018-11-04 15:58:14

标签: linux caching x86 dma persistent-memory

我的目标是在没有高速缓存一致性的情况下读取陈旧和过时的内存值。我尝试使用(defparameter *test-array* #2A((131 673 234 103 18) (201 96 342 965 150) (630 803 746 422 111) (537 699 497 121 956) (805 732 524 37 331))) (defun find-paths (array &aux (height (array-dimension array 0)) (width (array-dimension array 1))) "Returns the possible paths across a given 2d array from the left column to the right column." (loop :for i :from 0 :below height ;; We have three ways per starting point up, left and down. ;; In the first and last row there are two ways, only. :append (loop :for (j l) :in '((1 0) (0 1) (-1 0)) :when (and (>= (+ j i) 0) (< (+ j i) height)) :collect (list (aref array i 0) (aref array (+ i j) l))) :into paths :finally (return paths))) 来执行非临时加载,但是无法获取过时的值。我正在考虑执行某种“流式传输内存到内存”的直接内存访问,但是由于进行当前项目需要大量的背景知识,因此遇到了一些麻烦。目前,我正在尝试弄乱udmabuf,但即使这样进展也很缓慢。应该注意的是,理想情况下,我想忽略所有 CPU缓存的内容,包括当前的CPU。

提供有关以下原因的理由:我正在开发可用于证明为非易失性存储器编写的程序正确性的软件。由于CPU高速缓存是易失性的,因此CPU的回写高速缓存仍将是易失性的,并且需要观察如何将它们写回到内存中。

如果有人可以给我一些如何进行的指示,我将深表感谢。我不介意研究Linux内核,因为事实上我现在正在这样做,也不介意对其进行修改,我只需要在正确方向上提供一些指导即可。

1 个答案:

答案 0 :(得分:3)

我还没有解决这个问题,但是我从文档中了解到,对于负载(与NT存储区不同),没有任何东西可以绕过缓存或像普通的WB(回写)那样覆盖内存类型的强顺序。甚至NT都将已缓存的数据逐出,因此它们不会破坏此内核或为您正在编写的行缓存数据的另一个内核的一致性。

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

@MargaretBloom评论了

  

IIRC英特尔警告开发人员有关具有不同缓存类型的多重映射,在这种情况下,这确实不错。

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


我不知道是否仍然可以使用PCI / PCIe设备进行非一致性DMA,但这可能是您获得真正的DRAM内容而不通过缓存的唯一希望。 (现代x86系统上的大多数DMA是高速缓存一致性的,这对性能和性能都有好处,因为内存控制器内置在CPU中。因此在Intel CPU上,系统代理可以监听L3标签以查看是否存在行会在将请求发送到内存控制器的同时并行缓存在芯片上的任何位置。)


an INVD instruction会使所有缓存无效,而无需先执行回写操作,但是我认为其中包括共享的L3缓存,可能还包括所有其他内核的专用缓存< / strong>。因此,您几乎不能在其他核心可能正在做事的Linux系统上使用它。您可能会通过使用内核数据结构来破坏内核数据结构,并使用感兴趣的过程在NVDIMMs的计算机上模拟电源故障。

也许您是否以某种方式使所有其他CPU内核脱机,并在仍处于运行状态的一个内核上禁用了中断

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