asmlinkage __visible void __init start_kernel(void){/* 设置特定架构的信息
* 同时初始化memblock */setup_arch(&command_line);mm_init_cpumask(&init_mm);setup_per_cpu_areas();/* 初始化内存结点和内段区域 */build_all_zonelists(NULL,NULL);page_alloc_init();/*
* These use large bootmem allocations and must precede
* mem_init();
* kmem_cache_init();
*/mm_init();kmem_cache_init_late();kmemleak_init();setup_per_cpu_pageset();rest_init();}
struct memblock_type
{unsignedlong cnt;/* number of regions */unsignedlong max;/* size of the allocated array */
phys_addr_t total_size;/* size of all regions */struct memblock_region *regions;};
/* Definition of memblock flags. */enum{
MEMBLOCK_NONE =0x0,/* No special request */
MEMBLOCK_HOTPLUG =0x1,/* hotpluggable region */
MEMBLOCK_MIRROR =0x2,/* mirrored region */
MEMBLOCK_NOMAP =0x4,/* don't add to kernel direct mapping */};
void __init setup_arch(char**cmdline_p){/*
* Need to conclude brk, before memblock_x86_fill()
* it could use memblock_find_in_range, could overlap with
* brk area.
*/reserve_brk();cleanup_highmap();memblock_set_current_limit(ISA_END_ADDRESS);memblock_x86_fill();}// 内核建立内核页表需要扩展__brk, 而扩展后的brk就立即被声明为已分配. 这项工作是由reserve_brk通过调用memblock_reserve完成的,// 而其实并不是正真通过memblock分配的, 因为此时memblock还没有完成初始化staticvoid __init reserve_brk(void){if(_brk_end > _brk_start)memblock_reserve(__pa_symbol(_brk_start),
_brk_end - _brk_start);/* Mark brk area as locked down and no longer taking any
new allocations */
_brk_start =0;}// 设置完__brk后, 可以看到,setup_arch()函数通过memblock_x86_fill(),依据e820中的信息来初始化memblock.void __init memblock_x86_fill(void){int i;
u64 end;/*
* EFI may have more than 128 entries
* We are safe to enable resizing, beause memblock_x86_fill()
* is rather later for x86
*/memblock_allow_resize();for(i =0; i < e820.nr_map; i++){struct e820entry *ei =&e820.map[i];
end = ei->addr + ei->size;if(end !=(resource_size_t)end)continue;if(ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)continue;memblock_add(ei->addr, ei->size);}/* throw away partial pages */memblock_trim_memory(PAGE_SIZE);memblock_dump_all();}
arm下
void __init setup_arch(char**cmdline_p){arm_memblock_init(mdesc);}// void __init arm_memblock_init(conststruct machine_desc *mdesc){/* Register the kernel text, kernel data and initrd with memblock. */#ifdef CONFIG_XIP_KERNELmemblock_reserve(__pa(_sdata), _end - _sdata);#elsememblock_reserve(__pa(_stext), _end - _stext);#endif#ifdef CONFIG_BLK_DEV_INITRD/* FDT scan will populate initrd_start */if(initrd_start &&!phys_initrd_size){
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){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;}#endifarm_mm_memblock_reserve();/* reserve any platform specific memblock areas */if(mdesc->reserve)
mdesc->reserve();early_init_fdt_reserve_self();early_init_fdt_scan_reserved_mem();/* reserve memory for DMA contiguous allocations */dma_contiguous_reserve(arm_dma_limit);
arm_memblock_steal_permitted = false;memblock_dump_all();}