转自:https://www.cnblogs.com/hoys/archive/2012/02/17/2355914.html

来源:http://xmxohy.blog.163.com/blog/static/53469584201082734630713/

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

题外话:好像2.6.29内核中,6410的总线地址和物理地址是一样的,因为我在查看vir_to_bus函数的时候,发现在/arch/arm/linux/asm/memory.h中这样定义: 
#ifndef __virt_to_bus
#define __virt_to_bus    __virt_to_phys
#define __bus_to_virt    __phys_to_virt
#endif
而且用source Insight搜索了一遍,没有发现6410相关的代码中,重新定义__vit_to_bus,因此擅自认为2.6内核中,6410的总线地址就是物理地址。希望高手指点。

顺便提一下,总线地址是从设备角度上看到的内存,物理地址是CPU的角度看到的未经过转换的内存(经过转换的是虚拟地址)

由上面可以看出,DMA如果使用cache,那么一定要考虑cache的一致性。解决DMA导致的一致性的方法最简单的就是禁止DMA目标地址范围内的cache功能。但是这样就会牺牲性能。

因此在DMA是否使用cache的问题上,可以根据DMA缓冲区期望保留的的时间长短来决策。DAM的映射就分为:一致性DMA映射和流式DMA映射。

一致性DMA映射申请的缓存区能够使用cache,并且保持cache一致性。一致性映射具有很长的生命周期,在这段时间内占用的映射寄存器,即使不使用也不会释放。生命周期为该驱动的生命周期

流式DMA映射实现比较复杂,因为没具体了解,就不说明了。只知道种方式的生命周期比较短,而且禁用cache。一些硬件对流式映射有优化。建立流式DMA映射,需要告诉内核数据的流动方向。

因为LCD随时都在使用,因此在Frame buffer驱动中,使用一致性DMA映射
上面的代码中用到 dma_alloc_writecombine函数,另外还有一个一致性DMA映射函数dma_alloc_coherent

两者的区别在于:
查看两者的源代码

  1. /*
  2. * Allocate DMA-coherent memory space and return both the kernel remapped
  3. * virtual and bus address for that space.
  4. */
  5. void *
  6. dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
  7. {
  8. void *memory;
  9. if (dma_alloc_from_coherent(dev, size, handle, &memory))
  10. return memory;
  11. if (arch_is_coherent()) {
  12. void *virt;
  13. virt = kmalloc(size, gfp);
  14. if (!virt)
  15. return NULL;
  16. *handle =  virt_to_dma(dev, virt);
  17. return virt;
  18. }
  19. return __dma_alloc(dev, size, handle, gfp,
  20. pgprot_noncached(pgprot_kernel));
  21. }
  22. /*
  23. * Allocate a writecombining region, in much the same way as
  24. * dma_alloc_coherent above.
  25. */
  26. void *
  27. dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
  28. {
  29. return __dma_alloc(dev, size, handle, gfp,
  30. pgprot_writecombine(pgprot_kernel));
  31. }
  32. #define pgprot_noncached(prot)  __pgprot(pgprot_val(prot) &~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
  33. #define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) &~L_PTE_CACHEABLE)

再结合网上的资料(不过我感觉那文章写的有些问题,我修改了一下),由上面代码可以看出,两个函数都调用了__dma_alloc函数,区别只在于最后一个参数。

dma_alloc_coherent 在 arm 平台上会禁止页表项中的 C (Cacheable) 域以及 B (Bufferable)域。而 dma_alloc_writecombine 只禁止 C (Cacheable) 域.

C 代表是否使用高速缓冲存储器, 而 B 代表是否使用写缓冲区。

这样,dma_alloc_writecombine 分配出来的内存不使用缓存,但是会使用写缓冲区。而 dma_alloc_coherent  则二者都不使用。

C B 位的具体含义
0 0 无cache,无写缓冲;任何对memory的读写都反映到总线上。对 memory 的操作过程中CPU需要等待。
0 1 无cache,有写缓冲;读操作直接反映到总线上;写操作,CPU将数据写入到写缓冲后继续运行,由写缓冲进行写回操作。
1 0 有cache,写通模式;读操作首先考虑cache hit;写操作时直接将数据写入写缓冲,如果同时出现cache hit,那么也更新cache。
1 1 有cache,写回模式;读操作首先考虑cache hit;写操作也首先考虑cache hit。

这样,两者的区别就很清楚了。

A = dma_alloc_writecombine(struct device *dev, size_t size,dma_addr_t *handle, gfp_t gfp);

