e600 core MMU技术理解
MMU支持三种地址转换:
1. 页地址转换(每页4K)
2. 块地址转换(每块1=28K-256M)
3. 实地址转换(无地址转换-物理地址与虚地址一一对应)
CPU实现地址转换的机制:
MMU在关闭时,CPU处理地址就走蓝线所示路线,程序的逻辑地址就与物理地址一一对应,这地址包括CPU的4G的地址空间,不仅仅指内存部分。
当MMU打开后CPU处理地址就走红、黄两条路线,黄色路线是块地址转换,优先于页地址转换执行,逻辑地址到物理地址的转换是通过与BAT表比较实现的,BAT表一共有8组表项,4个指令BAT表项,4个数据BAT表项。这个表存放在SPR(特殊用途寄存器)528-SPR543中。在BSP中对于这个BAT表的设置是在sysLib.c中通过sysBatDesc数组实现的。根据VxWorks的内存管理的建议,虽然将内存地址同时映射成块地址和页地址是CPU允许的,但由于VxWorsk的缘故,这种做法会导致出错,所以块地址映射(BAT表)一般用于I/O地址映射,PROM,FLASH地址映射,由于BAT表无法不激活,所以不管在BAT表中放什么值都将会有一段地址空间被作为块地址寻址,这很容易与页地址映射造成冲突,所以在sp8240的BSP中8个BAT表项被全部用作FLASH地址空间的映射,避开了作为页地址映射的内存地址空间。
上图中的红线部分是逻辑地址到物理地址的页映射方式,页映射方式首先通过段描述符,确定逻辑地址是访问页地址还是直接存取段地址(建议不用),若是访问页地址,则根据页描述符中的内容生成一个52位的虚拟地址,MMU根据8240提供的TLB缓冲(内部寄存器)用于快速确定与52位虚拟地址对应的32位物理地址,若TLB缓冲中没有对应关系则根据内存中的页表确定。在BSP中对于页表PTE的设置(初始化)是通过sysPhysMemDesc数组实现的,对于内存的地址映射VxWorks一般通过页方式寻址,因此对于内存的保护等功能归根结底也是通过页表实现的。对于内存的页划分,可以事先指定通过sysPhysMemDesc数组,可以通过程序动态实现,所以对于内存保护也可以动态改变,因此页表大小必然会变化,下表是VxWorks给出的PPC8240的页表最小值。
内存容量 | 页表大小(至少) |
8M | 无论内存大小至少64K |
16M | 128K |
32M | 256K |
64M | 512K |
128M | 1M |
256M | 2M |
… | … |
对于页的大小,一般的CPU是8K,对于PPC架构的CPU是4K。
由于VxWorks的特性对于内存的地址管理一般都是通过页的方式实现的也就是一个从:逻辑地址->段描述符->虚拟地址->页表->物理地址的过程。
在整个地址转换过程中,地址要经过两次处理,通过段寄存器和页表,在段寄存器和页表中都保存了关于地址保护的信息,在经过段寄存器时可以侦测非法的取指操作,而在经过页表时可以侦测非法的地址访问。
段寄存器和页表的描述在VxWorks中定义在mmuPpcLib.h中,结构如下:
typedef union sr
{
struct
{
u_intt:1; /* SR 标志 0表示直接存取寻址(建议不用)1:页寻址 */
u_intks:1; /* Supervisor-state protection key */
u_intkp:1; /* User-state protection key */这两位用于在页寻址阶段与
MSR[PR]和页表的PP位一起判断当前操作处于用户模式还是核心模式,当前操作是否允许,三者的关系表见PPC8240的编程手册p294
u_intn:1; /* No-execute protection 用于在段寻址阶段判断取指是否合法*/
u_intreserved:4; /* reserved */
u_intvsid:24; /* 虚拟段号 */
}bit;
u_int value; /* SRvalue */
}SR;
typedef union pte /* PTE structure */
{
struct /* bitfield desciption */
{
u_intv:1; /*entry valid (v=1) or invalid (v=0) */
u_intvsid:24; /*Virtual Segment ID虚拟段号 */
u_inth:1; /* Hash functionidentifier */
u_intapi:6; /* Abbreviated pageindex */
u_intrpn:20; /*Physical page number 物理页号*/
u_intreserved1:3; /* reserved */
u_intr:1; /*Referenced bit 该表是否被访问过*/
u_intc:1; /*Changed bit 该表是否被改写过*/
u_intwimg:4; /* Memory/cache control bit*/
u_intreserved2:1; /* reserved */
u_intpp:2; /*Page protection bits见段表的kp,ks位 */
}field;
struct /* worddescription */
{
u_intword0; /* word 0 */
u_intword1; /* word 1 */
}bytes;
}PTE;
系统中的段寄存器设置是在MMU初始化时由mmuPpcLibInit函数根据sysPhysMemDesc数组设置的。而对于页表的设置则是通过mmuPpcPageMap函数实现的。VxWorks支持动态的页保护,因此提供了mmuPpcStateGet,mmuPpcStateSet函数用于获取页属性和设置页属性。