linux内核启动解析(五)
发布时间:2012-4-1 09:59
发布者:李宽
关键词:
linux
freshtree 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()函数,进入操作系统环境。 |
网友评论