CP15寄存器4,保留
对该寄存器的访问( 读或写) 结果无法预见。
CP15寄存器5,故障状态寄存器
访问:读/ 写
读CP 15 寄存器5,或故障状态寄存器(FSR),返回最后数据故障源,表示当数据中止出现时尝试访问的域与类型。
此外,将引起数据中止的虚拟地址写入故障地址寄存器(CP15 寄存器6)。
写CP 15 寄存器5,或故障状态寄存器(FSR),设置数据写入时FSR 值。用于调试器恢复FSR中值。
• Status[3:0]: 故障类型
说明故障类型。当数据中止出现时由MMU对状态域编码。状态域译码由域名及与数据中止相关的MVA(存于FAR中)确定。
• Domain[7:4]: 域
说明当故障出现时访问的域(D15 - D0)。
当写入时,未定义位为0,读出时结果无法预见。
CP15寄存器6,故障地址寄存器
访问:读/ 写
CP 15寄存器6,或故障地址寄存器(FAR),包含当最后故障出现时尝试访问的MVA 。FAR只会因数据故障而改变,不会因预取故障改变。
对FAR 的写性能,允许调试器保存一个先前状态。
CP15寄存器7,缓存工作寄存器
访问: 只写
CP15寄存器7,或缓存工作寄存器,用以管理指令缓存(ICache) 与数据缓存(DCache)。
每个缓存工作功能由pcode_2 及使用写CP15 寄存器7 的MCR 指令的CRm 域选定。
详细内容参照手册。
CP15寄存器8, TLB 工作寄存器
访问: 只读
CP15寄存器8,或转换后备缓冲器(TLB)工作寄存器,用于管理指令TLB与数据TLB。
使用opcode_2及写CP15 寄存器8 的MCR 指令中的CRm域选定TLB 工作 。
TLB:Translation Lookaside Buffer. 根据功能可以译为快表,直译可以翻译为旁路转换缓冲,也可以把它理解成页表缓冲.里面存放的是一些页表文件(虚拟地址到物理地址的转换表).当处理器要在主内存寻址时,不是直接在内存的物理地址里查找的,而是通过一组虚拟地址转换到主内存的物理地址,TLB就是负责将虚拟内存地址翻译成实际的物理内存地址,而CPU寻址时会优先在TLB中进行寻址.处理器的性能就和寻址的命中率有很大的关系.
二,为什么要引入TLB:
映射机制必须使一个程序能断言某个地址在其自己的进程空间或地址空间内,并且能够高效的将其转换为真实的物理地址以访问内存.一个方法是使用一个含有整个空间内所有页的入口(entry)的表(即页表),每个入口包含这个页的正确物理地址.这很明显是个相当大的数据结构,因而不得不存放于主存之中.
由于CPU首先接到的是由程序传来的虚拟内存地址,所以CPU必须先到物理内存中取页表,然后对应程序传来的虚拟页面号,在表里找到对应的物理页面号,最后才能访问实际的物理内存地址,也就是说整个过程中CPU必须访问两次物理内存(实际上访问的次数更多).因此,为了减少CPU访问物理内存的次数,引入TLB.。通常在ARM 的实现中每个内存接口有一个TLB。
· 有一个存储器接口的系统通常有一个唯一的TLB
· 指令和数据的内存接口分开的系统通常有分开的指令TLB 和数据TLB
当存储器中的转换表被改变或选中了不同的转换表(通过写CP15 的寄存器2),先前在TLB中的转换表遍历结果将不再有效。MMU 结构提供了刷新TLB 的操作。MMU 结构也允许特定的转换表遍历结果被锁定在一个TLB 中,这就保证了对相关的存储器区域的访问绝不会导致转换表遍历,这也对那些把指令和数据锁定在高速缓存中的实时代码有相同的好处。
试图用MRC 指令读CP15 寄存器8 的结果不确定。当只有很少量的存储器被重新映射时,无效的单一入口操作能被用来在一些实现中改善性能。对每个被重新映射的存储器区域(节、小页或大页),无效的单一入口需要在存储器区域的虚拟地址上执行。性能的改善来源于不用重新装载与没有被重新映射的存储器区域相关的TLB 入口。
---小心------
当存储器被重新映射时必须使与旧的映射相关的TLB 入口无效。如果不这样,可能会进入两个TLB 入口覆盖虚拟地址范围的状态。在最好的情况下访问这样的覆盖虚拟地址范围会有不可预料的结果;在某些实现中甚至会物理损坏MMU。强烈建议在重新映射存储器时要加倍小心使TLB 适当地失效。
------------
CP15寄存器9,缓存上锁寄存器
访问: 读/ 写
CP15寄存器9,或缓存上锁寄存器,复位时值为0x0。缓存上锁寄存器允许软件控制在ICache或DCache上的缓存线上载入填充。防止在填充时ICache 或 DCache 被驱逐,将其锁定在缓存中。
由CP15 寄存器9 读取返回缓存上锁寄存器值,即所有缓存段的基地址指针。只返回[31:26],其它值不可预见。
对CP15 寄存器9 写入更新缓存上锁寄存器,所有缓存段基地址与当前地址指针更新。
CP15寄存器10, TLB 上锁寄存器
访问: 读/ 写
CP15寄存器10,或 TLB上锁寄存器复位时值为0x0。每个TLB均有一个TLSB上锁寄存器;opcode_2值确定访问哪个TLB寄存器:
• opcode_2 = 0x0 , D TLB 寄存器
• opcode_2 = 0x1, I TLB寄存器
转换表遍历的执行需要一定的时间,特别当访问慢速的主存储器时。在实时中断处理程序中,当TLB 不包含中断处理程序的转换和/或要访问的数据时,中断延迟回大量加长。
TLB 锁定是一些ARM 存储器系统的特性,它允许把特定的转换表遍历的结果装载到TLB 中。这种方式不会被后来的转换表遍历的结果覆盖。由CP15 寄存器10 设定。设 W=LOG2(TLB 入口数),如果需要的话取整(round-up),则CP15 寄存器10 的格式为:
如果具体的实现有分开的指令和数据TLB,那么有2 个不同的寄存器,由访问寄存器10 的MCR 或MRC 指令中的opcode2 字段选择:
opcode2 == 0 选择数据TLB 锁定寄存器
opcode2 == 1 选择指令TLB 锁定寄存器
如果具体的实现只有唯一的TLB,那么只有1 个寄存器,opcode2 字段应该为0。访问寄存器10 的MCR 或MRC 指令中的CRm 总应该为0。
写寄存器10 有如下结果:
victim 字段表示下次TLB 失败(miss)时,转换表遍历的结果替代哪个TLB 入口。Base 字段包含TLB 替换的策略,只使用从(base)到(TLB 入口-1)的TLB 入口,victim 应该在这个区间。
转换表遍历的结果在写到TLB 入口时,若P==1 则它被保护起来,不能被寄存器8的使整个TLB 失效操作影响;若P==0 则会被那些操作给失效掉。
---注------
如果TLB 的入口不是2 的N 次方,那么写到大于或等于TLB 入口数的TLB 入口的base 或victim 的值将不确定。
-----------
读寄存器10 将返回它的值。
CP15寄存器11, 12,保留
对这些寄存器的访问( 读或写) 结果不可预见。
CP15寄存器13, FCSE PID寄存器
访问: 读/ 写
CP15寄存器13,或快速前后切换扩展(FCSE)处理标识符(PID) 寄存器,复位时值为0x0。
由CP15 寄存器13读取返回FCSE PID值。
向CP15 寄存器13写入置位FCSE PID。
FCSE PID 设置ARM9TDMI 与缓存存储器MMU 间映射。
ARM9TDMI 地址范围为0 ~ 32 M字节,通过FCSE PID 转换。
CP15寄存器14, 保留
对这些寄存器的访问( 读或写) 结果不可预见。
CP15寄存器15,测试配置寄存器
CP15寄存器15,或测试配置寄存器用于测试。对该寄存器的访问( 读或写) 结果不可预见。
四、设置MMU
下面是一个设置MMU进行地址重映射的一个实例
对于实际编程工作而言,主要是确定如何编写页表中的内容并如何确定页表项地址。现举例如下:
假设物理地址为0x3000_0000~0x30ff_ffff(1M空间)的一块连续空间需映射为0x0000_0000~0x000f_ffff的一块连续空间:
1.确定页表项中的内容:把物理地址的基地址作为页表项的高12位(31bit~21bit),填写访问属性。假设可以读写,可以读缓存、写缓冲,这样该页表项内容为0x3000_C00E;
2.确定页表基地址,填写页表基地址到CP15寄存器的C2中。页表的基地址要为64KB对齐,此处为0x305f_c000;
3.计算出偏移地址,把内容填写到页表项地址中。页表项地址=页表基地址+(虚拟地址基地址>>18),如页表基地址为0x305f_c000,那么,页表项地址=0x305f_c000;
4.将页表项数值写到对应的页表项地址中。上例中,需要向地址0x305f_c000中写入0x3000_COOE。
下面是程序的具体实现
;init MMU
;写MMU表到on chip sram from 0x60010000 to 0x60014000
import write_mmu_table
ldr r0,=table ;0x305f_c000
bl write_mmu_table ;
nop
nop
ldr r2,=0x55555555
mcr p15,0x0,r2,c3,c0,0 ;16个域均为0b01,客户模式
nop
nop
nop
nop
ldr r0,=table ;
mcr p15,0x0,r0,c2,c0,0 ;变换表基地址写入cp15 r2
nop
nop
nop
nop
mov r2,#0x7d ;0b0111 1101,使能cache,write buffer,MMU
mcr p15,0x0,r2,c1,c0,0
nop
nop
nop
nop
nop
nop
就这些,mmu初始化完了
write_mmu_table()是c的小程序,往ram写地址转换的描述
void write_mmu_table(UINT32 *base)
{
UINT32 *p_table;
UINT32 description;
UINT32 i;
p_table = base;
description = 0x3000_C00E; //页表项的值
*p_table = description;
p_table++;
description = 0x31000c10 //下面使除了上面映射地址之外,所有的虚拟地址都为无效
//地址..bits[1:0]==0b00,所关联的地址没有被映射
for (i=1;i<4096;i++)
{
*p_table = description;
description = description +0x00100000;
p_table ++;
}//return;
}