Cache 与内存的一致性
由于 Cache 位于 CPU 与内存中间,任何外设对内存数据的修改并不能保证 Cache 中数据也得到同样的更新。同样,处理器对 Cache 中内容的修改也不能保证内存中的数据及时得到更新。这种 Cache 中数据与内存中数据的不同步和不一致现象将可能导致使用 DMA 传输数据时或处理器运行自修改代码时产生错误。
Cache 和内存的一致性有一些是通过硬件自动保证的,另外一些则需要通过程序设计时遵守一定的规则来保证。下面介绍这些应该遵守的规则:
地址映射关系变化造成的数据不一致
当系统中使用了 MMU 时,如果查询 Cache 时使用的是虚拟地址,则当系统中虚拟地址到物理地址的映射关系发生变化时,可能造成 Cache 中数据和主存中数据不一致的情况。
在虚拟地址到物理地址的映射关系发生变化前,如果原虚拟地址所在的数据块已经缓存在 Cache 中,当虚拟地址到物理地址的映射关系变化后,这时 CPU 访问原虚拟地址的数据块将得到错误的结果。
为了避免发生这种数据不一致的情况,在虚拟地址到物理地址的映射关系发生变化前,根据系统的具体情况,需要执行以下当中的一种或几种操作:
- 如果 DCache 是写回类型,则 clean(回写)DCache。
- 置无效 ICache 或 DCache 中相应的数据块。
- 将相应的内存区域设置为非缓冲类型。
ICache 的数据一致性问题
当系统中采用独立的 DCache 和 ICache 时,下面的操作可能造成指令不一致情况:
- 读取地址 addr1 处的指令,则包含该指令的数据块被预取到 ICache,和 addr1 在同一个数据块中,地址为 addr2 的内容也同时被预取到 ICache 中。
- 当修改 addr2 处的内容时,写操作可能影响 DCache 和主存地址为 addr2 中的内容。但是不会影响 ICache 中地址为 addr2 中的内容。
- 如果地址 addr2 中的内容是指令,当执行该指令时,就可能发生指令不一致的问题。如果地址 addr2 所在的块还在 ICache 中,系统将执行修改前的指令;如果地址 addr2 所在的块不在 ICache 中,系统将执行修改后的指令。
为了避免这种指令不一致的情况发生,在修改 addr2 中的内容之后,执行下面的操作:
- 置无效 ICache。
- 如果 DCache 是写回类型,则 clean(回写)DCache。
DMA 造成的数据不一致问题
DMA 操作直接访问主存,但是不会更新 Cache 中相应的内容,这样就可能造成数据不一致。
如果 DMA 从主存中读取的数据已经包含在 Cache 中,而且 Cache 中相应的数据已经被更新,这样 DMA 读到的将不是系统中最新的数据。同样,DMA 写操作直接更新主存中的数据,如果该数据已经包含在 Cache 中,则 Cache 中的数据不会被更新,也将造成数据不一致。
为了避免发生这种数据不一致的情况,需要执行以下当中的一种或几种操作:
- 将 DMA 访问的内存区设置成非缓冲类型。
- 在 DMA 读内存区之前,如果 DCache 是写回类型,则 clean(回写)DCache。
- 在 DMA 写内存区之前,置无效 Dcache。