cache分为Dcache和Icache,本文讨论Dcache即数据cache。
什么是DMA:就是在CPU不参与的情况下,由DMA控制器完成内存RAM和其他外设(usb、网卡等)的数据传输,可以写RAM,也可以读
RAM。具体方式就是设定DMA的源地址和目标地址,以及DMA方式,然后写入传输的字节数就可以启动DMA数据传输了。CPU设置完后就不用管数据的传输。
DMA牵涉到cache,因为CPU为了提高和RAM的交互性能,会把RAM中的部分数据放到cache,这样CPU从cache读要比从RAM读快多了,CPU会根据需要更新cache。
但是DMA方式因为没有CPU的参与,会导致cache中的新数据还没有flush到RAM,RAM中的旧数据就被读走了;或者RAM中的数据已经被DMA更新了,但是CPU还是从cache读取了旧数据。因此,当使用DMA方式时,DMA读写RAM的同时要通知CPU,具体方式如下:
1. cpu写数据到RAM,DMA从RAM拷贝数据之前,先把cache数据flush,flush_dcache_range()
2. DMA把数据拷贝到RAM后,CPU读取数据前需要使无效RAM中的这段地址,invalidate_dcache_range ()
There are three types of cache operations:
• Cache Enable/Disable – Cache on/off
• Cache Clean – Writes back dirty cache lines to the memory (sometimes called a flush)
• Cache Invalidate – Marks the contents in cache as invalid (basically, a delete operation)
Note by baoli,
Cache flush - clean & invalidate cache
A cache clean and invalidate instruction behaves as the execution of a clean instruction followed
immediately by an invalidate instruction. Both instructions are performed to the same location.
uboot/arch/arm/cpu/armv8/cache_v8.c
/*
* Performs a invalidation of the entire data cache at all levels
*/
void invalidate_dcache_all(void)
{
__asm_invalidate_dcache_all();
__asm_invalidate_l3_dcache();
}
/*
* Performs a clean & invalidation of the entire data cache at all levels.
* This function needs to be inline to avoid using stack.
* __asm_flush_l3_dcache return status of timeout
*/
inline void flush_dcache_all(void)
{
int ret;
__asm_flush_dcache_all();
ret = __asm_flush_l3_dcache();
if (ret)
debug("flushing dcache returns 0x%x\n", ret);
else
debug("flushing dcache successfully.\n");
}
/*
* Invalidates range in all levels of D-cache/unified cache
*/
void invalidate_dcache_range(unsigned long start, unsigned long stop)
{
__asm_flush_dcache_range(start, stop);
}
/*
* Flush range(clean & invalidate) from all levels of D-cache/unified cache
*/
void flush_dcache_range(unsigned long start, unsigned long stop)
{
__asm_flush_dcache_range(start, stop);
}
void dcache_enable(void)
{
/* The data cache is not active unless the mmu is enabled */
if (!(get_sctlr() & CR_M)) {
invalidate_dcache_all();
__asm_invalidate_tlb_all();
mmu_setup();
}
set_sctlr(get_sctlr() | CR_C);
}
void dcache_disable(void)
{
uint32_t sctlr;
sctlr = get_sctlr();
/* if cache isn't enabled no need to disable */
if (!(sctlr & CR_C))
return;
set_sctlr(sctlr & ~(CR_C|CR_M));
flush_dcache_all();
__asm_invalidate_tlb_all();
}
cache的作用
CPU在访问内存时,首先判断所要访问的内容是否在Cache中,如果在,就称为“命中(hit)”,此时CPU直接从Cache中调用该内容;否则,就 称为“ 不命中”,CPU只好去内存中调用所需的子程序或指令了。CPU不但可以直接从Cache中读出内容,也可以直接往其中写入内容。由于Cache的存取速 率相当快,使得CPU的利用率大大提高,进而使整个系统的性能得以提升。
Cache的一致性就是直Cache中的数据,与对应的内存中的数据是一致的。
DMA是直接操作总线地址的,这里先当作物理地址来看待吧(系统总线地址和物理地址只是观察内存的角度不同)。如果cache缓存的内存区域不包括DMA分配到的区域,那么就没有一致性的问题。但是如果cache缓存包括了DMA目的地址的话,会出现什么什么问题呢?
问题出在,经过DMA操作,cache缓存对应的内存数据已经被修改了,而CPU本身不知道(DMA传输是不通过CPU的),它仍然认为cache中的数 据就是内存中的数据,以后访问Cache映射的内存时,它仍然使用旧的Cache数据。这样就发生Cache与内存的数据“不一致性”错误。
Each of the cache policy is described here:
• Write allocation (WA) – A cache line is allocated on a write miss. This means that executing a store instruction on the processor might cause a burst read to occur.
• Write-back (WB) – A write updates the cache only and marks the cache line as dirty. External memory is updated only when the line is evicted or explicitly cleaned.
• Write-through (WT) – A write updates both the cache and the external memory system. This does not mark the cache line as dirty