23

我对缓存同步操作有一些疑问。

Invalidate:在 cpu 尝试读取设备更新的部分内存之前,需要使相应的内存失效。

Flush:在设备读取 CPU 更新的部分内存之前,CPU 必须将缓存中的内容刷新(写回也正确?)到内存,以便设备从内存中读取更新后的内容。

如果不执行刷新,它可能会读取内存中存在的垃圾数据,因为内存仍未使用写入缓存的内容进行更新。

请确认我的上述理解是否正确?

您什么时候想结合刷新和无效?我听说在玩设备控制描述符时,我们需要通过组合刷新和无效来进行同步。为什么这样?

我们是否需要遵循冲洗后无效的顺序?

是否存在无效后刷新有用的情况?

4

2 回答 2

37

Flush 确实将缓存的内容写回主存,而 invalidate 确实将缓存行标记为无效,以便将来的读取进入主存。

如果设备正在更新内存块,我认为你会结合刷新和无效:刷新将确保设备具有最新的内容,然后无效将确保当设备完成时 CPU 将读取新内容从记忆里。

于 2010-02-27T11:43:55.047 回答
5

请确认我的上述理解是否正确?

一般来说,你是完全正确的,但有些石头可能会导致绊倒。您没有指定硬件平台。如果我们不是在谈论带有 SRAM 的小型嵌入式控制器,请考虑以下内容。带有 MMU 的处理器支持普通 DDR 内存和驱动程序(硬件相关)内存的不同内存属性。最后一个是不可缓存的,所以不用担心刷新/失效。


您什么时候想结合刷新和无效?我听说在玩设备控制描述符时,我们需要通过组合刷新和无效来进行同步。为什么这样?

由于标签中提到了 DMA,因此有几种情况(假设 HW 缓冲区是不可缓存的设备内存):

  1. DMA 将数据从 DDR 存储器传输到 HW 缓冲区。
  2. DMA 将数据从 HW 缓冲区传输到 DDR(HW 接收到数据并希望将其提供给 CPU)
  3. DMA 从 DDR 传输到 DDR 的另一个区域。

  1. DDR 缓冲区应在 DMA 之前刷新。驱动程序缓冲区不可缓存,因此无需失效。
  2. DDR 缓冲区应在DMA 传输之前或之后失效NOTE(详见下文),以防止 CPU 使用缓存中的“旧”数据。刷新硬件缓冲区是多余的。
  3. “源”缓冲区应被刷新,“目标”缓冲区应无效。因此,有效数据在传输之前存储在内存中供 DMA 使用,并且 CPU 在 DMA 完成工作后不会从缓存中获取“污垢”。


NOTE: 很明显,'source' 应该在 DMAing 之前被刷新。仍然存在何时失效的问题。从技术上讲,它是在 CPU 尝试访问“目标”数据之前,并且可能在 DMA 之前或之后(我们应该确保 DMA 已完成工作)。DMAing后IRL 失效可能会导致问题。参考 虚拟地址的Flush/Invalidate range;ARMv8;缓存;

如您所见,此特定平台的无效应该在 DMA之前完成。另外,我还发现了 ARMv7 设备的 BSP 代码,建议在DMA 传输之前使目标缓冲区无效。
但这还不是全部。您可能希望在再次进行 DMA 传输后使目标缓冲区无效(没错,第二次)。如果有问题的芯片有预取,它可以在 DMA 工作时将数据取回缓存。所以顺序可能是:在第一次使预取无效后,再次将数据放入缓存中-> DMA 覆盖内存中的数据-> 缓存具有与内存不同的数据,并且缓存被标记为具有有效数据。第二次无效将确保数据将再次被检索到缓存中,因此缓存和内存完成同步:)


我们是否需要遵循冲洗后无效的顺序?

假设源缓冲区和目标缓冲区不相交,则不存在依赖关系。你可以flush-invalidateinvalidate-flush


是否存在无效后刷新有用的情况?

不要这么想。

于 2017-02-20T01:45:12.143 回答