前言

  项目中需要通过驱动与fpga通讯,获取fpga往内存里写的数据。因为数据量比较大,需要驱动分配600多M的内存给fpga来写数据,且因为是与fpga通讯,需要连续的内存,还得是uncached的,因此打算采用dma接口dma_alloc_coherent来分配如此大的内存。然而,在分配的过程中遇到了一些问题,下面对这次的调试进行总结。

环境说明

  • soc: zc702(32bit arm + fpga)
  • ddr: 1g
  • linux kernel: 3.15.0

分配200M DMA空间失败

  原因分析:

  系统默认的DMA最大允许空间为128M,其他模块,如网卡驱动用去了一些,导致可使用的DMA空间低于128M了。要去分配200M,当然不够!

  解决方法:

  修改默认配置选项为CONFIG_CMA_SIZE_MBYTES=384,重新编译内核即可解决。当然,也可以通过给内核传参cma=384M,这样就不用重新编译内核了。

分配600M DMA空间失败

  当期望的dma分配为600M时,通过修改CMA_SIZE_MBYTES=700已经没用了,这会导致系统启动时报cma失败,进而导致系统其他模块dma申请都失败。CMA_SIZE_MBYTES=512(500是可以的)时报错信息如下:

cma: CMA: failed to reserve 512 MiB

原因分析:

没有这么大的连续空间

解决方法1:

找到没有这么大连续空间原因,毕竟CMA_SIZE_MBYTES已经为512M了

解决方法2:

如果方法1不能解决,那么只有通过另一种方式了,采用保留内存,然后再通过ioremap_nocache的方式申请这么大片保留的连续区域

在尝试方法1和方法2的过程中,又遇到了一些其他问题。

先说说方法2吧!保留内存很容易,在给内核传参时加上mem=256,那么就意味着我保留了768M内存,然而在ioremap时失败了,地址不够!!!这也很正常,毕竟内核的ioremap区域的地址才几十M,而我期望申请的是几百M!!!解决方法有,修改user/kernel 3G/1G的分配为1G/3G,这样内核的地址空间就够多了吧!经过验证,确实可以了。

再说说方法1,通过查看启动信息,发现dtb加载在0x20000000处,刚好是512M那里,这也就是导致了不连续的原因!通过修改uboot环境变量fdt_high(同理,如果用了ramdisk,那么可能也需要修改initrd_high的地址,后面就不再重复了)来修改dtb加载地址为0x28000000,成功启动。看来导致不连续的问题确实就是dtb导致的!那么将CMA_SIZE_MBYTES=512改为我们的目标CMA_SIZE_MBYTES=700 fdt_high=0x2c000000,是否可以呢?答案是no。错误信息如下:

cma: CMA: failed to reserve 700 MiB

这次我认为不是dtb的问题了,应该是linux kernel内存布局的限制!由于当前采用的user/kernel 3G/1G的分割,内核总共才1G的地址空间,且开启了CONFIG_HIGHMEM,而内核默认会保留240M(之前是128M,该问题后面细说)地址空间,低端内存总共才760M,而由于某些我暂时不知道的原因,限制了dma分配700M空间(可能是按某种比例划分导致的)!怎么解决呢???我的做法,第一步(当然,该方法不是解决该问题的关键),修改内核编译选项CONFIG_HIGHMEM,去掉highmem该功能,毕竟我们才1G内存,用那个选项会显得有点多余,还影响了性能!然而,新问题又出现了,这次是系统起来后,内存不是1G了,变成760M,再次分析得出,即使没有开启CONFIG_HIGHMEM,内核仍然会有240M地址空间作为保留,用于io remap等;第二步,采用方法2中的方法,修改user/kernel 3G/1G的分配为1G/3G。通过启动信息:

Memory: 416196K/1048576K available (5240K kernel code, 260K rwdata, 1616K rodata, 200K init, 301K bss, 632380K reserved)
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0x80800000 - 0xff000000 (2024 MB)
lowmem : 0x40000000 - 0x80000000 (1024 MB)
modules : 0x3f000000 - 0x40000000 ( 16 MB)
.text : 0x40008000 - 0x406ba454 (6858 kB)
.init : 0x406bb000 - 0x406ed380 ( 201 kB)
.data : 0x406ee000 - 0x4072f320 ( 261 kB)
.bss : 0x4072f32c - 0x4077a7a4 ( 302 kB)

可以看出,低端内存1G正常了,内存又回来了_,现在我将CMA_SIZE_MBYTES=700 fdt_high=0x30000000dma分配也正常了

240M的原因

Linux内核版本从3.2到3.3 默认的vmalloc size由128M 增大到了240M,3.4.0上的

修改Commit信息如下:

To accommodate all static mappings on machines withpossible highmem usage,

the default vmalloc area size is changed to 240 MB sothat VMALLOC_START

