微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux 的启动过程

ARM Linux 的启动过程

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

  1. dent
  2. *manner.Seearch/arm/mm/proc-*.Sfordetails.r10=baseof
  3. *xxx_proc_infostructureselectedby__lookup_machine_type
  4. *above.Onreturn,theCPUwillbereadyfortheMMUtobe
  5. *turnedon,andr0willholdtheCPUcontrolregistervalue.
  6. */
  7. /*这里的逻辑关系相当复杂,先是从proc_info结构中的中跳进__arm920_setup函数,
  8. *然后执__enable_mmu函数。最后在__enable_mmu函数通过movpc,r13来执行__switch_data,
  9. *__switch_data函数在最后一条语句,鱼跃龙门,跳进第一个C语言函数start_kernel。
  10. */
  11. ldrr13,__switch_data@addresstojumptoafter
  12. @mmuhasbeenenabled
  13. adrlr,__enable_mmu@return(PIC)address
  14. addpc,r10,#PROCINFO_INITFUNC
  15. OC(stext)



3 __lookup_processor_type 函数

__lookup_processor_type 函数是一个非常讲究技巧的函数,如果你将它领会,也将领会kernel了一些魔法。

Kernel代码将所有CPU信息的定义都放到.proc.info.init段中,因此可以认为.proc.info.init段就是一个数组,每个元素都定义了一个或一种CPU的信息。目前__lookup_processor_type使用该元素的前两个字段cpuid和mask来匹配当前CPUID,如果满足CPUID & mask == cpuid,则找到当前cpu的定义并返回。

下面是tqs3c2440开发板,CPU的定义信息,cpuid = 0x41009200,mask = 0xff00fff0。如果是码是运行在tqs3c2440开发板上,那么函数返回下面的定义:

[cpp]view plaincopy

  1. .section".proc.info.init",#alloc,#execinstr
  2. .type__arm920_proc_info,#object
  3. __arm920_proc_info:
  4. .long0x41009200
  5. .long0xff00fff0
  6. .longPMD_TYPE_SECT|\
  7. PMD_SECT_BUFFERABLE|\
  8. PMD_SECT_CACHEABLE|\
  9. PMD_BIT4|\
  10. PMD_SECT_AP_WRITE|\
  11. PMD_SECT_AP_READ
  12. .longPMD_TYPE_SECT|\
  13. PMD_BIT4|\
  14. PMD_SECT_AP_WRITE|\
  15. PMD_SECT_AP_READ
  16. /*__arm920_setup函数在stext的未尾被调用,请往回看。*/
  17. b__arm920_setup
  18. .longcpu_arch_name
  19. .longcpu_elf_name
  20. .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB
  21. .longcpu_arm920_name
  22. .longarm920_processor_functions
  23. .longv4wbi_tlb_fns
  24. .longv4wb_user_fns
  25. #ifndefCONFIG_CPU_DCACHE_WRITETHROUGH
  26. .longarm920_cache_fns
  27. #else
  28. .longv4wt_cache_fns
  29. #endif
  30. .size__arm920_proc_info,.-__arm920_proc_info

[cpp]view plaincopy

  1. .section".proc.info.init",#alloc,#execinstr
  2. .type__arm920_proc_info,#object
  3. __arm920_proc_info:
  4. .long0x41009200
  5. .long0xff00fff0
  6. .longPMD_TYPE_SECT|\
  7. PMD_SECT_BUFFERABLE|\
  8. PMD_SECT_CACHEABLE|\
  9. PMD_BIT4|\
  10. PMD_SECT_AP_WRITE|\
  11. PMD_SECT_AP_READ
  12. .longPMD_TYPE_SECT|\
  13. PMD_BIT4|\
  14. PMD_SECT_AP_WRITE|\
  15. PMD_SECT_AP_READ
  16. /*__arm920_setup函数在stext的未尾被调用,请往回看。*/
  17. b__arm920_setup
  18. .longcpu_arch_name
  19. .longcpu_elf_name
  20. .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB
  21. .longcpu_arm920_name
  22. .longarm920_processor_functions
  23. .longv4wbi_tlb_fns
  24. .longv4wb_user_fns
  25. #ifndefCONFIG_CPU_DCACHE_WRITETHROUGH
  26. .longarm920_cache_fns
  27. #else
  28. .longv4wt_cache_fns
  29. #endif
  30. .size__arm920_proc_info,.-__arm920_proc_info

[cpp]view plaincopy

  1. /*
  2. *ReadprocessorIDregister(CP#15,CR0),andlookupinthelinker-built
  3. *supportedprocessorlist.Notethatwecantusetheabsoluteaddresses
  4. *forthe__proc_infolistssincewearentrunningwiththeMMUon
  5. *(andtherefore,wearenotinthecorrectaddressspace).Wehaveto
  6. *calculatetheoffset.
  7. *
  8. *r9=cpuid
  9. *Returns:
  10. *r3,r4,r6corrupted
  11. *r5=proc_infopointerinphysicaladdressspace
  12. *r9=cpuid(preserved)
  13. */
  14. __lookup_processor_type:
  15. /*adr是相对寻址,它的寻计算结果是将当前PC值加上3f符号与PC的偏移量,
  16. *而PC是物理地址,因此r3的结果也是3f符号的物理地址*/
  17. adrr3,3f
  18. /*r5值为__proc_info_bein,r6值为__proc_ino_end,而r7值为.,
  19. *也即3f符号的链接地址。请注意,在链接期间,__proc_info_begin和
  20. *__proc_info_end以及.均是链接地址,也即虚执地址。
  21. */
  22. ldmdar3,{r5-r7}
  23. /*r3为3f的物理地址,而r7为3f的虚拟地址。结果是r3为虚拟地址与物理地址的差值,即PHYS_OFFSET-PAGE_OFFSET。*/
  24. subr3,r3,r7@getoffsetbetweenvirt&phys
  25. /*r5为__proc_info_begin的物理地址,即r5指针__proc_info数组的首地址*/
  26. addr5,r5,r3@convertvirtaddressesto
  27. /*r6为__proc_info_end的物理地址*/
  28. addr6,r6,r3@physicaladdressspace
  29. /*读取r5指向的__proc_info数组元素的CPUID和mask值*/
  30. 1:ldmiar5,{r3,r4}@value,mask
  31. /*将当前CPUID和mask相与,并与数组元素中的CPUID比

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

网站地图

Top