微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Android arm linux kernel启动流程

Android arm linux kernel启动流程

时间:11-09 来源:互联网 点击:

是一个结构体,它的头文件在 arch/arm/include/asm/arch/arch.h里面(machine_desc),它具体的实现根据你对芯片类型的选择而不同,这里我们使用的是高通的7x27,具体实现在arch/arm/mach-msm/board-msm7x27.c里面,这些结构体最后都会注册到 _arch_info_begin和_arch_info_end段里面,具体的大家可以看看vmlinux.lds或者system.map,这里的 lookup会根据bootloader传过来的nr来在__arch_info里面的相匹配的类型,没有的话就寻找下一个machin_desk结构体,直到找到相应的结构体,并会将结构体的地址赋值给寄存器,如果没有的话就会赋值为0的。一般来说这里的machine_type会有好几个,因为不同的芯片类型可能使用的都是同一个cpu架构。

对processor和machine的检查完以后就会检查atags parameter的有效性,关于这个atag具体的定义我们可以在./include/asm/setup.h里面看到,它实际是一个结构体和一个联合体构成的结合体,里面的size都是以字来计算的。这里的atags param是bootloader创建的,里面包含了ramdisk以及其他memory分配的一些信息,存储在boot.img头部结构体定义的地址中,具体的大家可以看咱以后对bootloader的分析~

view plainprint?

  1. __vet_atags:
  2. tstr2,#0x3@aligned?
  3. bne1f
  4. ldrr5,[r2,#0]@isfirsttagATAG_CORE?
  5. cmpr5,#ATAG_CORE_SIZE
  6. cmpner5,#ATAG_CORE_SIZE_EMPTY
  7. bne1f
  8. ldrr5,[r2,#4]
  9. ldrr6,=ATAG_CORE
  10. cmpr5,r6
  11. bne1f
  12. movpc,lr@atagpointerisok
  13. 1:movr2,#0
  14. movpc,lr
  15. ENDPROC(__vet_atags)

__vet_atags: tst r2, #0x3 @ aligned? bne 1f ldr r5, [r2, #0] @ is first tag ATAG_CORE? cmp r5, #ATAG_CORE_SIZE cmpne r5, #ATAG_CORE_SIZE_EMPTY bne 1f ldr r5, [r2, #4] ldr r6, =ATAG_CORE cmp r5, r6 bne 1f mov pc, lr @ atag pointer is ok 1: mov r2, #0 mov pc, lr ENDPROC(__vet_atags)

这里对atag的检查主要检查其是不是以ATAG_CORE开头,size对不对,基本没什么好分析的,代码也比较好看~ 下面我们来看后面一个重头戏,就是创建初始化页表,说实话这段内容我没弄清楚,它需要对ARM VIRT MMU具有相当的理解,这里我没有太多的时间去分析spec,只是粗略了翻了ARM V7的manu,知道这里建立的页表是arm的secition页表,完成内存开始1m内存的映射,这个页表建立在kernel和atag paramert之间,一般是4000-8000之间~具体的代码和过程我这里就不贴了,大家可以看看参考的链接,看看其他大虾的分析,我还没怎么看明白,等以后仔细研究ARM MMU的时候再回头来仔细研究了,不过代码虽然不分析,这里有几个重要的地址需要特别分析下~

这几个地址都定义在arch/arm/include/asm/memory.h,我们来稍微分析下这个头文件,首先它包含了arch /memory.h,我们来看看arch/arm/mach-msm/include/mach/memory.h,在这个里面定义了#define PHYS_OFFSET UL(0x00200000) 这个实际上是memory的物理内存初始地址,这个地址和我们以前在boardconfig.h里面定义的是一致的。然后我们再看 asm/memory.h,他里面定义了我们的memory虚拟地址的首地址#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET)。

另外我们在head.S里面看到kernel的物理或者虚拟地址的定义都有一个偏移,这个偏移又是从哪来的呢,实际我们可以从arch/arm /Makefile里面找到:textofs-y := 0x00008000 TEXT_OFFSET := $(textofs-y)这样我们再看kernel启动时候的物理地址和链接地址,实际上它和我们前面在boardconfig.h和 Makefile.boot里面定义的都是一致的~

建立初始化页表以后,会首先将__switch_data这个symbol的链接地址放在sp里面,然后获得__enable_mmu的物理地址,然后会跳到__proc_info_list里面的INITFUNC执行,这个偏移是定义在arch/arm/kernel/asm-offset.c里面,实际上就是取得__proc_info_list里面的__cpu_flush这个函数执行。

view plainprint?

  1. ldrr13,__switch_data@addresstojumptoafter
  2. @mmuhasbeenenabled
  3. adrlr,__enable_mmu@return(PIC)address
  4. addpc,r10,#PROCINFO_INITFUNC

ldr r13, __switch_data @ address to jump to after @ mmu has been enabled adr lr, __enable_mmu @ return (PIC) address add pc, r10, #PROCINFO_INITFUNC

这个__cpu_flush在这里就是我们proc-v6.S里面的__v6_setup函数了,具体它的实现我就不分析了,都是对arm控制寄存器的操作,这里转一下它对这部分操作的注释,看完之后就基本知道它完成的功能了。

/*

* __v6_setup

*

* Initialise TLB, Caches, and MMU stat

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top