您的位置:首页 > 其它

DMA和cache一致性问题

2015-03-30 17:17 218 查看
引自:http://blog.chinaunix.net/uid-272870-id-2137810.html

1 cacheFlush 用于将cache中的数据写到缓存如"
writetobuf( *buf); 此时数据写到cache中
cacheFlush(*buf );将cache中的数据写到buf ...内存中
2 cacheInvalidate 用于作废cache中的数据 , cache再将内存中的数据搬到cache中,如
cacheInvalidate( * buf); 用于作废cache中的数据 , cache再将内存buf中的数据搬到cache中
readfrombuf(* buf);cache中读数据,数据从buf上搬到cache中再读取的
Cache的工作原理
Cache的工作原理是基于程序访问的局部性。
对大量典型程序运行情况的分析结果表明。
在一个较短的时间间隔内,由程序产生的地址往往集中在存储器逻辑地址空间的很小范围内。
指令地址的分布本来就是连续的。
再加上循环程序段和子程序段要重复执行多次。因此。
对这些地址的访问就自然地具有时间上集中分布的倾向。
数据分布的这种集中倾向不如指令明显,但对数组的存储和访问以及工作单元的选择都可以使存储器地址相对集中。这种对局部范围的存储器地址
频繁访问,而对此范围以外的地址则访问甚少的现象,就称为程序访问的局部性。
根据程序的局部性原理,可以在主存和CPU通用寄存器之间设置一个高速的容量相对较小的存储器。
把正在执行的指令地址附近的一部分指令或数据
从主存调入这个存储器,供CPU在一段时间内使用。这对提高程序的运行速度有很大的作用。这个介于主存和CPU之间的高速小容量存储器称作
高速缓冲存储器(Cache)。
系统正是依据此原理,不断地将与当前指令集相关联的一个不太大的后继指令集从内存读到Cache,然后再与CPU高速传送,从而达到速度匹配。
CPU对存储器进行数据请求时,通常先访问Cache。由于局部性原理不能保证所请求的数据百分之百地在Cache中,这里便存在一个命中率。
即CPU在任一时刻从Cache中可靠获取数据的几率。
命中率越高,正确获取数据的可靠性就越大。一般来说,Cache的存储容量比主存的容量小得多。
但不能太小,太小会使命中率太低;
也没有必要过大,过大不仅会增加成本,而且当容量超过一定值后,命中率随容量的增加将不会有明显地增长。
只要Cache的空间与主存空间在一定范围内保持适当比例的映射关系,Cache的命中率还是相当高的。
一般规定Cache与内存的空间比为4:1000,即128kB
Cache可映射32MB内存;256kB Cache可映射64MB内存。在这种情况下。
命中率都在90%以上。
至于没有命中的数据,CPU只好直接从内存获取。获取的同时,也把它拷进Cache。
以备下次访问。
Cache的基本结构
Cache通常由相联存储器实现。相联存储器的每一个存储块都具有额外的存储信息,称为标签(Tag)。当访问相联存储器时,将地址和每一个标签
同时进行比较,从而对标签相同的存储块进行访问。Cache的3种基本结构如下:
全相联Cache
在全相联Cache中,存储的块与块之间。
以及存储顺序或保存的存储器地址之间没有直接的关系。程序可以访问很多的子程序、堆栈和段,
而它们是位于主存储器的不同部位上。 因此。
Cache保存着很多互不相关的数据块。
Cache必须对每个块和块自身的地址加以存储。当请求数据时,
Cache控制器要把请求地址同所有地址加以比较。
进行确认。
这种Cache结构的主要优点是。
它能够在给定的时间内去存储主存器中的不同的块,命中率高;缺点是每一次请求数据同Cache中的地址进行比较
需要相当的时间,速度较慢。
直接映像Cache
直接映像Cache不同于全相联Cache。
地址仅需比较一次。
在直接映像Cache中。
由于每个主存储器的块在Cache中仅存在一个位置,因而把地址的比较次数减少为一次。其做法是,为Cache中的每个块位置
分配一个索引字段,用Tag字段区分存放在Cache位置上的不同的块。
单路直接映像把主存储器分成若干页。
主存储器的每一页与Cache存储器的大小相同。
匹配的主存储器的偏移量可以直接映像为Cache偏移量。
Cache的Tag存储器(偏移量)保存着主存储器的页地址(页号)。
以上可以看出。
直接映像Cache优于全相联Cache,能进行快速查找,其缺点是当主存储器的组之间做频繁调用时,Cache控制器必须做多次转换。
组相联Cache
组相联Cache是介于全相联Cache和直接映像Cache之间的一种结构。这种类型的Cache使用了几组直接映像的块。
对于某一个给定的索引号,
可以允许有几个块位置。
因而可以增加命中率和系统效率。
Cache与DRAM存取的一致性
在CPU与主存之间增加了Cache之后,便存在数据在CPU和Cache及主存之间如何存取的问题。读写各有2种方式。
贯穿读出式(Look Through)
该方式将Cache隔在CPU与主存之间,CPU对主存的所有数据请求都首先送到Cache,由Cache自行在自身查找。如果命中。
则切断CPU对主存的请求,
并将数据送出;不命中。
则将数据请求传给主存。
该方法的优点是降低了CPU对主存的请求次数,缺点是延迟了CPU对主存的访问时间。
旁路读出式(Look Aside)
在这种方式中,CPU发出数据请求时,并不是单通道地穿过Cache。
而是向Cache和主存同时发出请求。由于Cache速度更快,如果命中,
则Cache在将数据回送给CPU的同时,还来得及中断CPU对主存的请求;不命中。
则Cache不做任何动作。
由CPU直接访问主存。
它的优点是没有时间延迟,缺点是每次CPU对主存的访问都存在,这样。
就占用了一部分总线时间。
写穿式(Write Through)
任一从CPU发出的写信号送到Cache的同时,也写入主存,以保证主存的数据能同步地更新。
它的优点是操作简单,但由于主存的慢速,降低了系统的写速度并占用了总线的时间。
回写式(Copy Back)
为了克服贯穿式中每次数据写入时都要访问主存。
从而导致系统写速度降低并占用总线时间的弊病,尽量减少对主存的访问次数,又有了回写式。
它是这样工作的:数据一般只写到Cache,这样有可能出现Cache中的数据得到更新而主存中的数据不变(数据陈旧)的情况。
但此时可在Cache 中设一标志地址及数据陈旧的信息。
只有当Cache中的数据被再次更改时。
才将原更新的数据写入主存相应的单元中,
然后再接受再次更新的数据。这样保证了Cache和主存中的数据不致产生冲突。
……
VxWorks中实现了MMU(前提是CPU要支持MMU),内存管理页灵活了很多,未能针对所有MMU属性代码一一查看。
但Cache安全(Cache-Safe)的内存分配是最为
常见实用的。VxWorks中用cacheDmaMalloc()来分配Cache-Safe的内存,也就是不存在cache一致性问题的内存,这些内存对于DMA设备和驱动常常使用。
而malloc分配的内存就是具有cache功能的,也就存在cache一致性的问题了,因此malloc分配的内存在DMA和驱动设备中使用有很大隐患。是否需要使用
Cache-Safe的内存,就得看应用场合了。
cacheDmaMalloc的实现机制使用CPU支持的MMU页表转换功能。
就是设定物理页属性。
将该页的属性设定不可cache,就可以实现分配Cache-Safe的内存了。
不使用cache功能。
性能上自然有些差距,而且该函数是以页大小为单位分配的。
因此分配小量内存是会浪费相当的内存空间的,使用时需要注意。
当CPU写一个DMA设备上的内存时。
数据首先被写到cache中,当DMA设备从RAM中传输数据时。
不保证内存中的数据与cache中的数据一致。
这样输出到设备的数据也许不是最新的,最新的数据应该在cache内。可以在数据传输到DMA设备之前将cache数据刷新到内存中。
当CPU读一个DMA设备上的内存时,数据读可以来自cache的buffer而不是从设备传输到内存的数据。
可以确保cache buffer已经被标记(屏蔽)
来解决读出的数据来自内存而非cache.
Driver可以通过分配无cache buffers(使用cacheDmaMalloc())或刷新和使cache无效来解决CPU与设备之间数据传输的cache一致性问题。
分配无cache buffers常用于分配静态buffers,它需要MMU的支持。无cache
buffers频繁地被动态分配和释放将导致大量的内存被标记为无cache.
一个择中的方法来使用动态无cache buffer是人为地刷新(使用cacheFlush()函数)和屏蔽cache
(使用cacheInvalidate( )

Cache的一致性问题:很多时候在我们开发板卡驱动程序的时候我们对分配的内存带的cache会产生迷惑,我们什么时候应该分配带cache的内存,有 cache有什么好处,应该要注意哪些问题,有可能会出现哪些问题等等太多的问题不明确,所以我们在这里就简单介绍一下有关的cache问题。首先cache的最大的好处是,解决CPU与内存之间的瓶颈,我们现在使用的SDRAM的速度一般都在3ns~10ns左右,而CPU的速度已经到了1G,甚至十几G或几十G的速度,很明显这样的速度差异会导致CPU在存取内存时经常要等待数据在内存上的操作,这将致命地影响系统的性能。所以人们引进了cache机制,因为造价及物理上的限制cache通常都不大只有256K或512K,但是速度很快,它的位置一般在CPU与内存之间,它有一些列的快速算法来保证下次CPU存取内存的数据在cache内的高机率。这样CPU在存取数据如果数据在cache内则直接对cache进行存取而无须与缓慢的内存打交道。为板卡开发的driver必须保证cache的一致性,即cache中的数据必须与内存中的数据保持同步,因为在使用异步方式读取内存时有可能产生内存与cache失步。数据cache是为了减少存取内存的次数,而加快系统的性能,数据cache通常有两种放式:writethrough和copyback。Writethrough是指在写内存时同时也往cache中写。保证cache的在输出上一致,但不保证在输入时一致。Copyback仅将数据写到cache中,它保证数据在输入和输出时都一致。当CPU写一个DMA设备上的内存时,数据首先被写到cache中,当DMA设备从RAM中传输数据时,不保证内存中的数据与cache中的数据一致。这样输出到设备的数据也许不是最新的,最新的数据应该在cache内。可以在数据传输到DMA设备之前将cache数据刷新到内存中。当CPU读一个DMA设备上的内存时,数据读可以来自cache的buffer而不是从设备传输到内存的数据,可以确保cache
buffer已经被标记(屏蔽)来解决读出的数据来自内存而非cache. Driver可以通过分配无cache buffers(使用cacheDmaMalloc())或刷新和使cache无效来解决CPU与设备之间数据传输的cache一致性问题。分配无cache
buffers常用于分配静态buffers,它需要MMU的支持。无cache buffers频繁地被动态分配和释放将导致大量的内存被标记为无cache.一个择中的方法来使用动态无cache
buffer是人为地刷新(使用cacheFlush()函数)和屏蔽cache (使用cacheInvalidate( )).注意在设备读数据之前用cacheFlush(
)保证数据一致,而在设备写内存后用cacheInvalidate( )保证将cache和内存数据的一致。
1,Writethrough是指在写内存时同时也往cache中写。保证cache的在输出上一致,但不保证在输入时一致。这句话怎么理解?
2,当CPU写一个DMA设备上的内存时,数据首先被写到cache中,当DMA设备从RAM中传输数据时,不保证内存中的数据与cache中的数据一致。 这句话是说,CPU对DMA设备进行写操作,数据虽写到cache中,但却是从ram中取的数据。cpu如何控制从cache取数据还是从ram取数据?
如果CACHE中已经有RMA数据的映像,那么CPU就会从RAM中取数据,虽然有可能这时CACHE和RAM中的数据已经不一致了;反之,CPU会从RAM中取数据,如果这快RAM是CACHEABLE的,那么CPU会把一块数据都取到CHCHE中。
还有外设和FLASH的地址空间不能设置承WRITE BUFFERABLE,外设的地址空间也不能设置成CACHEABLE的,
但FLASH的地址空间可以设置成READ CACHEABLE,无论是DATA还是INSTRUCTION,但FLASH的地址空间千万不能设置成WRITE
CACHEABLE,那样的话FLASH的操作都是不能完成。
对于没有MMU的CPU,要使能CAHCE,必须配置MPU,MPU很简单,就是对不同的内存区域给予不同的读写权限和缓冲机制,更具体的可以看看ARM的资料,在ARM的网站上就有。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: