首页 > 系统相关 >内存管理-13-CMA内存-1-初探

内存管理-13-CMA内存-1-初探

时间:2024-07-02 21:09:53浏览次数:1  
标签:13 region cma CMA 内存 shared root

基于msm-5.4

关键词 cma_alloc/cma_release  MIGRATE_ISOLATE  MIGRATE_CMA

一、概述

1. CMA简介

CMA(Contiguous Memory Alloctor)主要用于分配大块连续的物理内存。伙伴系统能分配的最大连续物理内存块是2^10,即一个pageblock大小4MB。为了提高内存的使用率,嵌入式平台上一般使用CMA.。

在伙伴系统的 free_area[] 链表中有一个 MIGRATE_CMA 类型,当不需要分配大块连续物理内存时,会将CMA内存通过伙伴系统提供给其它模块使用。

和DMA功能类似,CMA也是预先预留出一块连续的物理内存,给多媒体等需要大块连续物理内存的模块使用,如果不使用,CMA内存区也不会空闲着,通过伙伴系统的 free_page()/alloc_pages() 接口释放到伙伴系统,给其它模块使用。
当需要大块连续物理内存时,才会从CMA中分配,当CMA内存不足时,会将其释放到伙伴系统中的内存再拿回来,若属于CMA的一些页面已经被其它程序使用了,那么还要做一个迁移操作,腾出连续的区域。

简化理解,CMA区域就是对DMA区域的改进,在不使用时不让其空闲着,释放给伙伴系统给其它程序使用,当需要使用时再收回来,一方面满足了分配大块连续物理内存的需求,另一方面提高了内存的使用率。

 

2. CMA对外接口

cma_alloc(): 从CMA区域分配一大块连续的物理内存,若此内存已经被伙伴系统给别人使用了,还要回收回来用作CMA内存使用。

cma_release(): 当使用完CMA内存时,调用此函数将内存返还给CMA,CMA会调用伙伴系统的 free_page() 将这块内存释放到伙伴系统中,供其它模块使用。

实际上驱动很少通过 cma_alloc()/cma_release() 接口去分配CMA内存了,主要是通过DMA接口间接调用到CMA接口。

 

3. CMA实现

//mm/cma.h

struct cma {
    unsigned long   base_pfn; //此CMA区域起始页帧号
    unsigned long   count;    //物理页的个数
    unsigned long   *bitmap;  //表示此CMA中物理页的使用情况,每一个bit位表示一个物理页是否被分出去了还是空闲的。
    unsigned int order_per_bit; //和上面bitmap配合使用,若为0则每个bit代表一个物理页,若为1则表示每个bit代表两个物理页
    struct mutex    lock;
#ifdef CONFIG_CMA_DEBUGFS
    struct hlist_head mem_head;
    spinlock_t mem_head_lock;
#endif
    const char *name;
};

//mm/cma.c
struct cma cma_areas[MAX_CMA_AREAS]; //17 CONFIG_CMA_AREAS+1
unsigned cma_area_count;

内核允许系统上有多个CMA区域,因此定义了一个数组 cma_areas[] 来保存所有的CMA区域,最大支持的个数可配置。

假设 order_per_bit=1 的,每个bit代表2个物理页,为0则每个bit代表1个物理页。

CMA初始化的时候,也会将CMA内存以pageblock 4MB的大小,插入到伙伴系统的 MIGRATE_CMA 类型的空闲链表中。只有用户向伙伴系统申请的内存是可移动的,才可能会去CMA链表上去拿内存。

伙伴系统在初始化的时候将内存分为4MB大小的pageblock,每个pageblock内存块都有物理页的类型,MIGRATE_UNMOVABLE、MIGRATE_MOVABLE 等。

假设DMA模块现在要去申请两个pageblock大小的连续物理内存,系统会找到CMA内存在伙伴系统中的位置,将其对应的pageblock设置为 MIGRATE_ISOLATE 类型(此时其上所有物理页都变为这个类型),表示此pageblock已经被当做CMA内存拿去使用了,伙伴系统不要分配它了。


4. CMA初始化

初始化有两种方式,一个是通过内核配置,另一个是通过设备树dts文件。

设备树中 reserved-memory 节点也是受伙伴系统管理的,但是不会通过伙伴系统的接口给用户使用了。保留下来这块内存用于专门的用途。compatible = "shared-dma-pool" 指定的可以用作CMA区域,内核根据这个字眼去解析然后初始化成一个struct cma结构。

