/* * Build-time sanity checks on the kernel image and module * area mappings. (these are purely build-time and produce no code) */BUILD_BUG_ON(MODULES_VADDR<__START_KERNEL_map);BUILD_BUG_ON(MODULES_VADDR-__START_KERNEL_map<KERNEL_IMAGE_SIZE);BUILD_BUG_ON(MODULES_LEN+KERNEL_IMAGE_SIZE>2*PUD_SIZE);BUILD_BUG_ON((__START_KERNEL_map&~PMD_MASK)!=0);BUILD_BUG_ON((MODULES_VADDR&~PMD_MASK)!=0);BUILD_BUG_ON(!(MODULES_VADDR>__START_KERNEL));BUILD_BUG_ON(!(((MODULES_END-1)&PGDIR_MASK)==(__START_KERNEL&PGDIR_MASK)));BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses)<=MODULES_END);
/* Wipe all early page tables except for the kernel symbol map */staticvoid__initreset_early_page_tables(void){unsignedlongi;for(i=0;i<PTRS_PER_PGD-1;i++)early_level4_pgt[i].pgd=0;next_early_pgt=0;write_cr3(__pa(early_level4_pgt));}/* Kill off the identity-map trampoline */reset_early_page_tables();
注意这里有一个__pa(early_level4_pgt),我们来看一下__pa的定义:
123456789101112
staticinlineunsignedlong__phys_addr_nodebug(unsignedlongx){unsignedlongy=x-__START_KERNEL_map;/* use the carry flag to determine if x was < __START_KERNEL_map */x=y+((x>y)?phys_base:(__START_KERNEL_map-PAGE_OFFSET));returnx;}#define __phys_addr(x) __phys_addr_nodebug(x)#define __pa(x) __phys_addr((unsigned long)(x))
之后调用clear_bss,即将bss中的内容清零:
12345678910
/* Don't add a printk in there. printk relies on the PDA which is not initialized yet. */staticvoid__initclear_bss(void){memset(__bss_start,0,(unsignedlong)__bss_stop-(unsignedlong)__bss_start);}/* clear bss before set_intr_gate with early_idt_handler */clear_bss();
/* * The head.S code sets up the kernel high mapping: * * from __START_KERNEL_map to __START_KERNEL_map + size (== _end-_text) * * phys_base holds the negative offset to the kernel, which is added * to the compile time generated pmds. This results in invalid pmds up * to the point where we hit the physaddr 0 mapping. * * We limit the mappings to the region from _text to _brk_end. _brk_end * is rounded up to the 2MB boundary. This catches the invalid pmds as * well, as they are located before _text: */void__initcleanup_highmap(void){unsignedlongvaddr=__START_KERNEL_map;unsignedlongvaddr_end=__START_KERNEL_map+KERNEL_IMAGE_SIZE;unsignedlongend=roundup((unsignedlong)_brk_end,PMD_SIZE)-1;pmd_t*pmd=level2_kernel_pgt;/* * Native path, max_pfn_mapped is not set yet. * Xen has valid max_pfn_mapped set in * arch/x86/xen/mmu.c:xen_setup_kernel_pagetable(). */if(max_pfn_mapped)vaddr_end=__START_KERNEL_map+(max_pfn_mapped<<PAGE_SHIFT);for(;vaddr+PMD_SIZE-1<vaddr_end;pmd++,vaddr+=PMD_SIZE){if(pmd_none(*pmd))continue;if(vaddr<(unsignedlong)_text||vaddr>end)set_pmd(pmd,__pmd(0));}}
void__initinit_mem_mapping(void){...end=max_pfn<<PAGE_SHIFT;/* the ISA range is always mapped regardless of memory holes */init_memory_mapping(0,ISA_END_ADDRESS);memory_map_top_down(ISA_END_ADDRESS,end);if(max_pfn>max_low_pfn){/* can we preseve max_low_pfn ?*/max_low_pfn=max_pfn;}load_cr3(swapper_pg_dir);__flush_tlb_all();early_memtest(0,max_pfn_mapped<<PAGE_SHIFT);}
这里面虽然代码少,但是信息量还是蛮大的,我们一个一个来看。
首先是init_memory_mapping:
1234567891011121314151617181920212223242526
/* * Setup the direct mapping of the physical memory at PAGE_OFFSET. * This runs before bootmem is initialized and gets pages directly from * the physical memory. To access them they are temporarily mapped. */unsignedlong__init_refokinit_memory_mapping(unsignedlongstart,unsignedlongend){structmap_rangemr[NR_RANGE_MR];unsignedlongret=0;intnr_range,i;pr_info("init_memory_mapping: [mem %#010lx-%#010lx]\n",start,end-1);memset(mr,0,sizeof(mr));nr_range=split_mem_range(mr,0,start,end);for(i=0;i<nr_range;i++)ret=kernel_physical_mapping_init(mr[i].start,mr[i].end,mr[i].page_size_mask);add_pfn_range_mapped(start>>PAGE_SHIFT,ret>>PAGE_SHIFT);returnret>>PAGE_SHIFT;}
NEXT_PAGE(init_level4_pgt).quadlevel3_ident_pgt-__START_KERNEL_map+_KERNPG_TABLE.orginit_level4_pgt+L4_PAGE_OFFSET*8,0.quadlevel3_ident_pgt-__START_KERNEL_map+_KERNPG_TABLE.orginit_level4_pgt+L4_START_KERNEL*8,0/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */.quadlevel3_kernel_pgt-__START_KERNEL_map+_PAGE_TABLENEXT_PAGE(level3_ident_pgt).quadlevel2_ident_pgt-__START_KERNEL_map+_KERNPG_TABLE.fill511,8,0NEXT_PAGE(level2_ident_pgt)/* Since I easily can, map the first 1G. * Don't set NX because code runs from these pages. */PMDS(0,__PAGE_KERNEL_IDENT_LARGE_EXEC,PTRS_PER_PMD)