wacbbt 发表于 2011-11-07 15:57

__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

wacbbt 发表于 2011-11-09 09:28

呼唤高手.

jefby 发表于 2014-08-25 20:33

是在__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]
查看完整版本: __turn_mmu_on疑问