跳转至

Memory Layout

1. PureLinux

本文主要介绍alkaid下如何生成可视化dram layout 与 bootargs 内存参数详解(包含mma等size调整方法)

1.1 可视化dram layout实现说明

当前 alkaid project/build_pre_process_config.sh 负责读取Kconfig设置的size,计算dram_layout并生成所需的环境变量/编译选项/加载地址等

1.1.1 核心函数及参数说明

function add_region_to_layout() {
    local module="$1"
    local start_hex="$2"
    local end_hex="$3"
    local size_hex="$4"
    local parent="$5"

    local start_print=$(addr_to_offset "$start_hex")
    local end_print=$(addr_to_offset "$end_hex")
    local size_print="${size_hex:-"-"}"
    local parent_print="${parent:-"-"}"

    printf "%-12s %-18s %-18s %-12s %-12s\n" "$module" "$start_print" "$end_print" "$size_print" "$parent_print" >> "$DRAM_LAYOUT"
}

$1:模块名称

$2:起始地址(cpu base地址,可以是0x100000000 base,也可以是0x20000000 base)

$3:结束地址(cpu base地址,可以是0x100000000 base,也可以是0x20000000 base)

$4:模块大小

$5:父模块名称(如CMA/MMA这种在LX内部reserve的模块,支持不传入地址)

1.1.2 调用时机

alkaid project/build_pre_process_config.sh中,确保所有runtime模块都有调用add_region_to_layout函数进行记录,当前纳入统计的模块有:

add_region_to_layout "CMA" "" "" "$cma_size" "LX"
add_region_to_layout "FB" "" "" "$fb_size" "LX"
add_region_to_layout "LOGO" "$((logo_start_addr + dram_base_addr))" "$((logo_end_addr + dram_base_addr))" "$logo_size" "LX"
add_region_to_layout "FIRMWARES" "" "" "$component_size" "LX"
add_region_to_layout "LX" $lx_addr $lx_end_addr $lx_size
add_region_to_layout "MMA" "" "" "$mma_size" "LX"
add_region_to_layout "MMA" $mma_addr $mma_end_addr $mma_size
add_region_to_layout "IPU"                    $ipu_addr            $ipu_end_addr              $ipu_size
add_region_to_layout "RTOS" $rtos_addr $rtos_end_addr $rtos_size
add_region_to_layout "VMM" $vmm_addr $vmm_end_addr $vmm_size
add_region_to_layout "OPTEE" $optee_addr $optee_end_addr $optee_size
add_region_to_layout "RISCV" $riscv_addr $riscv_end_addr $riscv_size
add_region_to_layout "TFA" $tfa_addr $tfa_end_addr $tfa_size

1.1.3 可视化脚本

project/scripts/dram_layout_graph.py 读取由build_pre_process_config.sh生成dram_layout.txt,生成可视化html

# 依赖plotly库,需在python3环境下运行
python3 scripts/dram_layout_graph.py --input configs/dram_layout.txt --output configs/dram_layout.html

举例如下,cat project/configs/dram_layout.txt内容:

===========================================================================
DRAM: 0x0-0x40000000
Generation time: 2025-12-18 12:03:03
===========================================================================
MODULE       Start              End                Size         Parent
---------------------------------------------------------------------------
CMA          -                  -                  0x400000     LX
FB           -                  -                  0x1CF0000    LX
LOGO         0x3f500000         0x3fd00000         0x800000     LX
LX           0x0                0x3fd00000         0x3FD00000   -
MMA          -                  -                  0x10000000   LX
RISCV        0x3fd00000         0x3ff00000         0x200000     -
TFA          0x3ff00000         0x40000000         0x100000     -

以上例子既包含了地址确定的模块,又包含了地址不确定,但父模块确定的模块,dram_layout_graph.py处理结果如下图示(使用浏览器打开可视化html)

  • 对于地址确定的模块,使用实体色块显示,鼠标悬停后可显示具体的地址信息

    图1-1

  • 对于地址不确定,但父模块确定的模块,仅从父模块中模拟占用一块内存,但位置不具有实际意义,使用阴影色块显示,鼠标悬停后不显示具体的地址信息

    图1-2

  • 可通过点击上方色块实现单独显示或屏蔽某个模块的效果

    图1-3

运行时查看内存的方法

1.图1-1蓝色部分划分给linux,由linux管理,使用情况可以用linux通用命令查看,如:

cat /proc/meminfo
cat /proc/vmallocinfo

2.图1-1绿色条纹部分划分给MMA,由sys管理,使用情况查看:

cat /proc/mi_modules/mi_sys/mi_sys0
cat /proc/mi_modules/mi_sys_mma/mma_heap_name0

1.2 bootargs 内存参数详解

bootargs 是 U-Boot 传递给 Linux 内核的启动参数,其中包含了关键的内存配置信息。以下是一个典型的 bootargs 示例:

bootargs=ubi.mtd=ubia,2048 root=/dev/mtdblock6 rootfstype=squashfs ro init=/linuxrc LX_MEM=0x1000000000,0x80000000 cma=2M mma_heap=mma_heap_name0,miu=0,sz=0x22000000 mma_memblock_remove=1 mma_heap=mma_heap_fb,miu=0,sz=0x4048000 mmap_reserved=fb,miu=0,sz=0x800000,max_start_off=0x7f800000,max_end_off=0x80000000 mtdparts=nand0:1920k@1280k(BOOT),1920k(BOOT_BAK),256k(ENV),256k(ENV1),5m(KERNEL),5m(KERNEL_BACKUP),4m(rootfs),1152k(MISC),109952k(ubia)

