dts中memreserve和reserved-memory的区别 心已赠人 2023-07-11 11:24 126阅读 0赞 Devicetree 提供了两种方式预留内存: reserved-memory和memreserve memreserve示例 /memreserve/ 0x40000000 0x01000000 reserved-memory示例 reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; ipu_cma@90000000 { compatible = "shared-dma-pool"; reg = <0x90000000 0x4000000>; reusable; status = "okay"; }; **区别1:** 二者在dtc编译时中处理的方法不同, reserved-memory做为device tree node解析到device-tree structure中; memreserve最终会加到dtb文件的memory reserve map, 见下图 ![Center][] **区别2** 二者在内核中的处理方式不同 1 memreserve处理流程 start\_kernel - init/main.c ->setup\_arch - arch/arm/kernel/setup.c ->arm\_memblock\_init - arch/arm/kernel/setup.c ->arm\_dt\_memblock\_reserve - arch/arm/kernel/devtree.c arm\_dt\_memblock\_reserve实现如下 /* Reserve the dtb region */ memblock_reserve(virt_to_phys(initial_boot_params), be32_to_cpu(initial_boot_params->totalsize)); /* * Process the reserve map. This will probably overlap the initrd * and dtb locations which are already reserved, but overlaping * doesn't hurt anything */ reserve_map = ((void*)initial_boot_params) + be32_to_cpu(initial_boot_params->off_mem_rsvmap); while (1) { base = be64_to_cpup(reserve_map++); size = be64_to_cpup(reserve_map++); if (!size) break; memblock_reserve(base, size); } initial\_boot\_params实际指向dtb文件在内存中的位置, 该地址还可以指向其他类型的启动参数 initial\_boot\_params头中的off\_mem\_rsvmap指向一系列的reserve memory(地址, 尺寸)空间, 对于dtb来说, 就是memory reserve map. 2 reserved-memory处理流程 start\_kernel - init/main.c ->setup\_arch - arch/arm/kernel/setup.c ->arm\_memblock\_init - arch/arm/kernel/setup.c ->early\_init\_fdt\_scan\_reserved\_mem - arch/arm/mm/init.c ->\_\_fdt\_scan\_reserved\_mem, - drivers/of/fdt.c ->\_\_reserved\_mem\_reserve\_reg - drivers/of/fdt.c ->early\_init\_dt\_reserve\_memory\_arch - drivers/of/fdt.c ->memblock\_remove - mm/memblock.c ->memblock\_reserve - mm/memblock.c ->fdt\_init\_reserved\_mem reserved-memory有一些可选参数, 比如no-map, 如果使用了no-map, 那么这段区域执行memblock\_remove, 反之执行memblock\_reserve. 在调用完memblock\_reserve后,还会执行fdt\_init\_reserved\_mem void __init fdt_init_reserved_mem(void) { ... if (rmem->size == 0) err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size); if (err == 0) __reserved_mem_init_node(rmem); ... } /** * res_mem_init_node() - call region specific reserved memory init code */ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) { ... for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { reservedmem_of_init_fn initfn = i->data; const char *compat = i->compatible; if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) continue; if (initfn(rmem) == 0) { pr_info("Reserved memory: initialized node %s, compatible id %s\n", rmem->name, compat); return 0; } } return -ENOENT; } 如果reserved-memory下节点的compatible=<shared-dma-pool>, 则这块内存会被用来进行Contiguous Memory Allocator for dma initfn对应drivers/base/dma-contiguous.c下的rmem\_cma\_setup以及drivers/base/dma-coherent.c中的rmem\_dma\_setup, 由于二者的compatible相同,所以前者优先. rmem\_cma\_setup会对这块内存做初始化, 把这块区域加到cma\_areas\[cma\_area\_count\]中 cma\_areas保存着所有的CMA区域, 稍后core\_init\_reserved\_areas会对这个数组进行处理 static int __init cma_init_reserved_areas(void) { int i; for (i = 0; i < cma_area_count; i++) { int ret = cma_activate_area(&cma_areas[i]); if (ret) return ret; } return 0; } core_initcall(cma_init_reserved_areas); cma\_activate\_area把该cma area中的所有pages都改为MIGRATE\_CMA, 并加到MIGRATE\_CMA的free\_list上. **区别3** 由于二者的处理流程不同, 导致memreserve分配的内存, 无法再被操作系统使用; 而reserved-memory内存有可能进入系统CMA, 是否做为CMA, 依赖以下几个条件: 1. compatible 必须为shared-dma-pool 2. 没有定义no-map属性 3. 定义了resuable属性 原文链接:https://blog.csdn.net/kickxxx/article/details/54631535 [Center]: https://img-blog.csdn.net/20170120152706409?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lja3h4eA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
还没有评论,来说两句吧...