Linux 内核页表初始化

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




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值