从前面可知由CPU的初始化函数里把MMU相关寄存器的值保存到r0寄存器,这样就传送给函数__enable_mmu,以便设置到MMU的寄存器里。函数__enable_mmu的代码如下:
__enable_mmu:
#ifdefCONFIG_ALIGNMENT_TRAP
orr r0, r0, #CR_A
#else
bic r0, r0, #CR_A
#endif
#ifdefCONFIG_CPU_DCACHE_DISABLE
bic r0, r0, #CR_C
#endif
#ifdefCONFIG_CPU_BPREDICT_DISABLE
bic r0, r0, #CR_Z
#endif
#ifdefCONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
这段代码是设置r0寄存器里MMU相关的参数。
mov r5,#(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
mcr p15, 0, r5, c3,c0, 0 @ load domain access register
这段代码是设置页的访问权限。
mcr p15, 0, r4, c2,c0, 0 @ load page table pointer
这里是把页目录地址r4寄存器的设置到页目录寄存器C2。
b __turn_mmu_on
这里跳到MMU打开的函数运行。
ENDPROC(__enable_mmu)
这个函数主要修改r0寄存器里MMU相关的参数,设置页目录访问的权限,设置页目录的地址到C2寄存器,最后跳到函数__turn_mmu_on里继续执行打开MMU的操作。函数__turn_mmu_on的代码如下:
__turn_mmu_on:
mov r0, r0
mcr p15, 0, r0, c1,c0, 0 @ write control reg
mrc p15, 0, r3, c0,c0, 0 @ read id reg
mov r3, r3
mov r3, r3
mov pc, r13
ENDPROC(__turn_mmu_on)
这段代码比较简单,主要把r0的MMU参数设置到C1寄存器里,然后再读取到r3寄存器,这样就把CPU设置为打开MMU了,进入虚拟地址变换处理。在设置后面进行两条无用的指令,以便TLB可以加载页目录到缓存里,最后通过mov pc,r13指令,就把__mmap_switched函数的虚拟地址切换到当前执行指令寄存器里,因为__switch_data结构的第一个参数就是函数__mmap_switched的地址。
由前面可知,已经把函数__mmap_switched地址给PC寄存器,那么就会运行这个函数的代码,这个函数的代码如下:
.type __switch_data,%object
__switch_data:
.long __mmap_switched
.long __data_loc @r4
.long __data_start @r5
.long __bss_start @r6
.long _end @ r7
.long processor_id @r4
.long __machine_arch_type @r5
.long __atags_pointer @r6
.long cr_alignment @r7
.long init_thread_union+ THREAD_START_SP @ sp
这段代码是定义切换分页的数据结构。
/*
* The followingfragment of code is executed with the MMU on in MMU mode,
* and uses absoluteaddresses; this is not position independent.
*
* r0 = cp#15control register
* r1 = machine ID
* r2 = atagspointer
* r9 = processorID
*/
__mmap_switched:
adr r3,__switch_data + 4
ldmia r3!, {r4, r5,r6, r7}
获取数据段和全局数据段的开始位置。
cmp r4, r5 @ Copydata segment if needed
1: cmpne r5, r6
ldrne fp, [r4], #4
strne fp, [r5], #4
bne 1b
如果数据段需要重定位,就拷贝数据段的内容。
mov fp, #0 @Clear BSS (and zero fp)
1: cmp r6, r7
strcc fp, [r6],#4
bcc 1b
清空BSS段的内容。
ldmia r3, {r4, r5,r6, r7, sp}
str r9, [r4] @Save processor ID
str r1, [r5] @Save machine type
str r2, [r6] @Save atags pointer
保存参数到__switch_data结构里。
bic r4, r0,#CR_A @ Clear 'A' bit
stmia r7, {r0,r4} @ Save control register values
保存控制寄存器。
b start_kernel
这里就跳到C语言的开始函数start_kernel运行了。
ENDPROC(__mmap_switched)
从这个函数就开始进入C语言初始化函数start_kernel,终于完成汇编代码的初始化动作,并且进入简单的分页内存管理机制。而start_kernel函数是在文件kernel/init/mail.c里定义,下一次继续这个文件里开始分析。
分享到:
相关推荐
Android Framework精编内核解析
Android内核剖析 柯元旦 Android内核剖析 柯元旦 Android内核剖析 柯元旦 Android内核剖析 柯元旦 Android内核剖析 柯元旦 Android内核剖析 柯元旦
使用objdump指令反汇编出的linux文件,方便学习linux启动流程分析,本内核在实际产品中应用,已经量产,可使用nodepad++打开查看,也可以用文本编辑器查看
从汇编到windows内核编程,想熟悉底层编程,从这本书开始!
Android Framework精编内核解析.pdf 百度网盘永久地址
Android 原生浏览器内核,包名 com.android.webview,内核版本116。 适用版本:Android API 24 及以上版本。 com.android.webview_116.0.5845.163-minAPI24.apk
Android framework 系统编译 新版WebView浏览器内核101.0.4951.61
Android各个版本与Linux内核的关系 获得某个内核分支的方法 获得Android某个版本的源码 查看android版本方法
android Framework精编内核解析
对于学习Linux内核的朋友会有一定的指导作用,因为内核里的汇编实在不好理解。
学习Linux内核需要学习的汇编,学习linux内核需要懂的汇编
Android内核和驱动篇-Android内核介绍
从汇编语言到Windows内核编程,程序员必看
Android和Linux内核版本对应关系
Android内核和驱动篇-Android内核介绍.txt
这个android kernel 是google发布android4.0时的内核,其实质是kernel3.0。由于网路的限制,我把他压缩的很少,方便自己上传和大家下载。
android手机的内核操作(命令) 1、 进入android手机的内核操作界面 adb Shell 2、 查看andorid根文件系统 #ls 查看全属性 #ls –l 查看所有文件,包括隐藏文件 #ls –a 3、 查看当前运行的所有进程 #ps 4、 查看...
Android4.0内核源代码,自己用Get获取的Android4.0内核源代码,需要的朋友自己拿去研究。