在建好一页表之后,后面有几句这样的代码:
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处执行。
我们可以在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()函数,进入操作系统环境。
该系列文章列表:
用户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
用户1549494 2012-4-2 13:44
用户1404309 2012-4-2 09:19
用户1595216 2012-4-2 08:44
用户1602177 2012-3-31 16:15