linux kernel initiate steps

来源:互联网 发布:xrd分析软件下载 编辑:程序博客网 时间:2024/04/30 05:08
vmlinux被load到内存地址0,首先从地址0x8000开始执行,这段最开始的代码在arch/arm/kernel/head.S的ENTRY(stext)中。用arm-none-linux-gnueabi-objdump-d vmlinux后,可看到代码从0xc0008000开始,第一行代码正是ENTRY(stext)后的msr CPSR_c,#211。为什么是0xc0008000而不是0x8000呢,这和内存映射(memorymap)有关,稍后会详述。从地址0x8000开始的汇编代码做了以下几件事情:

这里用gdb调试的时候,pc(代码)在0x8000开始的内存

第一阶段: 启动-> start_kernel() [汇编语言]
1. 读取processor id, machine type
2. __vet_atags(??)
3. 创建页表( __create_page_tables)
4. 配置arm926的MMU,包括(I-Cache, D-Cache, TLB)(__arm926_setup(),arch/arm/mm/proc-arm926.S中)
5. Enable MMU(__enable_mmu)
enable MMU之后,Kernel代码就被映射到0xc0008000,后面所有pc都在0xc0008000开始内存中。
在__turn_mmu_on中的以下汇编语句会设定cp15:
     mcrp15, 0, r0, c1, c0, 0
此处r0的值在__arm926_setup()中设定,其中会开启MMU。在gdb中用breakpoint可以看到r0=0x93177。这句执行之后,原来在0开始的PC地址就被映射到0xC0008000开始的地方,之后的一句movpc, sp就从0xC0008164开始执行了。
6. __mmap_switched
7. start_kernel (开始引导kernel, init/main.c中)

第二阶段:start_kernel()中:irq disable阶段,做了以下几件事:
1. tick init: 注册clock event的notifier
2. boot cpu init: 初始化boot cpu
3. setup arch: 对cpu architecture特有的feature进行配置。在ARM上即对ARMCPU,TCM等进行配置。
   特别是在early_trap_init()中:
    (1)将arm exception vector table, stubs和kuserhelper配置到0xFFFF0000的High vector address上。
    (2)copy signal return handler到exception vector table的后面(0xFFFF0000+ 0x500)处。

         * Signal return handler是在从kernel mode返回usermode的时候,如果有pending的signal,则调用该signal的Handler。这段代码在entry-common.S中如下:

work_pending:
   tst r1, #_TIF_NEED_RESCHED
   bne work_resched
   tst r1,#_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
   beq no_work_pending
   mov r0,sp    @'regs'
   mov r2,why    @'syscall'
   bl do_notify_resume
   ret_slow_syscall  @Check work again

在do_notify_resume->.....->setup_return()中会将PC设成Signalhandler,LR设成Signal regturn handler,这样在restore_user_regs时就会去执行Signalhandler,执行完后再执行Signal return handler。Signal returnhandler实际做了什么呢?看一下entry_trap_init()中copy的sigreturn_codes,它实际上就是一组预先编码好的Arm指令,这些执行的效果就是条用sys_sigreturn()这个systemcall,从signal handler中返回。
 
   (3)copy system restarthandler到signal return handler后面。restarthandler就是执行sys_restart_syscall,重启动一个syscall。在do_notify_resume->do_signal中,如果没有signal要handle,就重新启动syscall。
0 0
原创粉丝点击