/ {
    reserved-memory {
        #address-cells = <0x02>;
        #size-cells = <0x02>;
        ranges;
        phandle = <0x2ea>;

        linux,cma {
            compatible = "shared-dma-pool";
            alloc-ranges = <0x00 0x00 0x00 0xffffffff>;
            reusable;
            alignment = <0x00 0x400000>;
            size = <0x00 0x2000000>; //32M
            linux,cma-default;
            phandle = <0x2eb>;
        };

        qseecom_region {
            compatible = "shared-dma-pool";
            alloc-ranges = <0x00 0x00 0x00 0xffffffff>;
            no-map;
            alignment = <0x00 0x400000>;
            size = <0x00 0x1400000>; //20M
            phandle = <0x02>;
        };

        qseecom_ta_region {
            compatible = "shared-dma-pool";
            alloc-ranges = <0x00 0x00 0x00 0xffffffff>;
            no-map;
            alignment = <0x00 0x400000>;
            size = <0x00 0x1000000>; //16M
            phandle = <0x03>;
        };

        mem_dump_region {
            compatible = "shared-dma-pool";
            alloc-ranges = <0x00 0x00 0x00 0xffffffff>;
            reusable;
            size = <0x00 0x1000000>; //16M
            phandle = <0x05>;
        };

        cnss_wlan_region {
            compatible = "shared-dma-pool";
            alloc-ranges = <0x00 0x00 0x00 0xffffffff>;
            reusable;
            alignment = <0x00 0x400000>;
            size = <0x00 0x6000000>; //96M
            phandle = <0x18b>;
        };

        pmem_shared_region {
            reg = <0x01 0x66500000 0x00 0x51400000>;
            label = "pmem_shared_mem";
            phandle = <0x2ec>;
        };

        ramoops@800000000 {
            compatible = "ramoops";
            reg = <0x08 0x00 0x00 0x200000>;
            record-size = <0x40000>;
            console-size = <0x40000>;
            pmsg-size = <0x40000>;
        };
    };
};

内核启动log打印:

# cat kernel.txt | grep OF:
<6>[    0.000000]  (0)[0:swapper]OF: reserved mem: initialized node qseecom_region, compatible id shared-dma-pool
<6>[    0.000000]  (0)[0:swapper]OF: reserved mem: initialized node qseecom_ta_region, compatible id shared-dma-pool
<6>[    0.000000]  (0)[0:swapper]OF: reserved mem: initialized node mem_dump_region, compatible id shared-dma-pool
<6>[    0.000000]  (0)[0:swapper]OF: reserved mem: initialized node cnss_wlan_region, compatible id shared-dma-pool
<6>[    0.000000]  (0)[0:swapper]OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool

<6>[    0.000000]  (0)[0:swapper]Memory: 13692116K/14227228K available (18344K kernel code, 3350K rwdata, 12772K rodata, 4224K init, 2509K bss, 387656K reserved, 147456K cma-reserved)

注:147456K=144MB,和  cat /proc/pagetypeinfo 对应的上。设备树前面加起来是180MB,对应不上 #####。


5. CMA相关接口

/sys # find ./ -name "*cma*"
./kernel/debug/tracing/events/cma
./kernel/debug/tracing/events/cma/cma_alloc_busy_retry
./kernel/debug/tracing/events/cma/cma_alloc
./kernel/debug/tracing/events/cma/cma_alloc_start
./kernel/debug/tracing/events/cma/cma_release

/sys/firmware/devicetree/base/reserved-memory # ls -l
drwxr-xr-x 2 root root  0 2024-07-02 20:26 cnss_wlan_region
drwxr-xr-x 2 root root  0 2024-07-02 20:26 linux,cma
drwxr-xr-x 2 root root  0 2024-07-02 20:26 mem_dump_region
drwxr-xr-x 2 root root  0 2024-07-02 20:26 pmem_shared_region
drwxr-xr-x 2 root root  0 2024-07-02 20:26 qseecom_region
drwxr-xr-x 2 root root  0 2024-07-02 20:26 qseecom_ta_region
drwxr-xr-x 2 root root  0 2024-07-02 20:26 ramoops@800000000

 

