mov pc, r4 @ call kernel

mov pc, r4          @ call kernel   绝对跳转到r4:40008000处开始执行

开始进入Image,Image由vmlinux生成,所以从vmlinux开始阅读理解。

arch/unicore/kernel目录,据其链接脚本,从head.S开始:

__lookup_processor_type:

运用相对取址,取出proc_info_list,做出processor对比(因为一个镜像支持一种processor,该processor的信息从协处理器的c0:4d000863中取出)。这里首先要运用相对取值,因为我们编译的内核是按照虚拟地址进行编译链接的,其次是proc_info_list的存储:我们在程序中声明了.section ".proc.info.init",而后链接脚本中显示的定义的该输入section,并且以__proc_info_begin和__proc_info_end作为界限,因此头文件的proc_info_begin结构体根本就没有相应的变量,该section的内容在编译时就确定了。

__lookup_machine_type:

验证过程同__lookup_processor_type,因为每个processor所处的环境不同,因此每个板子会有一个相应的machine_type,这在boot阶段就传入了的arch_id:0x9fc,可以与内核镜像中设定的做对比,以此来验证该内核镜像是否可以运行在该开发板上。

(查看:/arch/unicore/mach-sep0611/mach-tiger-test.c +226

             /arch/unicore/include/asm/mach/arch.h +53)

__vet_atags参数地址验证

__create_page_tables:

建立内核页表(40007000处,正好据内核起始4K大小,可以建立1K个一级变换条目),因为unicore32支持4M超页,所以建立内核的页表很简单,更具内核编译的起始地址,以及结束地址bss段末尾,为内核建立页表,同时也为DDR2的虚拟地址前4M建立一级超页表映射,当然实际上有点重复了,因为我们内核的链接起始地址是C0008000,而DDR2的欲建立的虚拟起始地址是C0000000。

ldw r13, __switch_data      @ address to jump to after

                                       @ mmu has been enabled

adr lr, __enable_mmu        @ return (PIC) address

add pc, r10, #PROCINFO_INITFUNC (实际上运行.section “.proc.info.init”中的b __ucv2_setup)

__ucv2_setup:

cache无效,TLB无效,将系统即将被设置的cache与MMU写入r0,我们采用了中断向量起始0xFFFF0000,I、Dcache使能,Dcache使用write_back策略,地址对其检查使能,Busrt传输使能,MMU使能(注意这些还未写进协控制寄存器),最后执行指令

mov pc,lr

因此开始运行__enable_mmu:

将页表基址写入p0.c2,相对跳转到__turn_mmu_on(注意没有改变lr寄存器值)

__turn_mmu_on:

    将r0写入pc.c1     movc    p0.c1, r0, #0

mov pc, r13    从此我们在虚拟地址下运行

nop; nop; nop; nop; nop; nop; nop; nop(unicore32是八级流水,不过还是多了,当然谁会在意这个呢)

__switch_data:

开始建立BSS段,将processor_id、__machine_arch_type、__atags_pointer、cr_alignment存放于固定地址(当然对这几个参数还不是很明白,以后再看看),还有一个栈值init_thread_union + THREAD_START_SP,反汇编是0xc058dff8,位于data段中,这个栈值不理解为什么要如此设置。

 

执行b start_kernel跳转到/init/main.c中开始执行第一个C程序。

你可能感兴趣的:(kernel)