From e611beba929f5e65b620071eed16adcce5036b7a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Sep 2016 15:41:39 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=8E=9F=E7=89=88?= =?UTF-8?q?=E7=9A=84=E6=9B=B4=E6=96=B0=EF=BC=8C=E4=BF=AE=E6=AD=A3=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Booting/linux-bootstrap-4.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Booting/linux-bootstrap-4.md b/Booting/linux-bootstrap-4.md index eb91799..3baa2d0 100644 --- a/Booting/linux-bootstrap-4.md +++ b/Booting/linux-bootstrap-4.md @@ -78,17 +78,17 @@ vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/piggy.o $(obj)/cpuflags.o ``` -注意 `$(obj)/head_$(BITS).o` 。这意味着我们将会选择基于 `$(BITS)` 所设置的文件执行链接操作,即 head_32.o 或者 head_64.o。`$(BITS)` 在 [arch/x86/kernel/Makefile](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/Makefile) 之中根据 .config 文件另外定义: +注意 `$(obj)/head_$(BITS).o` 。这意味着我们将会选择基于 `$(BITS)` 所设置的文件执行链接操作,即 head_32.o 或者 head_64.o。`$(BITS)` 在 [arch/x86/Makefile](https://github.com/torvalds/linux/blob/master/arch/x86/Makefile) 之中根据 .config 文件另外定义: ```Makefile ifeq ($(CONFIG_X86_32),y) - BITS := 32 + BITS := 32 ... ... else - ... - ... BITS := 64 + ... + ... endif ``` @@ -272,7 +272,7 @@ ebp 0x100000 0x100000 movl %eax, %esp ``` - `boots_stack_end` 被定义在同一个汇编文件 [arch/x86/boot/compressed/head_64.S](https://github.com/torvalds/linux/blob/master/arch/x86/boot/compressed/head_64.S) 中,位于 [.bss](https://en.wikipedia.org/wiki/.bss) 段: + `boots_stack_end` 标签被定义在同一个汇编文件 [arch/x86/boot/compressed/head_64.S](https://github.com/torvalds/linux/blob/master/arch/x86/boot/compressed/head_64.S) 中,位于 [.bss](https://en.wikipedia.org/wiki/.bss) 段: ```assembly .bss @@ -284,7 +284,7 @@ boot_stack: boot_stack_end: ``` -首先,我们把 `boot_stack_end` 放到 `eax` 寄存器中。现在 `eax` 寄存器将包含 `boot_stack_end` 链接后的地址或者说 `0x0 + boot_stack_end` 。为了得到 `boot_stack_end` 的实际地址,我们需要加上 `startup_32` 的实际地址。回忆一下,前面我们找到了这个地址并且把它存到了 `ebp` 寄存器中。最后,`eax` 寄存器将会包含 `boot_stack_end` 的实际地址,我们只需要将其加到栈指针上。 +首先,我们把 `boot_stack_end` 放到 `eax` 寄存器中。那么 `eax` 寄存器将包含 `boot_stack_end` 链接后的地址或者说 `0x0 + boot_stack_end` 。为了得到 `boot_stack_end` 的实际地址,我们需要加上 `startup_32` 的实际地址。回忆一下,前面我们找到了这个地址并且把它存到了 `ebp` 寄存器中。最后,`eax` 寄存器将会包含 `boot_stack_end` 的实际地址,我们只需要将其加到栈指针上。 在外面建立了栈之后,下一步是 CPU 的确认。既然我们将要切换到 `长模式` ,我们需要检查 CPU 是否支持 `长模式` 和 `SSE`。我们将会在跳转到 `verify_cpu` 函数之后执行: @@ -351,7 +351,7 @@ KBUILD_CFLAGS += -fno-strict-aliasing -fPIC addl $z_extract_offset, %ebx ``` -记住 `ebp` 寄存器的值就是 `startup_32` 标签的物理地址。如果在内核配置中 `CONFIG_RELOCATABLE` 内核配置项开启,我们就把这个地址放到 `ebx` 寄存器中,对齐到 `2M` ,然后和 `LOAD_PHYSICAL_ADDR` 的值比较。 `LOAD_PHYSICAL_ADDR` 宏定义在头文件 [arch/x86/include/asm/boot.h](https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/boot.h) 中,如下: +记住 `ebp` 寄存器的值就是 `startup_32` 标签的物理地址。如果在内核配置中 `CONFIG_RELOCATABLE` 内核配置项开启,我们就把这个地址放到 `ebx` 寄存器中,对齐到 `2M` 的整数倍 ,然后和 `LOAD_PHYSICAL_ADDR` 的值比较。 `LOAD_PHYSICAL_ADDR` 宏定义在头文件 [arch/x86/include/asm/boot.h](https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/boot.h) 中,如下: ```C #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ @@ -446,7 +446,7 @@ Linux 内核使用 `4级` 页表,通常我们会建立6个页表: * 1 个 `PML4` 或称为 `4级页映射` 表,包含 1 个项; * 1 个 `PDP` 或称为 `页目录指针` 表,包含 4 个项; -* 4 个 页目录表,包含 `2048` 个项; +* 4 个 页目录表,一共包含 `2048` 个项; 让我们看看其实现方式。首先我们在内存中为页表清理一块缓存。每个表都是 `4096` 字节,所以我们需要 `24` KB 的空间: From 1118bc65689471164bd7590bd8b8a23c396b054f Mon Sep 17 00:00:00 2001 From: Key_Zhang Date: Tue, 6 Sep 2016 15:53:37 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=8E=9F=E7=89=88=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Booting/linux-bootstrap-4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Booting/linux-bootstrap-4.md b/Booting/linux-bootstrap-4.md index 3baa2d0..651c49f 100644 --- a/Booting/linux-bootstrap-4.md +++ b/Booting/linux-bootstrap-4.md @@ -310,7 +310,7 @@ no_longmode: 计算重定位地址 -------------------------------------------------------------------------------- -下一步是在必要的时候计算解压缩之后的地址。首先,我们需要知道内核重定位的意义。我们已经知道 Linux 内核的32位入口点地址位于 `0x100000` 。但是那是一个32位的入口。默认的内核基地址由内核配置项 `CONFIG_PHYSICAL_START` 的值所确定,其默认值为 `0x100000` 或 `1 MB` 。这里的主要问题是如果内核崩溃了,内核开发者需要一个配置于不同地址加载的 `救援内核` 来进行 [kdump](https://www.kernel.org/doc/Documentation/kdump/kdump.txt)。Linux 内核提供了特殊的配置选项以解决此问题 - `CONFIG_RELOCATABLE` 。我们可以在内核文档中找到: +下一步是在必要的时候计算解压缩之后的地址。首先,我们需要知道内核重定位的意义。我们已经知道 Linux 内核的32位入口点地址位于 `0x100000` 。但是那是一个32位的入口。默认的内核基地址由内核配置项 `CONFIG_PHYSICAL_START` 的值所确定,其默认值为 `0x1000000` 或 `16 MB` 。这里的主要问题是如果内核崩溃了,内核开发者需要一个配置于不同地址加载的 `救援内核` 来进行 [kdump](https://www.kernel.org/doc/Documentation/kdump/kdump.txt)。Linux 内核提供了特殊的配置选项以解决此问题 - `CONFIG_RELOCATABLE` 。我们可以在内核文档中找到: ``` This builds a kernel image that retains relocation information