您的位置:首页 > 其它

CPU Cache原理 &避免dma cache 出错

2013-04-18 11:37 344 查看
CPU Cache 原理及操作 & dma_cache_maint

转载下文:

CPU Cache原理
CPU缓存(Cache Memory)是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。缓存的出现主要是为了解决CPU运算速度与内存读写速度不匹配的矛盾,因为CPU运算速度要比内存读写速度快很多,这样会使CPU花费很长时间等待数据到来或把数据写入内存。在缓存中的数据是内存中的一小部分,但这一小部分是短时间内CPU即将访问的,当CPU调用大量数据时,就可避开内存直接从缓存中调用,从而加快读取速度。

cache 一致性问题

由于缓存存在于cpu与内存中间,所以任何外设对内存的修改并不能保证cache中也得到同样的更新,同样处理器对缓存中内容的修改也不能保证内存中的数据得到更新。这种缓存中数据与内存中数据的不同步和不一致现象将可能导致 使用DMA 传输数据时 或 处理器运行自修改代码时产生错误。

DMA 与 Cache

在进行DMA 操作时,如果没有对Cache 进行适当的操作,将可能产生以下两种错误:

1. DMA 从外设读取数据到供处理器使用。DMA 将外部数据直接传到内存中,但cache 中仍然保留的是旧数据,这样处理器在访问数据时直接访问缓存将得到错误的数据。

2. DMA 向外设写入由处理器提供的数据。处理器在处理数据时数据会先存放到cache 中,此时cache 中的数据有可能还没来得及写回到内存中的数据。如果这时DMA 直接从内存中取出数据传送到外设,外设将可能得到错误的数据。

为了正确进行DMA 传输,必须进行必要的cache 操作。 cache 操作主要分为 invalidate (作废) 和 writeback (写回) ,有时也将两着放在一起使用。

以linux 下对DMA 操作的函数为例:

参考:kernel/arch/arm/mm/dma-mapping.c

/*

* Make an area consistent for devices.

* Note: Drivers should NOT use this function directly, as it will break

* platforms with CONFIG_DMABOUNCE.

* Use the driver DMA support - see dma-mapping.h (dma_sync_*)

*/

void dma_cache_maint(const void *start, size_t size, int direction)

{

void (*inner_op)(const void *, const void *);

void (*outer_op)(unsigned long, unsigned long);

BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1));

switch (direction) {

case DMA_FROM_DEVICE: /* invalidate only */

inner_op = dmac_inv_range;

outer_op = outer_inv_range;

break;

case DMA_TO_DEVICE: /* writeback only */

inner_op = dmac_clean_range;

outer_op = outer_clean_range;

break;

case DMA_BIDIRECTIONAL: /* writeback and invalidate */

inner_op = dmac_flush_range;

outer_op = outer_flush_range;

break;

default:

BUG();

}

inner_op(start, start + size);

outer_op(__pa(start), __pa(start) + size);

}

EXPORT_SYMBOL(dma_cache_maint);

1. DMA 从外设读取数据到供处理器使用时,可先进性invalidate 操作。这样将迫使处理器在读取cache中的数据时,先从内存中读取数据到缓存,保证缓存和内存中数据的一致性。

2. DMA 向外设写入由处理器提供的数据时,可先进性writeback 操作。这样可以DMA传输数据之前先将缓存中的数据写回到内存中。

如果不清楚DMA 操作的方向,也可先同时进行invalidate 和writeback 操作。操作的结果等同于invalidate 和 writeback 操作效果的和。

wince 操作系统也有一套cache 操作接口:

http://msdn.microsoft.com/en-us/library/ms904878.aspx

void OEMCacheRangeFlush( LPVOID pAddr, DWORD dwLength, DWORD dwFlags );
dwFlags 的定义如下表

ValueDescription
CACHE_SYNC_WRITEBACKWrite back cached data.
CACHE_SYNC_DISCARDWrite back and discard cached data.
CACHE_SYNC_INSTRUCTIONSDiscard all cached instructions.
自修改代码 与 Cache

当处理器要执行自修改代码时,处理器首先生成新的代码存放到cache中,最后从cache 中装入再将指令送入处理器。如果处理器的cache 分为 D-Cache (数据缓存)和 I-Cache (指令缓存),则生成代码时会存入D-Cache ,而取代码时从 I-Cache 中读出,这样当D-Cache 和 I-Cache 中的数据(也就是新要生成的指令码)不相同时,会导致无法执行正确的指令。

为了使指令正确执行,需要对两个Cache中的数据及时进行同步:对D-Cache 进行writeback 操作,对I-Cashe 进行invalidate 操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: