static inline pte_t *get_one_pte_map_nested(struct mm_struct *mm, unsigned long addr) { pgd_t * pgd; pmd_t * pmd; pte_t * pte = NULL; pgd = pgd_offset(mm, addr); if (pgd_none(*pgd)) goto end; if (pgd_bad(*pgd)) { pgd_ERROR(*pgd); pgd_clear(pgd); goto end; } pmd = pmd_offset(pgd, addr); if (pmd_none(*pmd)) goto end; if (pmd_bad(*pmd)) { pmd_ERROR(*pmd); pmd_clear(pmd); goto end; } pte = pte_offset_map_nested(pmd, addr); if (pte_none(*pte)) { pte_unmap_nested(pte); pte = NULL; } end: return pte; }
/* * need to get a 16k page for level 1 */ pgd_t *get_pgd_slow(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; unsigned long flags; new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2); if (!new_pgd) goto no_pgd; memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); /* * Copy over the kernel and IO PGD entries */ init_pgd = pgd_offset_k(0); pgd_list_lock(flags); memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); pgd_list_add(new_pgd); pgd_list_unlock(flags); clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); if (!vectors_high()) { #ifdef CONFIG_ARM_FCSE /* FCSE does not work without high vectors. */ BUG(); #endif /* CONFIG_ARM_FCSE */ /* * On ARM, first page must always be allocated since it * contains the machine vectors. */ new_pmd = pmd_alloc(mm, new_pgd, 0); if (!new_pmd) goto no_pmd; new_pte = pte_alloc_map(mm, new_pmd, 0); if (!new_pte) goto no_pte; init_pmd = pmd_offset(init_pgd, 0); init_pte = pte_offset_map_nested(init_pmd, 0); set_pte_ext(new_pte, *init_pte, 0); pte_unmap_nested(init_pte); pte_unmap(new_pte); } return new_pgd; no_pte: pmd_free(mm, new_pmd); no_pmd: free_pages((unsigned long)new_pgd, 2); no_pgd: return NULL; }
/* * get_pgd_slow:申请一个pgd项 * notice:一个pgd占用4个页框,每一个pgt项大小为8字节 */ pgd_t *get_pgd_slow(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; /*pgd占用四个页框*/ new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2); if (!new_pgd) goto no_pgd; memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); /* * 复制内核与I/O PGD entries */ init_pgd = pgd_offset_k(0); memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); if (!vectors_high()) { /* * On ARM, first page must always be allocated since it * contains the machine vectors. */ new_pmd = pmd_alloc(mm, new_pgd, 0); if (!new_pmd) goto no_pmd; /*返回pmd的第0项页表项,因为第0项用于映射中断向量*/ new_pte = pte_alloc_map(mm, new_pmd, 0); if (!new_pte) goto no_pte; /*返回中断向量的页表项,中断向量位于低地址空间时(0地址开始处)*/ init_pmd = pmd_offset(init_pgd, 0); init_pte = pte_offset_map_nested(init_pmd, 0); /*给新的页表项映射中断向量的页表项*/ set_pte_ext(new_pte, *init_pte, 0); pte_unmap_nested(init_pte); /*取消new_pte的高端内存的页表映射*/ pte_unmap(new_pte); } return new_pgd; no_pte: pmd_free(mm, new_pmd); no_pmd: free_pages((unsigned long)new_pgd, 2); no_pgd: return NULL; }
/* * need to get a 16k page for level 1 */ pgd_t *get_pgd_slow(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2); if (!new_pgd) goto no_pgd; memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); /* * Copy over the kernel and IO PGD entries */ init_pgd = pgd_offset_k(0); memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); if (!vectors_high()) { /* * On ARM, first page must always be allocated since it * contains the machine vectors. */ new_pmd = pmd_alloc(mm, new_pgd, 0); if (!new_pmd) goto no_pmd; new_pte = pte_alloc_map(mm, new_pmd, 0); if (!new_pte) goto no_pte; init_pmd = pmd_offset(init_pgd, 0); init_pte = pte_offset_map_nested(init_pmd, 0); set_pte_ext(new_pte, *init_pte, 0); pte_unmap_nested(init_pte); pte_unmap(new_pte); } return new_pgd; no_pte: pmd_free(mm, new_pmd); no_pmd: free_pages((unsigned long)new_pgd, 2); no_pgd: return NULL; }
/* * need to get a 16k page for level 1 */ pgd_t *get_pgd_slow(struct mm_struct *mm) { pgd_t *new_pgd, *init_pgd; pmd_t *new_pmd, *init_pmd; pte_t *new_pte, *init_pte; new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2); if (!new_pgd) goto no_pgd; memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); /* * Copy over the kernel and IO PGD entries */ //#define pgd_offset_k(addr) pgd_offset(&init_mm, addr) //其实就是要拷贝内核空间的页表项... init_pgd = pgd_offset_k(0); //拷贝内核空间的pgd表项到新创建的pgd表项 memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); //把Dcache行的数据写回到主存,并清除cache行的脏标记. //参数:主存的物理地址,(确定cache行) 需要写回的长度... clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); //异常向量表是在高端地址或是在低端地址... if (!vectors_high()) { //如果是在低端地址.那么异常向量表在第一页.. /* * On ARM, first page must always be allocated since it * contains the machine vectors. */ //该函数是在new_pgd指定的PGD页表上找到地址0对应的表项,然后分配一个页. //接着填充PGD的页表项(PMD). //哦,好像略过了PUD了、对于ARM来说PMD也是直接返回pgd. new_pmd = pmd_alloc(mm, new_pgd, 0); if (!new_pmd) goto no_pmd; //如果为空则分配一个页面,然后设置PGD的页表项. new_pte = pte_alloc_map(mm, new_pmd, 0); if (!new_pte) goto no_pte; //init_pgd就是init进程的页表,这里得到地址0的PGD页表的表项(PMD) init_pmd = pmd_offset(init_pgd, 0); //根据init_pmd,得到了PMD页表,然后根据0地址得到了PMD的表项(PTE) init_pte = pte_offset_map_nested(init_pmd, 0); //new_pte指定了要存放PTE的地址,init_pte就是PTE的值。 set_pte_ext(new_pte, *init_pte, 0); pte_unmap_nested(init_pte); pte_unmap(new_pte); } return new_pgd; no_pte: pmd_free(mm, new_pmd); no_pmd: free_pages((unsigned long)new_pgd, 2); no_pgd: return NULL; }