__turn_mmu_on疑问
在阅读arch/arm/kernel/head.S/head-common.s的反汇编代码时.对_turn_mmu_on部分始终搞不明白. 请大侠指点一下. 感激不尽.分析所得, 从__create_page_tables返回之后, r0 = 0x30007000.
在__enable_mmu的时候, 也只是或了个2, 也就是置了Abit,然后跳到下面
__turn_mmu_on, 这里r0 = 0x30007002,然后写cr1,网上说这个位置就mmu enable了,怎么理解呢.cp15 cr1的Mbit没见在哪置了1啊.
源代码里面的几个宏似乎也与Mbit无关. 怎么回事呢?
__enable_mmu:
#ifdef CONFIG_ALIGNMENT_TRAP
orr r0, r0, #CR_A
#else
bic r0, r0, #CR_A
#endif
#ifdef CONFIG_CPU_DCACHE_DISABLE
bic r0, r0, #CR_C
#endif
#ifdef CONFIG_CPU_BPREDICT_DISABLE
bic r0, r0, #CR_Z
#endif
#ifdef CONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
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
b __turn_mmu_on
ENDPROC(__enable_mmu)
板子是mini2440的.
/**
Image的入口, 起始地址是0x30008000
*/
00000000 <stext>:
0: e321f0d3 msr CPSR_c, #211 /**写CPSR, 0xd3, 1101 0011, mode = 10011, supervisor模式. */
4: ee109f10 mrc 15, 0, r9, cr0, cr0, {0} /**返回设备号.*/
8: eb000056 bl 168 <__lookup_processor_type> /**直接跳转到下面查询处理器类型.*/
c: e1b0a005 movs sl, r5/**如果异常返回0, 也就是eq置位, 跳转到__error.*/
10: 0a000052 beq 160 <__error>
14: eb00006c bl 1cc <__lookup_machine_type> /**查询机器类型.*/
18: e1b08005 movs r8, r5
1c: 0a00004f beq 160 <__error>
20: eb00007b bl 214 <__vet_atags> /**检查atags.*/
24: eb000013 bl 78 <__create_page_tables> /**创建页表.*/
28: e59fd0c0 ldr sp, /**栈指针=__mmap_switched*/
2c: e28fe000 add lr, pc, #0 /**返回地址是下面的__enable_mmu*/
30: e28af010 add pc, sl, #16 /**跳到__lookup_machine_type, 又回来跳到__enable_mmu?*/
00000034 <__enable_mmu>:
34: e3800002 orr r0, r0, #2 /**从__create_page_tables返回时, r0 = 0x30007000, 或, r0 = 0x30007002.*/
38: e3a0501f mov r5, #31 /**r5 = 0x1F.*/
3c: ee035f10 mcr 15, 0, r5, cr3, cr0, {0} /**将r5写入cp15-r3寄存器, enable域访问控制.*/
40: ee024f10 mcr 15, 0, r4, cr2, cr0, {0} /**r4 = 0x30004000, 写入页表基址.*/
44: ea000005 b 60 <__turn_mmu_on> /**跳到下面使能mmu?*/
48: e1a00000 nop ; (mov r0, r0)
4c: e1a00000 nop ; (mov r0, r0)
50: e1a00000 nop ; (mov r0, r0)
54: e1a00000 nop ; (mov r0, r0)
58: e1a00000 nop ; (mov r0, r0)
5c: e1a00000 nop ; (mov r0, r0)
00000060 <__turn_mmu_on>:
60: e1a00000 nop ; (mov r0, r0)
64: ee010f10 mcr 15, 0, r0, cr1, cr0, {0} /**r0这里等于0x30007002, control register*/
68: ee103f10 mrc 15, 0, r3, cr0, cr0, {0}
6c: e1a03003 mov r3, r3
70: e1a0300d mov r3, sp
74: e1a0f003 mov pc, r3
00000078 <__create_page_tables>:
78: e59f4068 ldr r4, /**指向下面e8的位置, r4 = 0x30004000, 也就是物理地址偏移16K的位置.*/
7c: e1a00004 mov r0, r4 /**r0 = r4*/
80: e3a03000 mov r3, #0 /**r3清零.*/
84: e2806901 add r6, r0, #16384/**r6 = 0x30008000*/
88: e4803004 str r3, , #4 /**清空0x30004000.*/
8c: e4803004 str r3, , #4 /**清空0x30004004.*/
90: e4803004 str r3, , #4 /**清空0x30004008.*/
94: e4803004 str r3, , #4 /**清空0x3000400C.*/
98: e1300006 teq r0, r6 /**循环, 全部清空, 至到0x30008000*/
9c: 1afffff9 bne 88 <__create_page_tables+0x10>
a0: e59a7008 ldr r7, /**此时的sl为__lookup_processor_type返回r5的值, 也就是下面1b8这个位置.
结果r7= .text.head*/
a4: e1a0600f mov r6, pc /**r6 = 下面的ac:, 0x300080AC*/
a8: e1a06a26 lsr r6, r6, #20 /**右移20位, r6 = 0x300. */
ac: e1873a06 orr r3, r7, r6, lsl #20 /**将r6的值向左移20位, 再与r7或, 结果保存在r3中. 也就是0x30000000和
.text.head(0xC0000000 + 0x00008000)或, 结果是r3 = 0xF0008000*/
b0: e7843106 str r3, /**r6再左移两位, 表达式变成str r3, , 也就将0xF0008000写入0x30004000中.*/
b4: e2840a03 add r0, r4, #12288 /**r0 = 0x30004000 + 0x3000 = 0x30007000*/
b8: e5a03000 str r3, ! /**将0xF0008000写入0x30007000地址, r0自增4.*/
bc: e59f6028 ldr r6, /**r6 = 0xFFFFFFFF*/
c0: e2800004 add r0, r0, #4 /**r0 +=4, r0 = 0x30007008*/
c4: e0846926 add r6, r4, r6, lsr #18 /**将r6, 右移18位, 等于0x00003FFF, 再加等于r4(0x30004000), 结果r6 = 0x30007FFF.*/
c8: e1500006 cmp r0, r6 /**下面会跳上来.*/
cc: e2833601 add r3, r3, #1048576 /**r3 = 0xF0008000 + 0x10000 = 0xF0108000, 也就是1M.*/
d0: 94803004 strls r3, , #4 /**如果r3 <= r0, 则写入, 也就是将0xF0108000+=1M写入0x30007008~0x30007FFF.*/
d4: 9afffffb bls c8 <__create_page_tables+0x50>
d8: e2840a03 add r0, r4, #12288 /**r0 = 0x30007000*/
dc: e3876203 orr r6, r7, #805306368 /**r7 = .text.head = 0xC0008000, r6 = r7|0x30000000 = 0xF0008000*/
e0: e5806000 str r6, /**又将0xF0008000写入0x30007000?, 0x30007004没写?*/
e4: e1a0f00e mov pc, lr /**函数返回.*/
e8: 30004000 andcc r4, r0, r0
ec: ffffffff undefined instruction 0xffffffff
ec: R_ARM_ABS32 _end
000000f0 <__switch_data>:
...
f0: R_ARM_ABS32 __mmap_switched
f4: R_ARM_ABS32 __data_loc
f8: R_ARM_ABS32 _data
fc: R_ARM_ABS32 __bss_start
100: R_ARM_ABS32 _end
104: R_ARM_ABS32 processor_id
108: R_ARM_ABS32 __machine_arch_type
10c: R_ARM_ABS32 __atags_pointer
110: R_ARM_ABS32 cr_alignment
114: 00001ff8 strdeqr1, , -r8
114: R_ARM_ABS32 init_thread_union 呼唤高手. 是在__v6_setup中设置的,有一段代码如下:
adr r5,v6_crval @将v6_crval的实际运行地址加载到r5处
ldmia r5,{r5,r6}@将r5地址处的两个字内容保存到r5和r6处,根据v6_crval定义可知,值为clear和mmuset,mmmuset的最后一个比特值为1,也就是CR_M=1
orr r0,r0,r6 @在此处将设置r0的bit0为1。随后在__turn_mmu_on中将MMU的值写入CP15的C1寄存器,真正使能MMU。
页:
[1]