未解压时的内核页表

这或许是x86平台启动过程中第一张页表了。

之前我们也学习了内核启动镜像bzImage由两部分组成setup.bin和vmlinux.bin。而这张第一章页表就在vmlinux.bin的head.S中。

如果对上述两个文件编译过程不熟悉的话可以参考下面的链接:

先来看个代码

这第一张页表初始化的代码就在arch/x86/boot/compressed/head_64.S中。

 /*
  * Build early 4G boot pagetable
  */
	/* Initialize Page tables to 0 */
	leal	pgtable(%ebx), %edi
	xorl	%eax, %eax
	movl	$(BOOT_INIT_PGT_SIZE/4), %ecx
	rep	stosl

	/* Build Level 4 */
	leal	pgtable + 0(%ebx), %edi
	leal	0x1007 (%edi), %eax
	movl	%eax, 0(%edi)

	/* Build Level 3 */
	leal	pgtable + 0x1000(%ebx), %edi
	leal	0x1007(%edi), %eax
	movl	$4, %ecx
1:	movl	%eax, 0x00(%edi)
	addl	$0x00001000, %eax
	addl	$8, %edi
	decl	%ecx
	jnz	1b

	/* Build Level 2 */
	leal	pgtable + 0x2000(%ebx), %edi
	movl	$0x00000183, %eax
	movl	$2048, %ecx
1:	movl	%eax, 0(%edi)
	addl	$0x00200000, %eax
	addl	$8, %edi
	decl	%ecx
	jnz	1b

	/* Enable the boot page tables */
	leal	pgtable(%ebx), %eax
	movl	%eax, %cr3

看到最后把地址保存到了cr3了么?Yep, you get it.

干这么看确实有点枯燥,不过简单来说就是分别填写了三层结构,构造出了一张覆盖4G大小的页表。

PS: 此时页表并没有启用,而是要等到后面CR0中的PG被置位后。

再来看一张图

看着图再去对照代码,我相信你就可以看懂了。

这样是不是清晰了很多。

代码我就不多说了,多看几遍自然就懂了。正所谓

代码虐我千百遍,我待代码如初恋

重要提醒

大家看这张表,有没有意识到什么特别的地方?对了,虚拟地址和物理地址是一样的。

那内核中的虚拟地址又是如何访问的呢?别着急,这一切才刚刚开始~

Last updated