来源: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是总线地址。对任意一个操作都将改变写缓冲区内容。

转载于:https://www.cnblogs.com/tureno/articles/6041105.html

DMA及cache一致性的学习心得 --dma_alloc_writecombine相关推荐

  1. DMA及cache一致性的学习心得

    这里提到的DMA设备是非PCI设备 在framebuffer的prob函数中,用到了这样一个函数,下面分析下它的作用 /* *    s3c_fb_map_video_memory(): *   分配 ...

  2. Linux内存管理:ARM64体系结构与编程之cache(3):cache一致性协议(MESI、MOESI)、cache伪共享

    目录 为什么系统软件人员要深入了解cache? cache一致性协议 神马是MESI协议? MESI的操作 MESI状态图 演示:初始化状态为I的cache line 当本地CPU的缓存行状态为I时, ...

  3. Cache(三):cache的常见名词与Cache一致性问题简介

    这里一起学习一点关于学习cache中常见的术语,并再次复习一下. 学习的前辈的blog链接:https://blog.csdn.net/vivo01/article/details/127243849 ...

  4. 《浅谈Cache Memory》 学习-第四章

    Cache的层次结构 我第一次接触存储器瓶颈这个话题是在上世纪九十年代,距今已接近二十年.至今这个问题非但没有缓和的趋势,却愈演愈烈,进一步发展为Memory Wall.在这些问题没有得到解决之前,片 ...

  5. 关于OR-Mapping的学习心得体会

    关于OR-Mapping的学习心得体会 注:本文只针对设计上采用OOA(面向对象分析)及OOD(面向对象设计)方式,数据存储采用关系型数据库的系统而言. 从对OR-Mapping错误认识谈起 从工作流 ...

  6. Assembly学习心得

    http://blog.csdn.net/etmonitor/ Assembly学习心得 说明: 最近开始准备把学到的.NET知识重新整理一遍,眼过千遍不如手过一遍,所以我准备记下我的学习心得,已备参 ...

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

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

  8. 多功能PCIE交换机之三:PCIE非透明桥 cache一致性

    关于PCIE非透明桥 cache一致性 PCIE非透明桥提供了两种机制来从local node往remote node迁移数据,分别是基于地址映射和内嵌的 DMA.对remote节点而言,当它接受数据 ...

  9. Cache 工作原理、Cache 一致性,你想知道的都在这里

    作者 | 桔里猫 来源 | https://zhuanlan.zhihu.com/p/386919471 可以随便到网上查一查,各大互联网公司笔试面试特别喜欢考一道算法题,即 LRU缓存机制,又顺手查 ...

最新文章

  1. python找人,PythonOpenCV:查找未知人物
  2. Objective-C设计模式(MVC)的实现,以及协议与委托的运用
  3. python连接oracle超时设置,Python连接Oracle设置过程记录
  4. 大白话,讲编程。前端君又回来了!
  5. MySQL的性能调优工具
  6. pythontuple数据类型_Python数据类型之Tuple元组实例详解
  7. DAHON 美国大行
  8. js 为对象添加和删除属性
  9. 请画出使用mapreduce对英文句子_英文写作中有哪些常见的标点符号问题?小心你的essay会被教授diss不专业...
  10. mysql fixed数据类型_MySQL数据类型有哪些?MySQL数据类型详解
  11. 冰蝎3.0 页面存在,但是无法获取密钥
  12. Windows Server - AD域 副域控
  13. Android Studio完成简单UI设计
  14. JAVA练习 家庭记账本
  15. 假期错过的...条AI新闻都在这里了
  16. 视觉学习笔记6——YOLOv5(v6.2)部署与代码理解
  17. Android面试攻略
  18. php网络通讯,Linux_网络通讯--efax,功能说明:收发传真。 语  - phpStudy
  19. RAID5破坏的数据恢复流程和思考
  20. WPF Aero Glass Window

热门文章

  1. checkbox 在火狐的不支持
  2. 正式版的Office2007打不开beta版创建的文件
  3. LinkedList 方法知识点
  4. Title:eNSP 映射到外网
  5. qtp12版本下载安装破解教程
  6. Excel还是那些事
  7. VMware虚拟机上配置nginx后,本机无法访问问题(转载)
  8. Django使用问题记录
  9. mini_magick上传图片
  10. Java基础-异常处理机制