启用init_level4_pgt
内核启动阶段,使用的页表是early_level4_pgt。(有可能不是,大部分情况下是的。)
early_level4_pgt的设置可以看head_64.S设置的段页
看这个名字就能猜出来,这个页表仅仅是初始的时候使用的。那什么时候内核第一次更改的呢?
成功上位
void __init init_mem_mapping(void)
{
load_cr3(swapper_pg_dir);
__flush_tlb_all();
}
然后呢? 咱来做个实验吧~
给出补丁~ 4.7上的
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 2ee7811..f6dc1ed 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -21,6 +21,7 @@ extern pmd_t level2_fixmap_pgt[512];
extern pmd_t level2_ident_pgt[512];
extern pte_t level1_fixmap_pgt[512];
extern pgd_t init_level4_pgt[];
+extern pgd_t early_level4_pgt[];
#define swapper_pg_dir init_level4_pgt
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 372aad2..ba19480 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -577,7 +577,7 @@ static void __init memory_map_bottom_up(unsigned long map_start,
void __init init_mem_mapping(void)
{
- unsigned long end;
+ unsigned long end, pgd;
probe_page_size_mask();
@@ -619,7 +619,13 @@ void __init init_mem_mapping(void)
early_ioremap_page_table_range_init();
#endif
+ printk(KERN_ERR "%s: early_level4_pgt is %lx\n", __func__, __pa_symbol(early_level4_pgt ));
+ printk(KERN_ERR "%s: init_level4_pgt is %lx\n", __func__, __pa_symbol(init_level4_pgt ));
+ pgd = read_cr3();
+ printk(KERN_ERR "%s: current cr3 is %lx\n", __func__, pgd);
load_cr3(swapper_pg_dir);
+ pgd = read_cr3();
+ printk(KERN_ERR "%s: cr3 is set to %lx\n", __func__, pgd);
__flush_tlb_all();
early_memtest(0, max_pfn_mapped << PAGE_SHIFT);
其实很简单,就是打印了一下early_level4_pgt, init_level4_pgt,用来对比一下cr3中,原有的值和更改后的值。
简单吧,然后看一下这次输出的结果,看看我们的猜想对不对~
[ 0.000000] init_mem_mapping: early_level4_pgt is 1fca000
[ 0.000000] init_mem_mapping: init_level4_pgt is 1e06000
[ 0.000000] init_mem_mapping: current cr3 is 1fca000
[ 0.000000] init_mem_mapping: cr3 is set to 1e06000
好了,内核页表切换完成。进入到init_level4_pgt统治的时代了。
补充细节
之前内核都是使用early_level4_pgt这个页表的,那和init_level4_pgt有什么关系呢?
来来看看这段代码。
asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
{
...
clear_page(init_level4_pgt);
...
/* set init_level4_pgt kernel high mapping*/
init_level4_pgt[511] = early_level4_pgt[511];
...
}
在这段代码中,init_level4_pgt[511]设置成了early_level4_pgt一样的值。
好了这下清楚了,从本质上讲,这两个页表没有什么区别,本次的页表和之前的页表样子没有变。
Last updated
Was this helpful?