缓存 - 刷新和无效操作
我有一些关于缓存同步操作的问题。
无效:在CPU尝试读取设备更新的部分内存之前,需要使相应的内存无效。
Flush:设备读取CPU更新的一部分内存之前,CPU必须将cache中的内容flush(回写也正确?)到内存中,以便设备从内存中读取更新后的内容。
如果未执行刷新,则可能会读取内存中存在的垃圾数据,因为内存尚未用写入缓存的内容进行更新。
请确认我的上述理解是否正确?
你什么时候想结合使用flush和invalidate?我听说在使用设备控制描述符时,我们需要通过组合刷新和无效来进行同步。为什么会这样呢?
我们是否需要遵循先刷新后无效的顺序?
是否存在先无效后刷新有用的场景?
I have some questions on cache synchronization operations.
Invalidate: Before cpu tries to read a portion of memory updated by a device, the corresponding memory needs to be invalidated.
Flush: Before the device read a portion of memory updated by CPU, CPU must flush (write back is also correct?) the contents from cache to memory, so that device reads the contents from memory with updated contents.
If flush is not carried out it may read junk data present in memory as the memory is not still updated with contents written to cache.
Please confirm whether my above understanding is correct?
When do you want to combine both flush and invalidate? I heard that while playing with device control descriptors we need to synchronize by combining flush and invalidate. Why so?
Do we need to follow a sequence like flush followed by invalidate?
Is there a scenario in which invalidate followed by flush will be useful?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Flush 会将缓存的内容写回主内存,而 invalidate 会将缓存行标记为无效,以便将来的读取进入主内存。
我认为如果设备正在更新内存块,您将结合刷新和无效:刷新将确保设备具有最新内容,而无效将确保当设备完成时CPU将读取新内容从记忆中。
Flush does write back the contents of cache to main memory, and invalidate does mark cache lines as invalid so that future reads go to main memory.
I think you would combine flush and invalidate if the device was updating a block of memory: the flush would ensure that the device had the latest contents, and the invalidate would then ensure that when the device had finished that the CPU would read the new contents from memory.
一般来说,你是完全正确的,但有些石头可能会导致绊倒。您没有指定硬件平台。如果我们讨论的不是带有 SRAM 的小型嵌入式控制器,请考虑以下因素。
配备 MMU 的处理器支持普通 DDR 内存和驱动程序(硬件相关)内存的不同内存属性。最后一个是不可缓存的,因此不用担心刷新/失效。
由于标签中提到了 DMA,因此存在以下几种情况(假设 HW 缓冲区是不可缓存的设备内存):
注释
),以防止 CPU 使用缓存中的“旧”数据。刷新 HW 缓冲区是多余的。注意
:很明显,在 DMA 之前应该刷新“源”。仍然存在何时无效的问题。从技术上讲,它是在 CPU 尝试访问“目标”数据之前,并且可能在 DMA 之前或之后(我们应该确保 DMA 已完成工作)。 DMA之后IRL 失效可能会导致问题。参考按虚拟地址刷新/无效范围; ARMv8;缓存;
如您所见,此特定平台的无效应该在DMA之前完成。另外,我还闲聊了 ARMv7 设备的 BSP 代码,发现建议在 DMA 传输之前使目标缓冲区无效。
但这还不是全部。您可能希望在再次进行 DMA 传输后使目标缓冲区无效(没错,是第二次)。如果相关芯片具有预取功能,它可以在 DMA 工作时将数据取回缓存。因此顺序可能是:首先使预取无效后,再次将数据放入缓存 -> DMA 覆盖内存中的数据 ->高速缓存具有与内存不同的数据,并且高速缓存被标记为具有有效数据。第二个无效将确保数据再次检索到缓存中,因此缓存和内存完成同步:)
假设源缓冲区和目标缓冲区不相互交叉,则不存在依赖性。您可以
flush-invalidate
或invalidate-flush
。不这么认为。
Generally you are totally right but there is some stones that might cause to stumble. You did not specify the HW platform. If we are not talking about small embedded controllers packed w/ SRAM, consider the following.
Processors packed with MMU support different memory attributes for normal DDR memory and Driver (HW related) memory. The last one is non cacheable so there is no worries about flushing/invalidating.
Since DMA is mentioned in a tags there are a few scenarios (assuming that HW buffer is non-cacheable device memory):
NOTE
below for details) DMA transfering to prevent CPU to use 'old' data from cache. Flushing of HW buffer is redundant.NOTE
: It's obvious that 'source' should be flushed before DMAing. Still there is the question when to invalidate. Technically it's before CPU will try to access 'Destination' data and could be before or after DMA (we should ensure that DMA has finished the job). IRL invalidating after DMAing might lead to a problem. Refer toFlush/Invalidate range by virtual address; ARMv8; Cache;
As you could see invalidate for this particular platform should be done before DMAing. Also rambling th/ the BSP code for ARMv7 device I found recommendation to invalidate destination buffer before a DMA transfer.
But that's not all. You might want to invalidate destination buffer after a DMA transfer again (that's right, second time). If chip in question has prefetch it could fetch data back to cache while DMA is working. So sequence might be: after first invalidate prefetch put data in cache again -> DMA override data in memory -> cache has data different than memory and cache is marked as having valid data. Second invalidate would ensure that data would be retrieved into cache again, therefore cache and memory finished to be in sync :)
Assuming that source and destination buffers do not intersect each other, there is not dependancies. You could
flush-invalidate
orinvalidate-flush
.Don't think so.