前面我们讨论了页描述符对象分配,以及初始化。接下来我们再来了解内核页表建立初始化处理。针对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);
 }
}