含义:
A          : 内存的虚拟起始地址,在内核要用此地址来操作所分配的内存
dev      : 可以平台初始化里指定,主要是用到dma_mask之类参数,可参考framebuffer
size      : 实际分配大小,传入dma_map_size即可
handle: 返回的内存物理地址,dma就可以用。

A和hanle是一一对应的,A是虚拟地址,而handle是总线地址。对任意一个操作都将改变写缓冲区内容。

DMA及cache一致性的学习心得 --dma_alloc_writecombine【转】的更多相关文章

  1. 【转】DMA和cache一致性

    DMA和cache一致性问题 Cache原理 CPU缓存(Cache Memory)是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多.缓存的出现主要是为了解决CPU ...

  2. DMA与cache一致性的问题

    Cache和DMA本身似乎是两个毫不相关的事物.Cache被用作CPU针对内存的缓存利用程序的空间局部性和时间局部性原理,达到较高的命中率,从而避免CPU每次都必须要与相对慢速的内存交互数据来提高数据 ...

  3. Cache一致性与DMA

    cache一致性与DMA 第一个问题 对于进行DMA操作的设备, 并不是所有系统都保持它们的cache一致性.在这种情况下, 准备进行DMA的设备可能从RAM得到陈旧的数据, 因为脏的cache行可能 ...

  4. 我的MYSQL学习心得(十一) 视图

    我的MYSQL学习心得(十一) 视图 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  5. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  6. 我的MYSQL学习心得(十六) 优化

    我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  7. 我的MYSQL学习心得(十七) 复制

    我的MYSQL学习心得(十七) 复制 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. 我的MYSQL学习心得(十一)

    原文:我的MYSQL学习心得(十一) 我的MYSQL学习心得(十一) 我的MYSQL学习心得(一) 我的MYSQL学习心得(二) 我的MYSQL学习心得(三) 我的MYSQL学习心得(四) 我的MYS ...

  9. linux学习心得之目录树开端与/etc(图文)

    linux学习心得之目录树开端与/etc(图文) linux中“一切皆文件”,学习linux一年了,在学习过程中对目录树的一点心得,分享给大家,有不对的地方敬请斧正. 不多说了,先上图: 根目录: / ...

随机推荐

  1. Java创建文件

    public class FileTest { public static void main(String[] args) throws IOException { File file = new ...

  2. luogu3646 巴厘岛的雕塑 (dp)

    我们一位一位地来做,每次判断这一位能否放0,而且要在满足前几位的情况下.用dp来判断 具体来说,设f[i][j]表示前i个划分成j个区间能否满足,那么我们会有转移trans[i][k+1],当区间[i ...

  3. Centos6.5使用yum安装mysql

    0. 说明 先要查看yum源是否有你想要的mysql版本 yum list | grep mysql 如果没有则先要更新yum源 yum -y update 更新后即可进行下一步操作. 1. yum安 ...

  4. C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!

    之前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点.知识用时方恨少,这一段时间正好各种笔试题,其中关于const的用法也是层出不穷,所以疲于在书本上各种翻,这里汇总一下,加深自 ...

  5. Eclipse使用总结(不定时更新)

    1.安装activiti插件 (1)在线下载 点击Add输入Location:http://activiti.org/designer/update/   Name:Activiti (2)本地安装 ...

  6. 8、JPA-映射-双向一对一

    一个管理对应一个部门,一个部门对应一个管理,例中由部门维护关联关系 实体类 Department package com.jpa.yingshe; import javax.persistence.* ...

  7. js的各种验证

    验证手机号格式是否正确 // 判断是否为手机号 isPoneAvailable: function (pone) { var myreg = /^[1][3,4,5,7,8][0-9]{9}$/; i ...

  8. 内联函数 —— C 中关键字 inline 用法解析

    一.什么是内联函数 在C语言中,如果一些函数被频繁调用,不断地有函数入栈,即函数栈,会造成栈空间或栈内存的大量消耗. 为了解决这个问题,特别的引入了inline修饰符,表示为内联函数. 栈空间就是指放 ...

  9. HITS算法--从原理到实现

    本文介绍HITS算法的相关内容. 1.算法来源 2.算法原理 3.算法证明 4.算法实现 4.1 基于迭代法的简单实现 4.2 MapReduce实现 5.HITS算法的缺点 6.写在最后 参考资料 ...

  10. pyqt5 添加属性-类方法用属性形式访问

    方法一 装饰器法 import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout,QLab ...