arch/i386/boot/compress/head.S is responsible for decompressed the kernel and move it to 0x100000. when it is executed, the virtual address is 0x1000 for low loaded vmlinux and 0x100000 for high loaded one, which are the same with their physical addresses, respectively.
/* check contents of 0x000000 and 0x100000, if not equal, means A20 is enabled. */
xorl %eax,%eax
1: incl %eax # check that A20 really IS enabled
movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000
je 1
/* decompress the kernel and jump to it (0x100000) for low loaded kernel */
subl $16,%esp # place for structure on the stack
pushl %esp # address of structure as first arg
call SYMBOL_NAME(decompress_kernel)
orl %eax,%eax
jnz 3f
xorl %ebx,%ebx
ljmp $(__KERNEL_CS), $0x10000
/* move move_routine_start to 0x1000 and jump to it */
movl $move_routine_start,%esi
movl $0x1000,%edi
movl $move_routine_end,%ecx
subl %esi,%ecx
cld
rep
movs
popl %esi # discard the address
popl %esi # low_buffer_start
popl %ecx # lcount
popl %edx # high_buffer_start
popl %eax # hcount
movl $0x100000,%edi
cli # make sure we don't get interrupted
ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
/* move hcount from high_buffer_start to 0x100000 and jump to it for high loaded kernel */
move_routine_start:
rep
movsb
movl %edx,%esi
movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
rep
movsb
xorl %ebx,%ebx
/*
* Well, the kernel relies on %esp pointing into low mem,
* with the decompressor loaded high this is no longer true,
* so we set esp here.
*/
mov $0x90000,%esp
ljmp $(__KERNEL_CS), $0x100000
move_routine_end:
本文介绍Linux i386架构下内核的加载与解压缩过程,包括检查A20地址线是否启用、解压内核到内存指定位置0x100000并跳转执行,以及对于高地址加载的内核如何移动解压后的代码。
450

被折叠的 条评论
为什么被折叠?



