arm linux 启动过程
时间:11-09
来源:互联网
点击:
- ART=PAGE_OFFSET+TEXT_OFFSET,
- *r0=((uint32_t*)(r4))[(KERNEL_START&0xff000000)>>20],
- *即r0指向KERNEL_START&0xff000000(即kernel以16M向下对齐的)虚拟地址,所在项表目录中的位置。
- addr0,r4,#(KERNEL_START&0xff000000)>>18
- /*r0=((uint32_t*)r0)[(KERNEL_START&0x00f00000)>>20]
- *执行前r0指向kernel以16M向下对齐的虚执地址,而这里再加上KERNEL_START未以16M向对齐部分的偏移量。
- *将原来r3的值写到页表目录中。R3的值就是之前已建立好va=pa映射的那个PA值。
- */
- strr3,[r0,#(KERNEL_START&0x00f00000)>>18]!
- /*r6为kernel镜像的尾部虚拟地址。*/
- ldrr6,=(KERNEL_END-1)
- /*指向下一个即将要填写的目录项*/
- addr0,r0,#4
- /*r6指向KERNEL_END-1虚拟地址所在的目录表项的位置*/
- addr6,r4,r6,lsr#18
- 1:cmpr0,r6
- /*每填一个目录项,后一个比前一个所指向的物理地址大1M。*/
- addr3,r3,#1<20
- strlsr3,[r0],#4
- bls1b
- #ifdefCONFIG_XIP_KERNEL
- /*忽略,不分析这种情况*/
- #endif
- /*通常kernel的启动参数由bootloader放到了物理内存的第1个M上,所以需要为RAM上的第1个M建立映射。
- *上面已为PHYS_OFFSET+TEXT_OFFSET建立了映射,如果TEXT_OFFSET小于0x00100000的话,
- *上面代码应该也为SDRAM的第一个M建立了映射,但如果大于0x0010000则不会。
- *所以这里无论如何均为SDRAM的第一个M建立映射(不知分析对否,还请指正)。
- */
- addr0,r4,#PAGE_OFFSET>>18
- orrr6,r7,#(PHYS_OFFSET&0xff000000)
- .if(PHYS_OFFSET&0x00f00000)
- orrr6,r6,#(PHYS_OFFSET&0x00f00000)
- .endif
- strr6,[r0]
- #ifdefCONFIG_DEBUG_LL
- /*略去*/
- #ifdefined(CONFIG_ARCH_NETWINDER)||defined(CONFIG_ARCH_CATS)
- /*略去*/
- #endif
- #ifdefCONFIG_ARCH_RPC
- /*略去*/
- #endif
- #endif
- movpc,lr
- ENDPROC(__create_page_tables)
一口气将__create_pages_table分析完,但里涉及的代码还是需要细细品读。尤其是右移20位和18位两个地方与页表目录项的地址关系比较复杂。执行完该函数后,虚拟内存和物理内存的映射关系如下图所示:
6. 开启MMU
看完页表的建立,想必开启MMU的代码也是小菜一碟吧。此函数的主要功能是将页表的基址加到cp15中的面表指针寄存器,同时设置域访问(domain access)寄存器。
[cpp]view plaincopyprint?
- /*
- *SetupcommonbitsbeforefinallyenablingtheMMU.Essentially
- *thisisjustloadingthepagetablepointeranddomainaccess
- *registers.
- */
- __enable_mmu:
- /*这里设置是否为非对齐内存访问产生异常*/
- #ifdefCONFIG_ALIGNMENT_TRAP
- orrr0,r0,#CR_A
- #else
- bicr0,r0,#CR_A
- #endif
- /*是否禁用数据缓存功能*/
- #ifdefCONFIG_CPU_DCACHE_DISABLE
- bicr0,r0,#CR_C
- #endif
- /*是否禁用CPU_BPREDICT?,不是很清楚此选项*/
- #ifdefCONFIG_CPU_BPREDICT_DISABLE
- bicr0,r0,#CR_Z
- #endif
- /*是否禁用指令缓存功能*/
- #ifdefCONFIG_CPU_ICACHE_DISABLE
- bicr0,r0,#CR_I
- #endif
- /*设置域访问寄存器的值。这里设置每个domain的属性是否上面建立的页表中,
- *每个目录项的damon值一起进行访问控制检查。具体情况请参考ARM处理器手册。
- */
- movr5,#(domain_val(DOMAIN_USER,DOMAIN_MANAGER)|\
- domain_val(DOMAIN_KERNEL,DOMAIN_MANAGER)|\
- domain_val(DOMAIN_TABLE,DOMAIN_MANAGER)|\
- domain_val(DOMAIN_IO,DOMAIN_CLIENT))
- mcrp15,0,r5,c3,c0,0@loaddomainaccessregister
- mcrp15,0,r4,c2,c0,0@loadpagetablepointer
- b__turn_mmu_on
- ENDPROC(__enable_mmu)
- /*
- *EnabletheMMU.Thiscompletelychangesthestructureofthevisible
- *memoryspace.Youwillnotbeabletotraceexecutionthroughthis.
- *Ifyouhaveanenquiryaboutthis,*please*checkthelinux-arm-kernel
- *mailinglistarchivesBEFOREsendinganotherposttothelist.
- *
- *r0=cp#15controlregister
- *r13=*virtual*addresstojumptouponcompletion
- *
- *otherregistersdependonthefunctioncalleduponcompletion
- */
- .align5
- __turn_mmu_on:
- movr0,r0
- /*将r0的值写到控制寄存器中。这里,终于开启MMU功能了。
- *查阅手册说控制寄存器的0位置1表示开启MMU,但这里r0的第0是多少呢(还请大家指正)
- */
- mcrp15,0,r0,c1,c0,0@writecontrolreg
- mrcp15,0,r3,c0,c0,0@readidreg
- /*这里的两个mov似乎是否流水线有关的,开启MMU语句后面几条是不能进行内存寻址的。但仍未搞明白具体东西的。*/
- movr3,r3
- movr3,r3
- /*转跳到r13的函数中去,r13为__mmap_switched函数的虚拟地址,
- *从stext函数的未尾可以找到它的赋值。故从此开始pc的值就真正在内存的虚拟地址空间了。
- */
- movpc,r13
- ENDPROC(__turn_mmu_on)
7.__mmap_switched函
armlinux启动过 相关文章:
- ARM Linux 的启动过程(11-09)
- ARM Linux启动过程学习(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)