在阅读玩memory初始化的大部分代码之后,突然发现一个问题:在log中发现memory type的遍历过程中发现memory type cnt的值从之前初始化的一个变成了7个,但是搜遍所有的代码也没有发现具体在哪里初始化的这个值,也就是说在reserve type region增加的过程中如何做到memory type region也同时增加的呢?
将初始化的代码又撸过一遍之后终于在reserve代码中找到了一些端倪:
__fdt_scan_reserved_mem->__reserved_mem_reserve_reg->early_init_dt_reserve_memory_arch:
early_init_dt_reserve_memory_arch的第三个参数nomap为此问题的关键点:
nomap的官方解释是当此reserve memory节点不需要映射时会设置此属性,通过分析后可以理解为,当reserve的memory为单独一块或者几块连在一起时地址最小的那一块需要设置nomap。
如上图中ABCD均为reserve memory。其中A和B两块reserve memory就需要nomap设置,而nomap的设置和下面问题至关重要。
看代码:
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
phys_addr_t size, bool nomap)
{
if (nomap)
return memblock_remove(base, size);
return memblock_reserve(base, size);
}
上面代码中当nomap设置之后,可以执行memblock_remove的操作,
memblock_remove->memblock_remove_range:
int __init_memblock memblock_remove_range(struct memblock_type *type,
phys_addr_t base, phys_addr_t size)
{
int start_rgn, end_rgn;
int i, ret;
ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);------------------------(1)
if (ret)
return ret;
for (i = end_rgn - 1; i >= start_rgn; i--)
memblock_remove_region(type, i);---------------------------(2)
return 0;
}
(1)memblock_isolate_range负责将需要reserve的memory从memory type中分离出来,如下图:
比如一整块内存,我需要reserve中间这一块,memblock_isolate_range会将这块memory分成三块,此时memory type region个数为3,其他在已经有reserve的内存上继续reserve的道理以此类推。
(2)memblock_remove_region将一分为三的三块内存中需要reserve的一块从memory type中remove掉,同时memory type region的个数减1,这样就达到了在reserve一块内存的同时,memory type region也增加1变成2个,待reserve操作完成之后,reserve memory region个数加1,memory会变成如下状态: