原创 linux内核启动解析(五)

2012-3-31 16:15 2739 13 21 分类: 消费电子

1.5 __enable_mmu()

       在建好一页表之后,后面有几句这样的代码:

       ldr   r13, __switch_data        @ address to jump to after

                                          @ mmu has been enabled

       adr   lr, __enable_mmu          @ return (PIC) address

       add  pc, r10, #PROCINFO_INITFUNC

       最后一句是跳转到处理器初始化函数执行。我们的处理器是armv6,所以处理器初始化函数可在arch/arm/mm/pro_v6.S中找到:

ENTRY(cpu_v6_proc_init)

       mov pc, lr

       OK,到这里就知道,目的就是跳转到__enable_mmu()函数执行。至于r13,另有他用,在__enable_mmu()函数的最后可以看到。

       建立好一级页表后,这时我们就可以打开MMU,就可以放心大胆地使用虚拟地址了。使能MMU的代码如下:

__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)

 

__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)

      

       这段代码很简单,就是把一级页表的基地址放到CP15的c2中,然后打开MMU。执行到最后,把r13赋值给pc,就是跳转到__swtich_data处执行。

1.6 __mmap_switched()

       我们可以在arch/arm/kernel/head-common.S找到__switch_data的定义:

__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

 

       可见标号__switch_data的值就等同于__mmap_switched()函数的指针地址。__mmap_switch()函数定义如下:

__mmap_switched:

       adr   r3, __switch_data + 4

 

       ldmia       r3!, {r4, r5, r6, r7}

       cmp r4, r5                           @ Copy data 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

 

       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

       bic   r4, r0, #CR_A               @ Clear 'A' bit

       stmia       r7, {r0, r4}                   @ Save control register values

       b     start_kernel

ENDPROC(__mmap_switched)

       这段代码很简单,就是拷贝数据到数据段;清BSS;然后保存处理器ID,机器类型和atag指针到内存的相应位置(因为接下来既要跳到c语言环境执行了,必须要把之前有意义的寄存器加以保存);跳转到start_kernel()函数,进入操作系统环境。

 

该系列文章列表:

linux内核启动解析(一)

linux内核启动解析(二)

linux内核启动解析(三)

linux内核启动解析(四)

linux内核启动解析(五)

PARTNER CONTENT

文章评论8条评论)

登录后参与讨论

用户1652412 2012-5-12 09:59

感谢博主分享

用户1612414 2012-4-29 21:59

学习了。谢谢楼主

gflin_846028555 2012-4-6 09:52

多谢分享

用户1190942 2012-4-2 21:15

hao

用户1549494 2012-4-2 13:44

学习中

用户1404309 2012-4-2 09:19

看看先

用户1595216 2012-4-2 08:44

多谢LZ分享

用户1602177 2012-3-31 16:15

多谢博主分享~~
相关推荐阅读
用户1181832 2012-03-31 16:14
linux内核启动解析(四)
1.4 __create_page_tables()        __create_page_tables()函数同样也是位于arch/arm/kernel/head.S中,代码如下: ...
用户1181832 2012-03-31 16:13
linux内核启动解析(三)
  1.2 __lookup_machine_type() 机器类型的查找代码如下: __lookup_machine_type:        adr   r3, 3b   ...
用户1181832 2012-03-31 16:12
linux内核启动解析(二)
1.1 __lookup_processor_type() 话说内核映像解压后,又跳到c0008000这个地址。这个地址指向内核代码的什么地方,我们肯定很想知道。在arch/arm/kerne...
用户1181832 2012-03-31 16:09
linux内核启动解析(一)
1 linux内核启动过程分析        嵌入式linux系统从软件角度来看可分为四部分:bootloader,linux内核,文件系统和应用程序。在这里我选取的内核版本是linux2.6....
用户1181832 2012-03-16 11:22
起帆
       我的主要关注点是linux内核和驱动和bootloader。在将来的一段日子里,我会不定期的就以上几点写一些东西,以和大家共同探讨。         linux的真谛在于开放和共...
EE直播间
更多
我要评论
8
13
关闭 站长推荐上一条 /3 下一条