E500核中有两段地址空间,空间0和空间1,cpu指令和数据段使用哪一个空间可以由cpu的MSR寄存器的IS位和DS位做修改。而MMU将物理地址映射到哪个空间中的有效地址取决于MMU MAS1寄存器中的TS位。
E500核刚上电时,指令段和数据段都在空间0中,TLB1的Entry0默认设置为映射uboot的以_start_e500开始的4K空间,所有产生的空间0中的地址都由Entry0映射到物理地址上,但是Entry0只有4K的大小,如果要运行不在这4K空间的uboot代码,就必须要加大Entry0的size,如果使用Entry0映射的代码去修改Entry0的size,有可能会出现错误,所以为了保险,uboot源码在start.s中进入switch as段之前会在空间1中设置一个TLB1的Entry15,用来过渡阶段使用,映射整个uboot的代码区,Entry15共4M,足够覆盖512K的uboot代码,然后通过修改MSR的IS和DS位让CPU产生空间1中的地址,通过Entry15映射将的空间1的地址映射到物理地址上。这时候修改TLB1中的Entry,使得有Entry可以映射整个boot区(在本例中使用Entry2),最后在init_tlbs()函数之后使用Entry2映射cpu产生的在空间0上的地址。
下面是进入switch as之前设置Entry15,跳转到空间1中的代码
/*使用TLB1的Entry15*/
lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
/*设置空间1,大小为4M的映射*/
lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
/*设置epn*/
lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
/*设置rpn*/
lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
/*使用r6,r7,r8,r9里面的值分别配置MAS0,1,2,3*/
mtspr MAS0,r6
mtspr MAS1,r7
mtspr MAS2,r8
mtspr MAS3,r9
isync
msync
tlbwe //将MAS0,1,2,3寄存器的值写入MMU的Entry。
lis r6,MSR_IS|MSR_DS@h
ori r6,r6,MSR_IS|MSR_DS@l//IS和DS置位,CPU使用空间1
lis r7,switch_as@h
ori r7,r7,switch_as@l
mtspr SPRN_SRR0,r7
mtspr SPRN_SRR1,r6
rfi //跳转到SRR0处,同时SRR1进MSR
下面是init_tlbs()函数中设置TLB1 Entry的代码:
/board/freescale/P2020ds/Tlb.c
/*设置TLB1的Entry0映射boot page*/
SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I,
0, 0, BOOKE_PAGESZ_4K, 1),
/*设置TLB1的Entry2映射整个Flash空间*/
SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE,
CONFIG_SYS_FLASH_BASE_PHYS ,
MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
0, 2, BOOKE_PAGESZ_256M, 1),
/cpu/MPC85XX/start.s
/*转换回 AS = 0 使用空间0*/
lis r3,(MSR_CE|MSR_ME|MSR_DE)@h
ori r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
mtmsr r3
isync