宏ARCH_SLAB_MINALIGN的值,使用DMA时的CACHE一致性

来源:互联网 发布:win10 windows.old 编辑:程序博客网 时间:2024/05/22 12:37

ARCH_SLAB_MINALIGN

同事说 发现一个内存可优化的小点:

“Slob实现kmalloc时,会申请(size+align)的空间,其中align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN)用来对齐

ARCH_SLAB_MINALIGN,在slob中定义,为4

ARCH_KMALLOC_MINALIGN,看601b/700a/701a代码,发现都有定义为128

这样现状就是每次kmalloc,都会多申请出128B。(实际用jtag观察申请的buf时,也确实如此)

如果很多个小bufkmalloc,就不划算了。后续如果发现内存有不够时,这个是一个着眼点。

 下面的分析表明并不适合从这里省内存:

对非一致性DMA访问的平台而言,宏ARCH_KMALLOC_MINALIGN的定义在include\asm-mips\mach-generic\kmalloc.h中:
#ifndef CONFIG_DMA_COHERENT
/*
 * Total overkill for most systems but need as a safe default.
 * Set this one if any device in the system might do non-coherent DMA.
 */
#define ARCH_KMALLOC_MINALIGN 128
#endif

由上面的注释可看出,ARCH_KMALLOC_MINALIGN的值定义为128的确增加系统负担,但该值是一个默认的安全值。

但对定义了CONFIG_DMA_COHERENT的平台而言,ARCH_KMALLOC_MINALIGN的值就是__alignof__(unsigned long)。(__alignof__是gcc扩展,查询变量的对齐方式,类似于sizeof、typeof ):

在mm\slob.c中:
#ifndef ARCH_KMALLOC_MINALIGN
#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long)
#endif

#ifndef ARCH_SLAB_MINALIGN
#define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
#endif

 

使用DMA时的CACHE一致性

cache coherency when using dma

linux提供两种方式,来保证使用dma时,内存和硬件cache的一致性:

1.Coherent DMA mapping

When using this mapping, the kernel ensures that there will be no cache coherency problems between the memory and the hardware device; this means that every write operation performed by the CPU on a RAM location is immediately visible to the hardware device, and vice versa. This type of mapping is also called "synchronous" or "consistent."

2.Streaming DMA mapping

When using this mapping, the device driver must take care of cache coherency problems by using the proper synchronization helper functions. This type of mapping is also called "asynchronous" or "non-coherent."

说白了,如果采用第一种方式的话,就是由kernel来保证一致性,驱动程序是不用考虑的,这种方法的缺点是在某些体系结构上,效率很低;如果采用第二种方式的话,那么是有驱动程序来保证一致性的,所以当驱动要使用dma来进行数据传输时,必须首先检测内存和硬件cache的一致性,linux提供了这类方法。

这里说明一下:宏CONFIG_DMA_COHERENT和CONFIG_DMA_NONCOHERENT用来定义系统平台内存一致性相关特性。对定义了CONFIG_DMA_COHERENT的某个芯片,其内存是一致性内存;对定义了CONFIG_DMA_NONCOHERENT的某个芯片,其内存不是一致性内存。一致性内存的定义见内核documentation/dma-api.txt:

Consistent memory is memory for which a write by either the device or the processor can immediately be read by the processor or device without having to worry about caching effects.  (You may however need to make sure to flush the processor's write buffers before telling devices to read that memory.)

而ldd3中所说的dma_alloc_coherent和dma_free_coherent用来建立一致性DMA映射,无论对哪种芯片,都已经考虑一致性问题(dma_alloc_coherent和dma_free_coherent中会自动对CONFIG_DMA_NONCOHERENT芯片进行刷cache的操作)。

cache的一致性
先理解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与内存的数据“不一致性”错误。

由上面可以看出,DMA如果使用cache,那么一定要考虑cache的一致性。解决DMA导致的一致性的方法最简单的就是禁止DMA目标地址范围内的cache功能。但是这样就会牺牲性能。
因此在DMA是否使用cache的问题上,可以根据DMA缓冲区期望保留的的时间长短来决策。DAM的映射就分为:一致性DMA映射和流式DMA映射。
一致性DMA映射申请的缓存区能够使用cache,并且保持cache一致性。一致性映射具有很长的生命周期,在这段时间内占用的映射寄存器,即使不使用也不会释放。生命周期为该驱动的生命周期
流式DMA映射实现比较复杂,因为没具体了解,就不说明了。只知道种方式的生命周期比较短,而且禁用cache。一些硬件对流式映射有优化。建立流式DMA映射,需要告诉内核数据的流动方向。

 

 

原创粉丝点击