标签:13,region,cma,CMA,内存,shared,root
From: https://www.cnblogs.com/hellokitty2/p/18280545

相关文章

  • 代码随想录算法训练营第四十四天 | 322.零钱兑换 279.完全平方数 139.单词拆分
    322.零钱兑换题目链接文章讲解视频讲解classSolution{public:intcoinChange(vector<int>&coins,intamount){//dp[j]:表示能凑成面额j所需的最少硬币个数vector<int>dp(amount+1,0);//递推公式:dp[j]=min(dp[j-coins[i]......
  • mac的其他内存怎么清理,全方位清理Mac其他内存必备
    对于很多职场朋友来说,一台mac电脑上标配,它的高效性能与优秀的交互体验总能让工作变得更加得心应手,但有时候也会发现,随着时间的推移,Mac运行变得缓慢,处理工作不似最开始的丝滑,那这可能是因为你的mac内存占用过多。那么mac的其他内存怎么清理呢,今天一文带大家搞定mac内存清理。......
  • 第3章 寄存器(内存访问)
    第3章寄存器(内存访问)3.1内存中的字存储CPU中用16位寄存器存储一个字,高8位存放高位字节,低8位存放低位字节。内存单元是字节单元,一个单元存放一个字节,一个字需要使用两个连续的内存单元进行存放,这个字的低位字节存放在低地址单元,高位字节存放在高地址单元问题:0地址......
  • 《C++ Primer》导学系列:第 13 章 - 拷贝控制
    13.1拷贝、赋值与析构函数拷贝控制是C++中类设计的重要组成部分,用于管理对象的复制、赋值和销毁过程。理解并正确实现拷贝控制函数(拷贝构造函数、拷贝赋值运算符和析构函数)对于编写健壮和高效的C++程序至关重要。13.1.1拷贝构造函数拷贝构造函数用于创建对象的副本。它的......
  • 内存管理-11-buddy伙伴子系统-2-Per-CPU页帧缓存
    基于msm-5.4一、概述1.实现背景buddy子系统管理的物理页面,绝大多数都是放在zone::free_area[]中的链表中,少部分放在zone::lowmem_reserve[]中。还有少量页面放在zone::__percpupageset这个每CPU变量中,每种迁移类型也都对应一个链表,但是没有order,都是单页大小的内存块。......
  • 最新版 SteinbergNuendo13.0.41 Win&Mac
    软件介绍2024.6.13官方最新发布WIN版本13.0.41,此版本为VR版本!资源包含6个版本。下载安装一个即可!新版本进行了大量的更新和修复,详情查看以下链接SteinbergNuendo是一款屡获殊荣的影视、游戏和沉浸式环绕声音频后期制作软件Nuendo在对白录音和编辑方面做了重大改进,为你的......
  • 内存管理-11-buddy伙伴子系统-1-初探
    基于msm-5.4一、伙伴系统概述1.简介伙伴系统是物理内存的三大管理机制之一,另外两个是slab缓存和per-cpu页帧缓存。#####管理物理内存实际上就是管理page结构,将page添加到不同链表上进行管理。当用户申请内存的时候,从链表上拿一个page返还给用户,然后用户根据page可以找到对......
  • 汇编语言------内存段
    分段内存模型:将内存划分为几个独立的区域,每个区域称为段,通过段寄存器中的指针来引用。每个段都被用来保存某种特殊的数据。Datasegment:数据段,主要用来保存声明的变量、常量等等。用.data和.bss表示。Codesegment:代码段,主要用来保存指令代码。用.text表示。Stacksegment......
  • CMake
    文章目录CMakeCMake的使用静&动态库库链接嵌套的CMake示例控制流程条件循环预定义宏CMakeCMake是一个项目构建工具,是跨平台的。CMake允许开发者指定整个工程的编译流程,并根据编译平台,自动生成本地化的Makefile和工程文件,最后用户只需make编译即可,可以把CMake当作......
  • P6754 [BalticOI 2013 Day1] Palindrome-Free Numbers
    数据范围一眼数位dp。关键条件为如果一个数字串的一个长度大于 11 的子串也为回文串的话,那么我们也定义这个数字串为回文串。仔细思考发现一旦两个连续的数相同(偶回文)或两个数隔一个数相同(奇回文)都是回文,所以要保证连续三个数不相同,记录前两位即可。注意事项:1.前导零不应为0......