Linux内核加载过程


以32位x86,bzImge为例

grub版本为0.97

1、计算机上电

2、0xFFFFFFF0

当cpu检测reset引脚上的信号后

便将指令指针寄存器的值设置为0xfff0

——INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986, Chapter 10

此时为实模式,cpu将执行物理地址0xFFFFFFF0处的指令

访址的时候,硬件将该地址映射到BIOS的ROM中

BIOS中的指令将MBR复制到物理地址0x7c00处,并跳转到该处执行

3、0x7C00

MBR中的指令由grub安装而来,为grub-0.97/stage1/stage1.S

stage1将stage2的第1部分grub-0.97/stage2/start.S(512字节)复制到物理地址0x8000处,并跳转到该处执行

stage2将剩余部分grub-0.97/stage2/asm.S复制到物理地址0x8200处,并跳转到该处执行

...

grub-0.97/stage2/boot.c——load_image()函数

将内核映像bzImage的setup部分复制到物理地址0x90000

vmlinux部分复制到物理地址0x100000处

随后跳转到0x90200处执行

4、0x90200

arch/x86/boot/heaer.S——_start => start_of_setup

检查准备实模式堆栈,bss段清0,随后调用arch/x86/boot/main.c——main()函数

main()中使用BIOS中断读取一些硬件信息,如内存信息等

最后调用arch/x86/boot/pm.c——go_to_protected_mode()函数

go_to_protected_mode()设置段描述符,随后调用arch/x86/boot/pmjump.S——protected_mode_jump()函数

protected_mode_jump()置cr0的PE位,开启保护模式

最后跳转到code32_start,对于bzImage即物理地址0x100000,grub复制的bzImage第2部分

5、0x100000

arch/x86/boot/compressed/head_32.S——startup_32

arch/x86/boot/compressed/misc.c——decompress_kernel()解压内核

解压完成后跳转到output

6、LOAD_PHYSICAL_ADDR

根据不同的配置,解压后的代码在物理内存中的起始位置亦不同

arch/x86/kernel/head_32.S——startup_32

设置页表,置cr0的PG位,开启分页

最后跳转到arch/x86/kernel/head32.c——i386_start_kernel()函数

i386_start_kernel()中最后调用start_kernel()

7、start_kernel()

init/main.c——start_kernel()

进入c代码部分

详细的注释请参考git://github.com/kernel-digger/linux-2.6.git

错漏之处还望不吝指出

相关内容