Rockchip · AI & Linux Hub

Linux & boot

Rockchip Linux CMA: Driver Framework, Reserved Memory and Debugging

Complete CMA configuration, DTS, device-specific regions, debugfs nodes, framework diagram and boot logs.

· ArmSoM Editorial · Rockchip source documentation · 8 min read

ArmSoM applicability and source

Platform reference for adapting ArmSoM, translated from Chinese V1.1.0. Source scope: RK3588 / RK3568 / RK3399 / RK3288 / RK3368 / RV1126 / PX30, Linux 4.4 / 4.19 / 5.10. No English PDF was supplied; English, Russian and German fully translate the Chinese source. German reuses the English article’s image URLs. No specific ArmSoM board, SDK/BSP or driver combination has been confirmed or hardware-tested. Check the actual SoC, board memory layout, SDK/BSP, kernel configuration and driver implementation. Code, addresses, logs and measurements are source examples, not ArmSoM test results.

Editorial notes · ArmSoM Docs · Rockchip Linux

The sole framework diagram comes from Chinese PDF page 4; no English original exists.

Source SoC Source kernel
RK3588 / RK3568 / RK3399 / RK3288 / RK3368 / RV1126 / PX30 Linux 4.4 / 4.19 / 5.10

1. CMA driver framework

CMA driver framework (original Chinese PDF, page 4)

CMA driver framework (original Chinese PDF, page 4)

The CMA driver has three main parts:

  1. size@address

Parameters can be supplied in three ways, in the source BSP priority order DTS > CMDLINE > DEFCONFIG. A valid DTS node determines the final configuration; otherwise the driver checks for cma=size@base on the command line, then the four macro definitions mentioned in the source defconfig discussion.

  1. reserved cma_areas[]

DTS can configure multiple CMA nodes; cmdline and defconfig can define only the default node. All reserved regions are stored in the global cma_areas[].

  1. active cma_area

Parameter parsing and memory reservation finish during kernel setup_arch. Activation is called through core_initcall, before all drivers. It mainly creates the CMA area bitmap and adds CMA pages to the buddy system.

2. Allocating reserved memory

2.1 Method 1: reserve 16MByte through menuconfig

CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=16
CONFIG_CMA_SIZE_SEL_MBYTES=y

2.2 Method 2: the DTS reserved-memory node

See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt.

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x1000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };
};

3. Allocating device-specific memory

The above methods allocate a system-shared memory region. Repeated allocations and frees by multiple devices can fragment it. Some peripherals need large contiguous CMA blocks and may malfunction if fragmentation prevents allocation. Allocate a separate region for such devices.

3.1 Method 1: a separate region that the system can borrow

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    cma_region: region@88000000 {
        compatible = "shared-dma-pool";
        reusable;
        reg = <0x88000000 0x1800000>;
    };
};

Assign this region to a specific device through of_reserved_mem_device_init.

#include <linux/of_reserved_mem.h>
static inline int of_reserved_mem_device_init(struct device *dev)
{
    return of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0);
}

3.2 Method 2: a memblock region

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };
};

Inspect the allocation through /sys/kernel/debug/memblock/reserved.

The displayed memblock ranges have been merged and consolidated.

This allocation is not managed by kernel page management. The source says users must create a “page scale list” as needed; that term is retained pending clarification.

console:/sys/kernel/debug/cma # cat /sys/kernel/debug/memblock/reserved
    0: 0x60004000..0x60007fff
    1: 0x60100000..0x61404a07
    2: 0x62e00000..0x62eeffff
    3: 0x68300000..0x6830d07f
...

4. Debugging reserved memory

4.1 CMA debug configuration switches

CONFIG_CMA_DEBUGFS=y #打开调试文件节点
CONFIG_CMA_DEBUG=y #打印CMA日志信息

Configuration notes: CONFIG_CMA_DEBUGFS=y creates debug nodes; CONFIG_CMA_DEBUG=y prints CMA logs.

4.2 CMA debug nodes

console:/sys/kernel/debug/cma # ls
cma-region@8800 cma-reserved
console:/sys/kernel/debug/cma/cma-reserved # ls
alloc bitmap free order_per_bit used
base_pfn count maxchunk

alloc: allocate memory from the current CMA region, in pages.

bitmap: allocation state of each page; 1 means allocated, 0 means unallocated.

free: release memory in the current CMA region, in pages.

order_per_bit: the order of the number of pages represented by one bit.

used: number of currently allocated pages.

base_pfn: page frame number of the first page of the current CMA region.

maxchunk: largest number of contiguous free pages in the current CMA region.

5. Memory reservation messages during boot

[ 0.000000] Booting Linux on physical CPU 0xf00
[ 0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c5387d
[ 0.000000] CPU: div instructions available: patching division code
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[ 0.000000] OF: fdt: Machine model: Rockchip RK3126 bnd-d708 board
[ 0.000000] earlycon: uart8250 at MMIO32 0x20068000 (options '')
[ 0.000000] bootconsole [uart8250] enabled
[ 0.000000] Memory policy: Data cache writealloc
[ 0.000000] Reserved memory: created CMA memory pool at 0x88000000, size 24 MiB
[ 0.000000] OF: reserved mem: initialized node region@88000000, compatible id shared-dma-pool
[ 0.000000] cma: Reserved 16 MiB at 0x9f000000
[ 0.000000] On node 0 totalpages: 258560
[ 0.000000] Normal zone: 1728 pages used for memmap
[ 0.000000] Normal zone: 0 pages reserved
[ 0.000000] Normal zone: 193024 pages, LIFO batch:63
[ 0.000000] HighMem zone: 65536 pages, LIFO batch:15
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv65535.65535 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] psci: SMC Calling Convention v1.0
[ 0.000000] percpu: Embedded 17 pages/cpu s38924 r8192 d22516 u69632
[ 0.000000] pcpu-alloc: s38924 r8192 d22516 u69632 alloc=17*4096
[ 0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 256832
[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Memory: 960940K/1034240K available (11264K kernel code, 985K rwdata, 3180K rodata, 1024K init, 2104K bss, 32340K reserved, 40960K cma-reserved, 245024K highmem)
...

Successful allocation of the first CMA region:

[ 0.000000] Reserved memory: created CMA memory pool at 0x88000000, size 24 MiB
[ 0.000000] OF: reserved mem: initialized node region@88000000, compatible id shared-dma-pool

Successful allocation of the second CMA region (system default):

[ 0.000000] cma: Reserved 16 MiB at 0x9f000000

Explore this topic → · Learning paths →