CMA 连续内存机制与实现详解

CMA 连续内存机制与实现详解

源码路径rk3588/kernel-6.1/mm/cma.ccma.hcma_debug.ccma_sysfs.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 问题背景

DMA、摄像头、显示、VPU 等硬件常要求 物理地址连续 的缓冲区。伙伴分配器在高 order 或碎片化严重时难以提供大块连续物理页。

1.2 CMA 思路

在启动早期 预留 一片物理连续区域:

  • 平时:页作为 MIGRATE_CMA 类型进入 buddy,可被 可迁移 的普通分配使用
  • 驱动需要时:从 CMA 池分配,通过 迁移(compaction) 腾出连续物理块并 pin

兼顾 系统内存利用率驱动连续内存需求

1.3 与 reserved-memory 区别

机制 平时是否进 buddy 用途
memblock reserve 固件/驱动私有,内核不管理
CMA 是(可迁移页) 动态借出,需要时收回

DT 中 linux,cma 与独立 reserved-memory 可并存。


二、实现方式

2.1 初始化

  1. DT / cma= 启动参数指定区域名、大小、对齐
  2. cma_init_reserved_memblock() 在 memblock 阶段 reserve
  3. cma_init_reserved_areas():buddy 初始化后,将区域页标为 MIGRATE_CMA,建立 bitmap 跟踪 CMA 内分配

struct cma 字段:base_pfncountbitmapnameorder_per_bit

2.2 分配:cma_alloc()

1
2
3
4
5
6
7
8
9
struct page *cma_alloc(struct cma *cma, unsigned long count,
unsigned int align, bool no_warn)
{
// bitmap_find_next_zero_area_off 找连续空闲位
bitmap_set(...);
pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, GFP_KERNEL);
// 失败则 cma_clear_bitmap 并重试
}

要点:

  • bitmap 防止重复分配同一段
  • alloc_contig_rangecompaction.c):isolate + migrate 腾出 [pfn, pfn+count)
  • 失败 -EBUSY 时换偏移重试

2.3 释放:cma_release()

清除 bitmap,free_contig_range 将页归还 CMA migratetype 的 buddy。

2.4 驱动 API

API 说明
dma_alloc_from_contiguous DMA 框架封装
cma_alloc / cma_release 内核直接调用
devm_cma_alloc 设备 managed

2.5 与 page_alloc 协作

  • 普通 GFP 不应长期占用 CMA 页;is_migrate_cma() 检查
  • NR_FREE_CMA_PAGES 在 vmstat 中统计
  • 分配 CMA 时可能触发 全局 compact

三、关键数据结构与接口

符号 说明
cma_areas[] 全局 CMA 区域数组
cma_get_base/size/name 查询接口
cma_alloc / cma_release 分配释放
alloc_contig_range 底层连续化(compaction.c)

四、RK3588 平台说明

4.1 典型配置

  • defconfig CONFIG_CMA=y
  • DT reserved-memorylinux,cma 默认池
  • 显示/ISP/VPU 可能还有 命名 CMA 或固定 reserve

4.2 编解码场景

  • drm_gem_cmavb2 dma-contig 等从 CMA 取 buffer
  • 多路编码同时分配大块 → CmaFree 下降、compact 频繁 → 延迟抖动
  • 排查:/proc/meminfoCmaTotal/CmaAllocated/CmaFree

4.3 失败处理

  • 增大 DT CMA 或 cma=512M 等启动参数
  • 减少用户态 hoarding dmabuf
  • 检查是否有驱动泄漏未 cma_release

五、调试与观测

手段 说明
/proc/meminfo Cma* 行
CONFIG_CMA_DEBUGFS debugfs 位图
CONFIG_CMA_SYSFS /sys/kernel/mm/cma/
trace trace/events/cma.h

附录:源码索引

主题 文件 约略行号
cma_alloc cma.c 438
cma 初始化 cma.c 搜索 init_reserved

文章互动

阅读 --

留言

0 条留言

正在加载留言…