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 最后一句是跳轉(zhuǎn)到處理器初始化函數(shù)執(zhí)行。我們的處理器是armv6,所以處理器初始化函數(shù)可在arch/arm/mm/pro_v6.S中找到: ENTRY(cpu_v6_proc_init) mov pc, lr OK,到這里就知道,目的就是跳轉(zhuǎn)到__enable_mmu()函數(shù)執(zhí)行。至于r13,另有他用,在__enable_mmu()函數(shù)的最后可以看到。 建立好一級頁表后,這時(shí)我們就可以打開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。執(zhí)行到最后,把r13賦值給pc,就是跳轉(zhuǎn)到__swtich_data處執(zhí)行。 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 可見標(biāo)號(hào)__switch_data的值就等同于__mmap_switched()函數(shù)的指針地址。__mmap_switch()函數(shù)定義如下: __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) 這段代碼很簡單,就是拷貝數(shù)據(jù)到數(shù)據(jù)段;清BSS;然后保存處理器ID,機(jī)器類型和atag指針到內(nèi)存的相應(yīng)位置(因?yàn)榻酉聛砑纫絚語言環(huán)境執(zhí)行了,必須要把之前有意義的寄存器加以保存);跳轉(zhuǎn)到start_kernel()函數(shù),進(jìn)入操作系統(tǒng)環(huán)境。 |