一个人勃一次不难,难的是勃一辈子……
最近分心的事很多,勃得越来越少了!
打开mmu是一件神圣的工作,需要仔细、再仔细……
从__v7_setup函数返回来,进入到__enable_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))
结合数据手册,此段是将D0、D1两个域,D1对应于USER域,D0对应于KERNEL和TABLE域,配置为管理模式,对这两个域的访问和执行不受TLB中相应标志位影响,D2域,对应于IO域,配置为客户模式,对此域的访问受TLB中相应标志位的检查;
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
写入域访问控制寄存器,其实和__v7_setup函数中写入的值相同;
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
__v7_setup函数中也已经写过这个寄存器了;
b __turn_mmu_on
__turn_mmu_on就在后面紧跟着,不明白为何还要b一下;
ENDPROC(__enable_mmu)
再看看紧接着的__turn_mmu_on函数:
/*
* Enable the MMU. This completely changes the structure of the visible
* memory space. You will not be able to trace execution through this.
* If you have an enquiry about this, *please* check the linux-arm-kernel
* mailing list archives BEFORE sending another post to the list.
*
* r0 = cp#15 control register
* r13 = *virtual* address to jump to upon co