免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6273 | 回复: 9

[驱动] 原创:RISC cpu cache管理总结 [复制链接]

论坛徽章:
0
发表于 2009-12-17 15:01 |显示全部楼层
花了些时间,了解了一下 嵌入式中 cache的一些问题
总结一下,贴出来共享一下. 写得不好,或者有什么问题 欢迎提出.

ps: 也算是原创帖子了,欢迎讨论. 不知道怎么把帖子变成原创呢?
本文以MIPS R4000系列cpu为例.
假如使用的MIPS 4KEC (MIPSr232):
D cache & I cache 的结构都是4组并联的 cache,
每组为4KB,因此 I cache & D cache都是 16KB.
cacheline 是 16字节.


一. cache管理中,特别注意的2点:
1.DMA 控制器的操作内存的问题:
DMA 控制器的操作是直接操作内存的,并不经过cpu的cache.

2. 写指令问题.也就是flash驱动驱动load指令代码到内存中要注意的问题:
在MIPS中Data cache 与 Instrution cache 是相互独立的.因此,从内存中读取指令数据到内存,有可能数据读取到了D cache中,
没有实际回写到实际物理内存里面. 如果这个时候,执行刚才拷贝到内存的代码,就会有问题.
解释如下:
因为假如指令代码处于Data cache中(实际物理内存中,没有相应指令),此时,执行刚刚load进内存
的指令, cpu 只会 透过 Instrution cache 去执行指令,I cache里面没有对应的索引,会到内存里面去读.
但是由于指令数据还在D cache中,就出现问题了.
结论是:假如flash 驱动从介质读取指令代码到内存中时候,
必须保证 指令代码 已经回写到物理内存中,而不能留在Data cache中.

在MIPS cpu下有两种方法去保证:
MIPS下
处于kseg0的物理地址,也就是0x8000 0000 - 0x9FFF FFFF(512M)地址,进行内存访问是经过cache,但不经过MMU的
(也就是访问该内存地址后,会在cache中留有数据)
处于kseg1的物理地址,也就是0xA000 0000 - 0xBFFF FFFF(512M)地址,进行内存访问是不经过cache,也不经过MMU的
(也就是访问该内存地址后,不会在cache中留有数据)

1). 假如传入flash驱动的内存地址是处于kseg0的物理地址,也就是0x8000 0000 - 0x9FFF FFFF(512M).
a.若flash 驱动以CPU 方式通过D cache 读取数据到内存后, 最后需要将D cache中的数据回写到物理内存里面.
b.若flash 驱动以DMA驱动读取指令数据到内存,因为数据已经直接写到物理内存,不会残留在D cache中,因此DMA读取flash数据后不需要回写cache.
不过,使用DMA进行访问前,需要先将内存对应的cache无效.--->参看DMA设备写数据到内存
      但是还是有一点要注意,若此时读取出来的数据,然后cpu根据硬件ECC校验结果对内存数据进行修正.也就是使用CPU方式修改了内存.
此时,还是需要重新将D cache中的数据回写到物理内存里面.
2). 将传入flash驱动的内存地址 统一转换为 kseg1的物理地址,也就是0xA000 0000 - 0xBFFF FFFF(512M).
因为,在MIPS中,kseg1的物理地址空间是不通过cache 存取的.因此,在flash驱动里面无论使用cpu方式还是DMA方式读取数据,
都不用将D cache中的数据回写到物理内存里面.

二 . cache管理中,要注意3点问题.
1).在DMA设备从内存取数据之前. (回写cache操作)
        必须先回写cache,也就是将D cache的数据回写到物理内存中,否则DMA 直接从 内存中取数据,会取到错误的数据
       
2).DMA设备写数据到内存.(无效cache 操作)
        必须将物理内存对应的D cache索引无效掉.

3). 写指令,也就是特别注意的一.中的第2点.所谓,写指令,也就是从介质透过D cache load 指令代码到内存中,然后 cpu 执行指令
(MIPS cpu 下执行指令必须透过I cache进行执行指令)
a.写回 D cache的 数据
b. 无效I cache 相应的数据

在linux中 的一个例子,就是加载驱动模块时候,shell下执行 insmode XXX.drv
会调用内核函数load_module
load_module函数最后会执行
        flush_icache_range((unsigned long)mod->module_core,
                           (unsigned long)mod->module_core + mod->core_size);                          
注意flush_icache_range 其实是做了先回写D cache然后在无效I cache
//对于R4K mips cpu
flush_icache_range其实是执行了local_r4k_flush_icache_range.
static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
{
..
                if (end - start >= dcache_size) {
                        r4k_blast_dcache();//回写全部D cache
                } else {
                        protected_blast_dcache_range(start, end);//回写相应D cache
                }


        if (end - start > icache_size)
                r4k_blast_icache();//无效全部I cache
        else
                protected_blast_icache_range(start, end);//无效相应I cache
}

