一 mm_init
1.0 mm_init
定义在init/main.c中
static void __init mm_init(void)
{
/*
* page_cgroup requires contiguous pages,
* bigger than MAX_ORDER unless SPARSEMEM.
*/
page_cgroup_init_flatmem(); // mem_cgroup_disabled为true,直接返回了
mem_init(); // 从memboot分配器转化为伙伴系统分配器
kmem_cache_init(); 初始化kmem_cache和kmalloc_caches,使能slab内存分配器
percpu_init_late(); // 每cpu变量
pgtable_cache_init(); // arm64中 #define pgtable_cache_init() do { } while (0)
vmalloc_init();
}
1.1 mem_init
void __init mem_init(void)
{
unsigned long reserved_pages, free_pages;
struct memblock_region *reg;
arm64_swiotlb_init(); // 初始化software IO TLB,用于DMA API
max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; // max_pfn是物理内存的最大页帧号,PHYS_PFN_OFFSET是物理内存的起始地址的页帧号 // 最高内存页指针减去最低内存页指针,所以max_mapnr存放的是系统的内存页数
#ifndef CONFIG_SPARSEMEM_VMEMMAP
/* this will put all unused low memory onto the freelists */
free_unused_memmap();
#endif
totalram_pages += free_all_bootmem(); // 释放空闲的页到伙伴系统分配器
reserved_pages = free_pages = 0;
for_each_memblock(memory, reg) { // 遍历memblock.memory,统计空闲的页和保留的页
unsigned int pfn1, pfn2;
struct page *page, *end;
pfn1 = __phys_to_pfn(reg->base);
pfn2 = pfn1 + __phys_to_pfn(reg->size);
page = pfn_to_page(pfn1);
end = pfn_to_page(pfn2 - 1) + 1;
do {
if (PageReserved(page))
reserved_pages++;
else if (!page_count(page))
free_pages++;
page++;
} while (page < end);
}