今天接着讲memory的初始化函数arm_memblock_init,在上面完成了memory size的初始化,将整个memory添加以memory type的方式添加到了memory block中,下面是memory reserve部分的初始化,其初始化流程如下:
setup_arch->arm_memblock_init->early_init_fdt_scan_reserved_mem->of_scan_flat_dt->__fdt_scan_reserved_mem->__reserved_mem_reserve_reg->early_init_dt_reserve_memory_arch->memblock_reserve->memblock_reserve_region->memblock_add_range.
首先看arm_memblock_init, 此函数主要在上面已经初始化完成的memory size上完成kernel以及外设的memory reserve工作:
void __init arm_memblock_init(const struct machine_desc *mdesc)
{
/* Register the kernel text, kernel data and initrd with memblock. */
#ifdef CONFIG_XIP_KERNEL
memblock_reserve(__pa(_sdata), _end - _sdata);//调用memblock_reserve reserve从_sdata的物理地址到_end的物理地址的一段内存
#else
memblock_reserve(__pa(_stext), _end - _stext);//调用memblock_reserve reserve从_stext的物理地址到_end的物理地址的一段内存,此处宏一般未定义,所以走下面
#endif
#ifdef CONFIG_BLK_DEV_INITRD
/* FDT scan will populate initrd_start */
if (initrd_start && !phys_initrd_size) {//关于initrd的一些判断
phys_initrd_start = __virt_to_phys(initrd_start);
phys_initrd_size = initrd_end - initrd_start;
}
initrd_start = initrd_end = 0;
if (phys_initrd_size &&
!memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) {
pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",
(u64)phys_initrd_start, phys_initrd_size);
phys_initrd_start = phys_initrd_size = 0;
}
if (phys_initrd_size &&
memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) {
pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n",
(u64)phys_initrd_start, phys_initrd_size);
phys_initrd_start = phys_initrd_size = 0;
}
if (phys_initrd_size) {//如果initrd段没有被reserve,则调用memblock_reserve函数reserve initial ramdisk image区域
memblock_reserve(phys_initrd_start, phys_initrd_size);
/* Now convert initrd to virtual addresses */
initrd_start = __phys_to_virt(phys_initrd_start);
initrd_end = initrd_start + phys_initrd_size;
}
#endif
arm_mm_memblock_reserve();//reserve一段地址用来存放用于进行地址映射的pgd table.
/* reserve any platform specific memblock areas */
if (mdesc->reserve)
mdesc->reserve();
early_init_fdt_scan_reserved_mem();//解析dts的node name为reserved-memory的所有部分进行reserve
/* reserve memory for DMA contiguous allocations */
dma_contiguous_reserve(arm_dma_limit);
/* reserve memory for MT-RAMDUMP */
mrdump_rsvmem();
//memblock_reserve(0x78000000, 0x8000000);
//memblock_reserve(0x72100000, 0x1600000);
//memblock_reserve(0x44640000, 0xE00000);
arm_memblock_steal_permitted = false;
memblock_dump_all();
}
early_init_fdt_scan_reserved_mem:
void __init early_init_fdt_scan_reserved_mem(void)
{
int n;
u64 base, size;
if (!initial_boot_params)//initial_boot_params实际上对应得是fdt的虚拟地址,如果此处为0,则表示没有fdt需要scan,return
return;
/* Reserve the dtb region */
early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
fdt_totalsize(initial_boot_params),
0);//reserve一段设备树文件大小内存用来存放设备树文件</