/*
* Enable the MMU.
*
* x0 = SCTLR_EL1 value for turning on the MMU.
* x27 = *virtual* address to jump to upon completion
*
* Other registers depend on the function called upon completion.
*
* Checks if the selected granule size is supported by the CPU.
* If it isn't, park the CPU
*/
ENTRY(__enable_mmu)
mrs x18, sctlr_el1 // preserve old SCTLR_EL1 value
mrs x1, ID_AA64MMFR0_EL1 //x1:0x1122
ubfx x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4 //x2:0
cmp x2, #ID_AA64MMFR0_TGRAN_SUPPORTED //相等
b.ne __no_granule_support
update_early_cpu_boot_status 0, x1, x2 //变量__early_cpu_boot_status赋值为0
其中x2=0
.macro str_l, src, sym, tmp //地址sym的内容是src
adrp \tmp, \sym //\sym的页地址,即12位地址对齐
str \src, [\tmp, :lo12:\sym] //:lo12:\sym 指\sym的低12位
.endm
__early_cpu_boot_status = x2 = 0
msr ttbr0_el1, x25 // load TTBR0 //x25:idmap_pg_dir
msr ttbr1_el1, x26 // load TTBR1 //x26:swapper_pg_dir
isb
msr sctlr_el1, x0 //sctlr_el1在__cpu_setup中赋值 开启mmu icache dcache等等, 其值下面分析
isb
/*
* Invalidate the local I-cache so that any instructions fetched
* speculatively from the PoC are discarded, since they may have
* been dynamically patched at the PoU.
*/
ic iallu
dsb nsh
isb
br x27
ENDPROC(__enable_mmu)
下面分析msr sctlr_el1, x0中x0的值,x0在__cpu_setup中赋值
分析x0值
w5=0xfcffffff
w6=0x34d5d91d
bic x0, x0, x5 // clear bits x0 = x0 & (~x5) x5反码后再相与
orr x0, x0, x6 // set bits
x0=0x34D5D91D 0b0011 0100 1101 0101 1101 1001 0001 1101
rk3399使用的指令集为ARMV8-A, 不支持ARMV8.2 列出bit为1的位解释 即
在EL0允许执行 a DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU指令
在EL0允许执行WFE指令,并不会陷入到EL1
在EL0允许执行WFI指令,并不会陷入到EL1
在EL0允许访问CTR_EL0
在EL0允许执行DC ZVA指令
最后一位是1(SCTLR_EL1.M是1)
1:表示EL0和EL1对normal memory的I cache访问没有影响(这里的理解是如果有影响即0,所有的指令对normal memory的访问,在EL1和EL0,都是non-cacheable。所以没有影响指是icache 打开了)
EL0 SP对齐检查。如果load或者store(ldr str)指令,在El0使用了sp寄存器,但是sp寄存器没有16byte对齐,则会产生一个sp对齐错误异常
EL1 SP对齐检查。如果load或者store(ldr str)指令,在El1使用了sp寄存器,但是sp寄存器没有16byte对齐,则会产生一个sp对齐错误异常
0表示在EL0和EL1数据对normal memoryde 访问,以及normal memory对EL1&EL0 stage 1地址转换表的访问都是non-cacheable
dcache打开
允许地址转换表