添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
威武的蘑菇  ·  Apache Hadoop 3.4.1 – ...·  22 小时前    · 
乖乖的钱包  ·  win32ui vs wxPy ...·  昨天    · 
老实的鸵鸟  ·  Computer memory - ...·  3 天前    · 
勤奋的雪糕  ·  RAM vs ROM vs Cache ...·  3 天前    · 
想表白的面包  ·  Memory Access Error ...·  2 周前    · 
爱吹牛的青蛙  ·  2. Deblur応用: ...·  1 月前    · 
私奔的柳树  ·  Linux ...·  1 月前    · 
踢足球的卡布奇诺  ·  Solved: Exceptions ...·  2 月前    · 
健身的苦瓜  ·  [dedicated server] ...·  2 月前    · 


http://blog.csdn.net/kickxxx/article/details/54631535


Devicetree 提供了两种方式预留内存: reserved-memory和memreserve


memreserve示例

  1. /memreserve/ 0x40000000 0x01000000
/memreserve/ 0x40000000 0x01000000

reserved-memory示例

  1. reserved-memory {
  2. #address-cells = <1>;
  3. #size-cells = <1>;
  4. ranges;
  5. ipu_cma@90000000 {
  6. compatible = "shared-dma-pool" ;
  7. reg = <0x90000000 0x4000000>;
  8. reusable;
  9. status = "okay" ;
  10. };
    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,

见下图


区别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实现如下

  1. memblock_reserve(virt_to_phys(initial_boot_params),
  2. be32_to_cpu(initial_boot_params->totalsize));
  3. reserve_map = (( void *)initial_boot_params) +
  4. be32_to_cpu(initial_boot_params->off_mem_rsvmap);
  5. while (1) {
  6. base = be64_to_cpup(reserve_map++);
  7. size = be64_to_cpup(reserve_map++);
  8. if (!size)
  9. break ;
  10. memblock_reserve(base, size);
  11. }
    /* 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

  1. void __init fdt_init_reserved_mem( void )
  2. {
  3. ...
  4. if (rmem->size == 0)
  5. err = __reserved_mem_alloc_size(node, rmem->name,
  6. &rmem->base, &rmem->size);
  7. if (err == 0)
  8. __reserved_mem_init_node(rmem);
  9. ...
  10. }
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);

  1. static int __init __reserved_mem_init_node( struct reserved_mem *rmem)
  2. {
  3. ...
  4. for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) {
  5. reservedmem_of_init_fn initfn = i->data;
  6. const char *compat = i->compatible;
  7. if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
  8. continue ;
  9. if (initfn(rmem) == 0) {
  10. pr_info( "Reserved memory: initialized node %s, compatible id %s\n" ,
  11. rmem->name, compat);
  12. return 0;
  13. }
  14. }
  15. return -ENOENT;
  16. }
/** 
 * 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会对这个数组进行处理

  1. static int __init cma_init_reserved_areas( void )
  2. {
  3. int i;
  4. for (i = 0; i < cma_area_count; i++) {
  5. int ret = cma_activate_area(&cma_areas[i]);
  6. if (ret)
  7. return ret;
  8. }
  9. return 0;
  10. }
  11. core_initcall(cma_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属性


版权声明:本文为CSDN博主「prike」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接: https://blog.csdn.net/prike/article/details/79524117