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

ARM Linux 的启动过程

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

pe函数就是返回该对象指针。

这里涉及很多函数指针,它们都是在start_kernel函数里在各种阶段进行初始化的回函数。如map_io指向的tq2440_map_io就是在建立好内核页表后,再调用它来针对开发板的各种IO端口来建立相关的映射和页表。

至于__loopup_machine_type的代码就不作详细分析,请对比__lookup_processor_type来自行分析。代码如下:

[cpp]view plaincopy

  1. /*
  2. *Lookupmachinearchitectureinthelinker-buildlistofarchitectures.
  3. *Notethatwecantusetheabsoluteaddressesforthe__arch_info
  4. *listssincewearentrunningwiththeMMUon(andtherefore,weare
  5. *notinthecorrectaddressspace).Wehavetocalculatetheoffset.
  6. *
  7. *r1=machinearchitecturenumber
  8. *Returns:
  9. *r3,r4,r6corrupted
  10. *r5=mach_infopointerinphysicaladdressspace
  11. */
  12. __lookup_machine_type:
  13. adrr3,3b
  14. ldmiar3,{r4,r5,r6}
  15. subr3,r3,r4@getoffsetbetweenvirt&phys
  16. addr5,r5,r3@convertvirtaddressesto
  17. addr6,r6,r3@physicaladdressspace
  18. 1:ldrr3,[r5,#MACHINFO_TYPE]@getmachinetype
  19. teqr3,r1@matchesloadernumber?
  20. beq2f@found
  21. addr5,r5,#SIZEOF_MACHINE_DESC@nextmachine_desc
  22. cmpr5,r6
  23. blo1b
  24. movr5,#0@unknownmachine
  25. 2:movpc,lr
  26. ENDPROC(__lookup_machine_type)

[cpp]view plaincopy

  1. /*
  2. *Lookupmachinearchitectureinthelinker-buildlistofarchitectures.
  3. *Notethatwecantusetheabsoluteaddressesforthe__arch_info
  4. *listssincewearentrunningwiththeMMUon(andtherefore,weare
  5. *notinthecorrectaddressspace).Wehavetocalculatetheoffset.
  6. *
  7. *r1=machinearchitecturenumber
  8. *Returns:
  9. *r3,r4,r6corrupted
  10. *r5=mach_infopointerinphysicaladdressspace
  11. */
  12. __lookup_machine_type:
  13. adrr3,3b
  14. ldmiar3,{r4,r5,r6}
  15. subr3,r3,r4@getoffsetbetweenvirt&phys
  16. addr5,r5,r3@convertvirtaddressesto
  17. addr6,r6,r3@physicaladdressspace
  18. 1:ldrr3,[r5,#MACHINFO_TYPE]@getmachinetype
  19. teqr3,r1@matchesloadernumber?
  20. beq2f@found
  21. addr5,r5,#SIZEOF_MACHINE_DESC@nextmachine_desc
  22. cmpr5,r6
  23. blo1b
  24. movr5,#0@unknownmachine
  25. 2:movpc,lr
  26. ENDPROC(__lookup_machine_type)

5. 为kernel建立临时页表

前面提及到,kernel里面的所有符号在链接时,都使用了虚拟地址值。在完成基本的初始化后,kernel代码将跳到第一个C语言函数start_kernl来执行,在哪个时候,这些虚拟地址必须能够对它所存放在真正内存位置,否则运行将为出错。为此,CPU必须开启MMU,但在开启MMU前,必须为虚拟地址到物理地址的映射建立相应的面表。在开启MMU后,kernel指并不马上将PC值指向start_kernl,而是要做一些C语言运行期的设置,如堆栈,重定义等工作后才跳到start_kernel去执行。在此过程中,PC值还是物理地址,因此还需要为这段内存空间建立va = pa的内存映射关系。当然,本函数建立的所有页表都会在将来paging_init销毁再重建,这是临时过度性的映射关系和页表。

在介绍__create_table_pages前,先认识一个macro pgtbl,它将KERNL_RAM_PADDR – 0x4000的值赋给rd寄存器,从下面的使用中可以看它,该值是页表在物理内存的基础,也即页表放在kernel开始地址下的16K的地方。

[cpp]view plaincopy

  1. .macropgtbl,rd
  2. ldr\rd,=(KERNEL_RAM_PADDR-0x4000)
  3. .endm

[cpp]view plaincopy

  1. .macropgtbl,rd
  2. ldr\rd,=(KERNEL_RAM_PADDR-0x4000)
  3. .endm

[cpp]view plaincopy

  1. /*
  2. *Setuptheinitialpagetables.Weonlysetupthebarest
  3. *amountwhicharerequiredtogetthekernelrunning,which
  4. *generallymeansmappinginthekernelcode.
  5. *
  6. *r8=machinfo
  7. *r9=cpuid
  8. *r10=procinfo
  9. *
  10. *Returns:
  11. *r0,r3,r6,r7corrupted
  12. *r4=physicalpagetableaddress
  13. */
  14. __create_page_tables:
  15. /*r4=KERNEL_RAM_PADDR–0x4000=0x30004000
  16. *后面的C代码中的swapper_pg_dir变量,它的值也指向0x30004000
  17. *内存地址,不过它的值是虚拟内存地址,即0xc0004000
  18. */
  19. pgtblr4@pagetableaddress
  20. /*将从r4到KERNEL_RAP_PADDR的16K页表空间清空。*/
  21. movr0,r4
  22. movr3,#0
  23. addr6,r0,#0x4000
  24. 1:strr3,[r0],#4
  25. strr3,[r0],#4
  26. strr3,[r0],#4
  27. strr3,[r0],#4
  28. teqr0,r6
  29. bne1b
  30. /*还记得r10指向开发板相应的proc_info元素吗?这里它将的mm_mmuflags值读到r7中。
  31. *PROCINFO_MM_MMUFLAGS值为8,可对应上面列出来的__arm920_proc_info结构或你相应开发板结构的值来查看该mmu_flags值。
  32. *这里的flags就是用于设置目录项的flags。查看该mmu_flags的定义,发现它是要求一级页表是section。
  33. */
  34. ldrr7,[r10,#PROCINFO_MM_MMUFLAGS]

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

网站地图

Top