1.2.1 内存相关参数说明

参数 含义与作用 对应defconfig配置 如何修改
LX_MEM= Linux 内存配置(内核可用的系统内存空间)
格式: LX_MEM=<基地址>,<大小>(arm64)或 LX_MEM=<大小>(arm32)
示例: LX_MEM=0x1000000000,0x80000000(基地址0x1000000000,大小2GB)
CONFIG_LX_MEM_SIZE 修改 defconfig 中的 CONFIG_LX_MEM_SIZE
cma= CMA(Contiguous Memory Allocator)连续内存区域大小
用于 DMA、Framebuffer、Camera 等需要物理连续内存的设备
格式: cma=<十进制大小>M(本项目脚本只生成带 M 单位的格式)
示例: cma=2Mcma=16M(由脚本从十六进制配置自动转换)
CONFIG_CMA_MEM_SIZE 修改 defconfig 中的 CONFIG_CMA_MEM_SIZE(十六进制)
脚本自动转换为十进制+M单位格式
mma_heap= MMA(Memory Management Allocator)内存堆配置
格式: mma_heap=<名称>,miu=<MIU号>,sz=<大小>
参数说明:
  - 名称:堆标识符(如 mma_heap_name0 主堆、mma_heap_fb 帧缓冲堆)
  - miu:MIU 接口号(通常为0,表示 MIU0)
  - sz:堆大小(十六进制,如 0x22000000 约 544MB)
示例: mma_heap=mma_heap_name0,miu=0,sz=0x22000000
CONFIG_MMA_MEM_SIZE
CONFIG_FB_MEM_SIZE
修改 defconfig 中的对应配置项
miu 和名称由系统自动指定
mma_memblock_remove= MMA 从系统 memblock 中移除已分配的内存
防止 Linux 内核将 MMA 预留的内存分配给其他模块
格式: mma_memblock_remove=<0|1>
参数说明: 0=不移除,1=移除(默认启用)
自动生成 不需要手动修改
mmap_reserved= 预留内存映射区域(用于 LOGO 等固定位置预留内存)
格式: mmap_reserved=<名称>,miu=<MIU号>,sz=<大小>,max_start_off=<起始偏移>,max_end_off=<结束偏移>
参数说明:
  - 名称:预留区域标识(如 fb
  - miu:MIU 接口号(通常为0)
  - sz:预留大小(十六进制)
  - max_start_off:相对于 DRAM 基地址的最大起始偏移(十六进制)
  - max_end_off:相对于 DRAM 基地址的最大结束偏移(十六进制)
偏移计算: 仅 LOGO(CONFIG_LOGO_MEM_SIZE)的偏移由 build_pre_process_config.sh 自动计算,从 lx_size 往下分配;其他区域需手动指定偏移
示例: mmap_reserved=fb,miu=0,sz=0x800000,max_start_off=0x3f500000,max_end_off=0x3fd00000
CONFIG_LOGO_MEM_SIZE 修改 defconfig 中对应配置
LOGO 偏移自动计算,其他需手动指定

bootargs中格式统一约定

  • 地址格式:十六进制,以 0x 前缀开头(如 0x80000000
  • 大小格式:
  • cma=:十进制+M单位(由脚本从十六进制自动转换,如 2M
  • mma_heap=sz:十六进制(如 0x22000000
  • mmap_reserved=sz:十六进制(如 0x800000
  • MIU 号:数字标识,通常为 0(表示 MIU0)

1.2.2 内存布局示例

根据上述 bootargs,内存布局如下(从高地址到低地址):

  ┌─────────────────────────────────────┐
  │ mmap_reserved FB (8MB)              │ ← 0x80000000 (高地址)
  ├─────────────────────────────────────┤
  │ MMA Heap (544MB)                    │
  ├─────────────────────────────────────┤
  │ MMA Heap FB (64MB)                  │
  ├─────────────────────────────────────┤
  │ CMA (2MB)                           │
  ├─────────────────────────────────────┤
  │ Linux System Memory (~1.36GB)       │ ← 0x0 (低地址)
  │ kernel + user space                 │
  └─────────────────────────────────────┘

1.2.3 LX_MEM 与 DRAM 的大小关系

在 defconfig 配置中,pure Linux defconfig 默认CONFIG_LX_MEM_SIZE=CONFIG_DRAM_SIZE

但有些defconfig中CONFIG_LX_MEM_SIZE 可能小于 CONFIG_DRAM_SIZE,比如需要开OPTEE的defconfig,会预留部分区间用于 ARM TrustZone 安全固件,对Linux是不可见的。

1.2.4 修改 bootargs 的方式

修改 defconfig

通过修改项目配置文件中的相关配置项:

CONFIG_LX_MEM_SIZE="0x80000000"
CONFIG_CMA_MEM_SIZE="0x200000"
CONFIG_MMA_MEM_SIZE="0x22000000"
CONFIG_FB_MEM_SIZE="0x4048000"

U-Boot 环境变量

setenv bootargs 'LX_MEM=0x1000000000,0x80000000 cma=2M ...'
saveenv