is no higher than 0xf0000000 by default.

总结

  本文提供了两种方式来解决期望DMA区域特别大的情况(几百M的情况),通过这次的bug调试,更加深入的理解了linux内存管理相关知识。突然想感叹下,好久没碰内核了,看来以后有时间就的补补!!!

关于cma扩展阅读

完!

2016年12月

增大dma的分配的更多相关文章

  1. 32.Linux-2440下的DMA驱动(详解)

    DMA(Direct Memory Access) 即直接存储器访问, DMA 传输方式无需 CPU 直接控制传输,通过硬件为 RAM .I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大 ...

  2. 22、DMA驱动程序框架

    一.使用DMA的优点及DMA支持的请求源(请求源是启动DMA传输的事件,可以认为是触发.它可以是软件,也可以是中断,或者外部事件) 1.DMA优点是其进行数据传输时不需要CPU的干涉,可以大大提高CP ...

  3. Java NIO-09-零拷贝之 DMA

    DMA 的好处 在介绍DMA之前我想问大家:我们为什么要引入DMA,DMA对我们有什么好处那? 计算机系统中各种常用的数据输入/输出方法有查询方式(包括无条件及条件传送方式)和中断方式,这些方式适用于 ...

  4. 逃逸分析与栈、堆分配分析 escape_analysis

    小结: 1.当形参为 interface 类型时,在编译阶段编译器无法确定其具体的类型.因此会产生逃逸,最终分配到堆上. 2.The construction of a value doesn't d ...

  5. 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型

    小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...

  6. Memcached简介

    在Web服务开发中,服务端缓存是服务实现中所常常采用的一种提高服务性能的方法.其通过记录某部分计算结果来尝试避免再次执行得到该结果所需要的复杂计算,从而提高了服务的运行效率. 除了能够提高服务的运行效 ...

  7. PROC 文件系统调节参数介绍(netstat -us)

    转自:http://www.cnblogs.com/super-king/p/3296333.html /proc/net/* snmp文件 Ip: ip项 Forwarding        : 是 ...

  8. net_device 结构体分析

    /* * The DEVICE structure. * Actually, this whole structure is a big mistake. It mixes I/O * data wi ...

  9. Operating System Memory Management、Page Fault Exception、Cache Replacement Strategy Learning、LRU Algorithm

    目录 . 引言 . 页表 . 结构化内存管理 . 物理内存的管理 . SLAB分配器 . 处理器高速缓存和TLB控制 . 内存管理的概念 . 内存覆盖与内存交换 . 内存连续分配管理方式 . 内存非连 ...

随机推荐

  1. 评论模块Demo(XML读写,定时器。)

    这个Demo主要是自己做练习熟悉jquery,ajax,与xml文件的读写,以下是实现页面效果: 后台控制器: public ActionResult AddMsg() { XmlDocument x ...

  2. (转) Parameter estimation for text analysis 暨LDA学习小结

    Reading Note : Parameter estimation for text analysis 暨LDA学习小结 原文:http://www.xperseverance.net/blogs ...

  3. 【题解】51nod 1672区间交

    二分答案 + two - pointer + 树状数组大法好ヽ(゚∀゚)メ(゚∀゚)ノ 我们可以直接二分一个答案,然后检验 是否存在一个值大于等于这个二分的答案的,且覆盖次数大于等于 \(k\) 的区 ...

  4. [NOIP2012 TG D2T1]同余方程

    题目大意:求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 题解:即求a在mod b意义下的逆元,这里用扩展欧几里得来解决 C++ Code: #include<cstdio ...

  5. Android ListView的优化

    最近的项目中有通讯录这个模块,里面的通讯录涉及的联系人数量很大,导致在加载页面的时候有点卡,所以就必须得进行优化,优化的最终实现理论是什么?就是让ListView一次性加载的数据较少,后续根据用户操作 ...

  6. 20165218 2017-2018-1《Java程序设计》第二周学习总结

    20165218 2017-2018-1 <Java程序设计>第2周学习总结 教材学习内容总结 Ch2 基本数据类型与数组 Unicode字符集之中所有都叫做"字母", ...

  7. MySQL基础原创笔记(一)

    对表的增删改操作: 创建表: create table student (          id  int  primary key  auto_increment,          name   ...

  8. X day1

    题目pdf 官方题解 T1: 我们可以发现此题若要求$[L,R]$区间的答案,其实就是再求前缀和,我们设$b$为当前出现次数最多的字符,$c$为最小,所以答案为$s[b]_r-s[c]_r-(s[b] ...

  9. weakself的另一种写法

    在不久前看AFNetworking的源码时候发现了这么一句: 1 2 3 4 5 6 7 8 9 10 // 不知道这行代码的使用场景的同学你该去自习看看ARC的注意事项和Block的使用了 // A ...

  10. HDU2647 topsort

    Problem Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he ...