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

Android arm linux kernel启动流程

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

__lookup_processor_type: adr r3, 3f ldmda r3, {r5 - r7} sub r3, r3, r7 @ get offset between virt&phys add r5, r5, r3 @ convert virt addresses to add r6, r6, r3 @ physical address space 1: ldmia r5, {r3, r4} @ value, mask and r4, r4, r9 @ mask wanted bits teq r3, r4 beq 2f add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) cmp r5, r6 blo 1b mov r5, #0 @ unknown processor 2: mov pc, lr ENDPROC(__lookup_processor_type)

他这里的执行过程其实比较简单就是在__proc_info_begin和__proc_info_end这个段里面里面去读取我们注册在里面的 proc_info_list这个结构体,这个结构体的定义在arch/arm/include/asm/procinfo.h,具体实现根据你使用的 cpu的架构在arch/arm/mm/里面找到具体的实现,这里我们使用的ARM11是proc-v6.S,我们可以看看这个结构体:

view plainprint?

  1. .section".proc.info.init",#alloc,#execinstr
  2. /*
  3. *MatchanyARMv6processorcore.
  4. */
  5. .type__v6_proc_info,#object
  6. _proc_info:
  7. .long0x0007b000
  8. .long0x0007f000
  9. .longPMD_TYPE_SECT|/
  10. PMD_SECT_BUFFERABLE|/
  11. PMD_SECT_CACHEABLE|/
  12. PMD_SECT_AP_WRITE|/
  13. PMD_SECT_AP_READ
  14. .longPMD_TYPE_SECT|/
  15. PMD_SECT_XN|/
  16. PMD_SECT_AP_WRITE|/
  17. PMD_SECT_AP_READ
  18. b__v6_setup
  19. .longcpu_arch_name
  20. .longcpu_elf_name
  21. .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
  22. .longcpu_v6_name
  23. .longv6_processor_functions
  24. .longv6wbi_tlb_fns
  25. .longv6_user_fns
  26. .longv6_cache_fns
  27. .size__v6_proc_info,.-__v6_proc_info

.section ".proc.info.init", #alloc, #execinstr /* * Match any ARMv6 processor core. */ .type __v6_proc_info, #object __v6_proc_info: .long 0x0007b000 .long 0x0007f000 .long PMD_TYPE_SECT | / PMD_SECT_BUFFERABLE | / PMD_SECT_CACHEABLE | / PMD_SECT_AP_WRITE | / PMD_SECT_AP_READ .long PMD_TYPE_SECT | / PMD_SECT_XN | / PMD_SECT_AP_WRITE | / PMD_SECT_AP_READ b __v6_setup .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA .long cpu_v6_name .long v6_processor_functions .long v6wbi_tlb_fns .long v6_user_fns .long v6_cache_fns .size __v6_proc_info, . - __v6_proc_info

对着.h我们就知道各个成员变量的含义了,他这里lookup的过程实际上是先求出这个proc_info_list的实际物理地址,并将其内容读出,然后将其中的mask也就是我们这里的0x007f000与寄存器与之后与0x007b00进行比较,如果一样的话呢就校验成功了,如果不一样呢就会读下一个proc_info的信息,因为proc一般都是只有一个的,所以这里一般不会循环,如果检测正确寄存器就会将正确的proc_info_list的物理地址赋给寄存器,如果检测不到就会将寄存器值赋0,然后通过LR返回。

view plainprint?

  1. bl__lookup_machine_type@r5=machinfo
  2. movsr8,r5@invalidmachine(r5=0)?
  3. beq__error_a@yes,errora

bl __lookup_machine_type @ r5=machinfo movs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error a

检测完proc_info_list以后就开始检测machine_type了,这个函数的实现也在head-common.S里面,我们看看它具体的实现:

view plainprint?

  1. __lookup_machine_type:
  2. adrr3,3b
  3. ldmiar3,{r4,r5,r6}
  4. subr3,r3,r4@getoffsetbetweenvirt&phys
  5. addr5,r5,r3@convertvirtaddressesto
  6. addr6,r6,r3@physicaladdressspace
  7. 1:ldrr3,[r5,#MACHINFO_TYPE]@getmachinetype
  8. teqr3,r1@matchesloadernumber?
  9. beq2f@found
  10. addr5,r5,#SIZEOF_MACHINE_DESC@nextmachine_desc
  11. cmpr5,r6
  12. blo1b
  13. movr5,#0@unknownmachine
  14. 2:movpc,lr
  15. ENDPROC(__lookup_machine_type)

__lookup_machine_type: adr r3, 3b ldmia r3, {r4, r5, r6} sub r3, r3, r4 @ get offset between virt&phys add r5, r5, r3 @ convert virt addresses to add r6, r6, r3 @ physical address space 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type teq r3, r1 @ matches loader number? beq 2f @ found add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc cmp r5, r6 blo 1b mov r5, #0 @ unknown machine 2: mov pc, lr ENDPROC(__lookup_machine_type)

这里的过程基本上是同proc的检查是一样的,这里主要检查芯片的类型,比如我们现在的芯片是MSM7X27FFA,这也

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

网站地图

Top