在閱讀玩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會變成如下狀態: