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
错漏之处还望不吝指出