您的位置:首页 > 运维架构 > Linux

Linux 内核页表初始化

2018-02-07 10:31 411 查看
前面我们讨论了页描述符对象分配,以及初始化。接下来我们再来了解内核页表建立初始化处理。针对ARM64进行。
start_kernel --> setup_arch --> paging_init()
void __init paging_init(void){ phys_addr_t pgd_phys = early_pgtable_alloc();  分配页全局目录表地址
 pgd_t *pgd = pgd_set_fixmap(pgd_phys);
 map_kernel(pgd); 创建内核空间映射
 map_mem(pgd); 对其他的一些bank块进行映射。
下面就是一些针对pgd进行设置。
 /*  * We want to reuse the original swapper_pg_dir so we don't have to  * communicate the new address to non-coherent secondaries in  * secondary_entry, and so cpu_switch_mm can generate the address with  * adrp+add rather than a load from some global variable.  *  * To do this we need to go via a temporary pgd.  */ cpu_replace_ttbr1(__va(pgd_phys)); memcpy(swapper_pg_dir, pgd, PAGE_SIZE); cpu_replace_ttbr1(swapper_pg_dir);
 pgd_clear_fixmap(); memblock_free(pgd_phys, PAGE_SIZE);
 /*  * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd  * allocated with it.  */ memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,        SWAPPER_DIR_SIZE - PAGE_SIZE);}
static void __init map_kernel(pgd_t *pgd){ static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data;
 map_kernel_segment(pgd, _text, _etext, PAGE_KERNEL_EXEC, &vmlinux_text); map_kernel_segment(pgd, __start_rodata, __init_begin, PAGE_KERNEL, &vmlinux_rodata); map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,      &vmlinux_init); map_kernel_segment(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
 if (!pgd_val(*pgd_offset_raw(pgd, FIXADDR_START))) {  /*   * The fixmap falls in a separate pgd to the kernel, and doesn't   * live in the carveout for the swapper_pg_dir. We can simply   * re-use the existing dir for the fixmap.   */  set_pgd(pgd_offset_raw(pgd, FIXADDR_START),   *pgd_offset_k(FIXADDR_START)); } else if (CONFIG_PGTABLE_LEVELS > 3) {  /*   * The fixmap shares its top level pgd entry with the kernel   * mapping. This can really only occur when we are running   * with 16k/4 levels, so we can simply reuse the pud level   * entry instead.   */  BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));  set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START),   __pud(__pa(bm_pmd) | PUD_TYPE_TABLE));  pud_clear_fixmap(); } else {  BUG(); }
 kasan_copy_shadow(pgd);}
static void __init map_mem(pgd_t *pgd){ struct memblock_region *reg;
 /* map all the memory banks */ for_each_memblock(memory, reg) {  phys_addr_t start = reg->base;  phys_addr_t end = start + reg->size;
  if (start >= end)   break;  if (memblock_is_nomap(reg))   continue;
  __map_memblock(pgd, start, end); }}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: