内存管理(六):系统映射

通过memblock已经有了内存布局的信息,接下来就要完成内存的映射。映射的过程位于paging_init函数中

1.	/* 
2.	 * paging_init() sets up the page tables, initialises the zone memory 
3.	 * maps and sets up the zero page. 
4.	 */  
5.	void __init paging_init(void)  
6.	{  
7.	    phys_addr_t pgd_phys = early_pgtable_alloc();  
8.	    pgd_t *pgd = pgd_set_fixmap(pgd_phys);  
9.	  
10.	    map_kernel(pgd);  
11.	    map_mem(pgd);  
12.	  
13.	    /* 
14.	     * We want to reuse the original swapper_pg_dir so we don't have to 
15.	     * communicate the new address to non-coherent secondaries in 
16.	     * secondary_entry, and so cpu_switch_mm can generate the address with 
17.	     * adrp+add rather than a load from some global variable. 
18.	     * 
19.	     * To do this we need to go via a temporary pgd. 
20.	     */  
21.	    cpu_replace_ttbr1(__va(pgd_phys));  
22.	    memcpy(swapper_pg_dir, pgd, PGD_SIZE);  
23.	    cpu_replace_ttbr1(lm_alias(swapper_pg_dir));  
24.	  
25.	    pgd_clear_fixmap();  
26.	    memblock_free(pgd_phys, PAGE_SIZE);  
27.	  
28.	    /* 
29.	     * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd 
30.	     * allocated with it. 
31.	     */  
32.	    memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,  
33.	              SWAPPER_DIR_SIZE - PAGE_SIZE);  
34.	}  

映射的过程如下图所示:
内存管理(六):系统映射_第1张图片
在map_kernel和map_mem中,最终都会通过__create_pgd_mapping将指定地址和大小进行一一映射,流程如下。
内存管理(六):系统映射_第2张图片
其实在dtb中映射中,最终也会走到__create_pgd_mapping,映射kernel和mem和映射dtb的区别在于,此时可以通过memblock模块进行物理内存的分配了,并且,这里我们又看到了fixmap的使用pte_set_fixmap,用来获取刚刚分配的物理地址对应的虚拟地址,然后对这个page清零,之后再解除这段映射。在系统映射的时候我们会看到很多类似的步骤,通过fixmap建立刚刚分配PGD/PMD/PTE对应的映射,使用完毕之后再解除映

35.	static phys_addr_t __init early_pgtable_alloc(void)  
36.	{  
37.	    phys_addr_t phys;  
38.	    void *ptr;  
39.	  /*****1****/
40.	    phys = memblock_alloc(PAGE_SIZE, PAGE_SIZE);  
41.	  
42.	    /* 
43.	     * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE 
44.	     * slot will be free, so we can (ab)use the FIX_PTE slot to initialise 
45.	     * any level of table. 
46.	     */  
47.	/*****2*****
48.	    ptr = pte_set_fixmap(phys);  
49.	  /******3****/
50.	    memset(ptr, 0, PAGE_SIZE);  
51.	  
52.	    /* 
53.	     * Implicit barriers also ensure the zeroed page is visible to the page 
54.	     * table walker 
55.	     */  
56.	/*****4*****/
57.	    pte_clear_fixmap();  
58.	  
59.	    return phys;  
60.	}  
  • (1)分配4k大小区域
  • (2)利用fixmap区域建立与刚分配的一块物理地址的映射
  • (3)对分配的区域清零
  • (4)解除映射
    内存管理(六):系统映射_第3张图片

你可能感兴趣的:(Linux内存管理)