三. cache 操作要注意的问题
1.cache 操作最常用的几种为:
        1). 无效cache (invalidate)
        2). 回写cache (writeback),对于MIPS cpu 回写cache 一般都是回写D cache. 我没有看见过
        什么时候需要回写I cache的.还望 大牛 指点.
        3). 回写并且无效cache.
无效cache时候,要注意无效的地址是否是cache line对齐的,
因为不是cache line 对齐的话,有可能将其他有用的数据清除了.
比如: cpu的cache line 是16字节.
假如要无效0x8000 1004 的地址,也就是要无效 物理地址为 0x8000 1000 -  0x8000 100F ,这16 字节的cache line
这个时候, 程序的本意应该是 无效0x8000 1004 之后的一条 cahche内存.
但是,由于cache line 要对齐的原因, 却无效了0x8000 1000 - 0x8000 1003    4字节的数据.
也就是将这4字节的内存毁坏了.
很有可能这4字节的数据在之前并没有回写到物理内存里面.
最终结论是: 假如要对 cache line不对齐的内存进行无效时候,对于边界不对齐的内存,要进行
先回写,然后再无效的动作, 也就是回写并且无效cache. 不能单单是无效cache.

2. cache操作的例子
DMA拷贝的一些例子,使用DMA 从src 内存地址,将数据搬运到 dst 内存地址:
INT32S am_memcpy_dma(void* dst, void* src, INT32U count)
{
...
                r4k_dma_cache_wback((INT32U)src,count);//回写DMA源地址
                r4k_dma_cache_wback_inv((INT32U)dst,count);//无效DMA目的地址,
                // 这里要注意,由于dst 的地址可能不是cache line
                //对齐,因此,需要先回写边界部分cache line,然后再无效边界的cache line,否则,边界数据有可能丢失.
                start_dma(src,dst,count);
        ...
}

评分

参与人数 1可用积分 +30 收起 理由
T-Bagwell + 30 精品文章

查看全部评分

论坛徽章:
0
发表于 2009-12-17 16:59 |显示全部楼层
怎么 嵌入式版,那么冷清的...
只有人看了.没有回的
回帖是种美德..

人阿 !!这世道!!

论坛徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:2815-16赛季CBA联赛之四川
日期:2018-12-17 14:10:21
发表于 2009-12-18 11:25 |显示全部楼层
主要是人家有用到的时候就用了,好贴不一定非要人家回帖的
有人有建议和疑问会回帖的
如果回的是“顶”,“好贴”,“学习了”一类的帖子,我会按照版规处理的

[ 本帖最后由 T-Bagwell 于 2009-12-18 11:33 编辑 ]

论坛徽章:
0
发表于 2009-12-22 12:57 |显示全部楼层
好文,“一”中的两点在工作中都遇到过,并且折腾了很长的时间才解决,所以现在对cache特别敏感,如果遇到一些从代码上解释不清楚的问题,可以想想是不是cache的影响。

论坛徽章:
8
2015年辞旧岁徽章
日期:2015-03-03 16:54:15午马
日期:2015-02-04 12:00:07羊年新春福章
日期:2015-02-04 11:57:56双子座
日期:2014-12-02 11:44:59金牛座
日期:2014-10-08 16:47:08狮子座
日期:2014-08-29 13:37:46巳蛇
日期:2014-08-26 17:32:29NBA常规赛纪念章
日期:2015-05-04 22:32:03
发表于 2009-12-24 15:20 |显示全部楼层

回复 #1 kendyke 的帖子

好文章 感谢楼主

论坛徽章:
0
发表于 2012-01-10 20:21 |显示全部楼层
好文章 感谢楼主

论坛徽章:
0
发表于 2012-01-10 20:27 |显示全部楼层
好帖子,学习了

论坛徽章:
0
发表于 2012-03-15 16:24 |显示全部楼层
没怎么看懂

论坛徽章:
0
发表于 2012-03-17 22:56 |显示全部楼层
  感兴趣的话题,
  有几个问题想请教下:
  -1) D&I cache 在硬件上的表现形式是什么样的? 是在cpu内部的一块控制电路吗? 这块电路还是只存放数据和指令?
  -2) 帖子中提到的flash,是包括易释如内存和非易释如U盘之类的设备吗?
  -3) 结论是:假如flash 驱动从介质读取指令代码到内存中时候, 必须保证 指令代码 已经回写到物理内存中,而不能留在Data cache中
      >>> 帖子中提到这些, 我的理解指令流应该是这样的
         介质  ==>===内存条==>===>I Cache
         想问下把指令代码写回内存,是指介质还是内存条?这个功能有软件做还是硬件做?
  -4) 既然 Data cache 与 Instrution cache 是相互独立的,有怎么会把指令取到Data Cache里呢?

论坛徽章:
0
发表于 2012-08-27 20:41 |显示全部楼层
没有实际回写到实际物理内存里面
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP