ARM Linux 的启动过程
时间:11-09
来源:互联网
点击:
- dent
- *manner.Seearch/arm/mm/proc-*.Sfordetails.r10=baseof
- *xxx_proc_infostructureselectedby__lookup_machine_type
- *above.Onreturn,theCPUwillbereadyfortheMMUtobe
- *turnedon,andr0willholdtheCPUcontrolregistervalue.
- */
- /*这里的逻辑关系相当复杂,先是从proc_info结构中的中跳进__arm920_setup函数,
- *然后执__enable_mmu函数。最后在__enable_mmu函数通过movpc,r13来执行__switch_data,
- *__switch_data函数在最后一条语句,鱼跃龙门,跳进第一个C语言函数start_kernel。
- */
- ldrr13,__switch_data@addresstojumptoafter
- @mmuhasbeenenabled
- adrlr,__enable_mmu@return(PIC)address
- addpc,r10,#PROCINFO_INITFUNC
- 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
- .section".proc.info.init",#alloc,#execinstr
- .type__arm920_proc_info,#object
- __arm920_proc_info:
- .long0x41009200
- .long0xff00fff0
- .longPMD_TYPE_SECT|\
- PMD_SECT_BUFFERABLE|\
- PMD_SECT_CACHEABLE|\
- PMD_BIT4|\
- PMD_SECT_AP_WRITE|\
- PMD_SECT_AP_READ
- .longPMD_TYPE_SECT|\
- PMD_BIT4|\
- PMD_SECT_AP_WRITE|\
- PMD_SECT_AP_READ
- /*__arm920_setup函数在stext的未尾被调用,请往回看。*/
- b__arm920_setup
- .longcpu_arch_name
- .longcpu_elf_name
- .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB
- .longcpu_arm920_name
- .longarm920_processor_functions
- .longv4wbi_tlb_fns
- .longv4wb_user_fns
- #ifndefCONFIG_CPU_DCACHE_WRITETHROUGH
- .longarm920_cache_fns
- #else
- .longv4wt_cache_fns
- #endif
- .size__arm920_proc_info,.-__arm920_proc_info
[cpp]view plaincopy
- .section".proc.info.init",#alloc,#execinstr
- .type__arm920_proc_info,#object
- __arm920_proc_info:
- .long0x41009200
- .long0xff00fff0
- .longPMD_TYPE_SECT|\
- PMD_SECT_BUFFERABLE|\
- PMD_SECT_CACHEABLE|\
- PMD_BIT4|\
- PMD_SECT_AP_WRITE|\
- PMD_SECT_AP_READ
- .longPMD_TYPE_SECT|\
- PMD_BIT4|\
- PMD_SECT_AP_WRITE|\
- PMD_SECT_AP_READ
- /*__arm920_setup函数在stext的未尾被调用,请往回看。*/
- b__arm920_setup
- .longcpu_arch_name
- .longcpu_elf_name
- .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB
- .longcpu_arm920_name
- .longarm920_processor_functions
- .longv4wbi_tlb_fns
- .longv4wb_user_fns
- #ifndefCONFIG_CPU_DCACHE_WRITETHROUGH
- .longarm920_cache_fns
- #else
- .longv4wt_cache_fns
- #endif
- .size__arm920_proc_info,.-__arm920_proc_info
[cpp]view plaincopy
- /*
- *ReadprocessorIDregister(CP#15,CR0),andlookupinthelinker-built
- *supportedprocessorlist.Notethatwecantusetheabsoluteaddresses
- *forthe__proc_infolistssincewearentrunningwiththeMMUon
- *(andtherefore,wearenotinthecorrectaddressspace).Wehaveto
- *calculatetheoffset.
- *
- *r9=cpuid
- *Returns:
- *r3,r4,r6corrupted
- *r5=proc_infopointerinphysicaladdressspace
- *r9=cpuid(preserved)
- */
- __lookup_processor_type:
- /*adr是相对寻址,它的寻计算结果是将当前PC值加上3f符号与PC的偏移量,
- *而PC是物理地址,因此r3的结果也是3f符号的物理地址*/
- adrr3,3f
- /*r5值为__proc_info_bein,r6值为__proc_ino_end,而r7值为.,
- *也即3f符号的链接地址。请注意,在链接期间,__proc_info_begin和
- *__proc_info_end以及.均是链接地址,也即虚执地址。
- */
- ldmdar3,{r5-r7}
- /*r3为3f的物理地址,而r7为3f的虚拟地址。结果是r3为虚拟地址与物理地址的差值,即PHYS_OFFSET-PAGE_OFFSET。*/
- subr3,r3,r7@getoffsetbetweenvirt&phys
- /*r5为__proc_info_begin的物理地址,即r5指针__proc_info数组的首地址*/
- addr5,r5,r3@convertvirtaddressesto
- /*r6为__proc_info_end的物理地址*/
- addr6,r6,r3@physicaladdressspace
- /*读取r5指向的__proc_info数组元素的CPUID和mask值*/
- 1:ldmiar5,{r3,r4}@value,mask
- /*将当前CPUID和mask相与,并与数组元素中的CPUID比
ARMLinux启动过 相关文章:
- arm linux 启动过程(11-09)
- ARM Linux启动过程学习(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)