一. CP15寄存器
mcr |
将ARM处理器的寄存器中的数据写到CP15中的寄存器中 |
mrc |
将CP15中的寄存器中的数据读到ARM处理器的寄存器中 |
4.1.2 CP15寄存器介绍
寄存器编号 |
基本作用 |
在MMU中的作用 |
在PU中的作用 |
0 |
ID编码(只读) |
ID编码和cache类型 |
|
1 |
控制位(可读写) |
各种控制位 |
|
2 |
存储保护和控制 |
地址转换表基地址 |
Cachability的控制位 |
3 |
存储保护和控制 |
域访问控制位 |
Bufferablity控制位 |
5 |
存储保护和控制 |
内存失效状态 |
访问权限控制位 |
6 |
存储保护和控制 |
内存失效地址 |
保护区域控制 |
7 |
高速缓存和写缓存 |
高速缓存和写缓存控制 |
|
8 |
存储保护和控制 |
TLB控制 |
保留 |
9 |
高速缓存和写缓存 |
高速缓存锁定 |
|
10 |
存储保护和控制 |
TLB锁定 |
保留 |
13 |
进程标识符 |
进程标识符 |
|
CP15的寄存器C0
CP15中寄存器C0对应两个标识符寄存器,由访问CP15中的寄存器指令中的<opcode_2>指定要访问哪个具体物理寄存器,<opcode_2>与两个标识符寄存器的对应关系如下所示:
0b000 |
主标识符寄存器 |
0b001 |
cache类型标识符寄存器 |
1)主标识符寄存器
访问主标识符寄存器的指令格式如下所示:
mrc p15, 0, r0, c0, c0, 0 ;将主标识符寄存器C0,0的值读到r0中
ARM不同版本体系处理器中主标识符寄存器的编码格式说明如下。
ARM7之后处理器的主标识符寄存器编码格式如下所示:
31 24 23 20 19 16 15 4 3 0 |
|||||
由生产商确定 |
产品子编号 |
ARM体系版本号 |
产品主编号 |
处理器版本号 |
|
位 |
说 明 |
||||
位[3: 0] |
生产商定义的处理器版本号 |
||||
位[15: 4] |
生产商定义的产品主编号,最高4位可能的取值为0~7但不能是0,7 |
||||
位[19: 16] |
0x1 ARM体系版本4 |
||||
位[23: 20] |
生产商的产品子编号,使用子编号来区分不同的产品子类,如产品中不同的高速缓存的大小等 |
||||
位[31: 24] |
生产厂商的编号0x41 =A ARM公司;0x69 =I intel公司 |
2)cache类型标识符寄存器
访问cache类型标识符寄存器的指令格式如下所示:
mrc p15, 0, r0, c0, c0, 1 ;将cache类型标识符寄存器C0,1的值读到r0中
ARM处理器中cache类型标识符寄存器的编码格式如下所示:
位[28: 25] |
指定控制字段位[24: 0]指定的属性之外的cache的其他属性 |
位[24] |
定义系统中的数据cache和指令cache是分开的还是统一的: 0 系统的数据cache和指令cache是统一的; 1 系统的数据cache和指令cache是分开的 |
位[23: 12] |
定义数据cache的相关属性,如果位[24]为0,本字段定义整个cache的属性 |
位[31: 24] |
定义指令cache的相关属性,如果位[24]为0,本字段定义整个cache的属性 |
其中控制字段位[28:25]的含义说明如下:
编 码 |
cache类型 |
cache内容清除方法 |
cache内容锁定方法 |
0b0000 |
写通类型 |
不需要内容清除 |
不支持内容锁定 |
0b0001 |
写回类型 |
数据块读取 |
不支持内容锁定 |
0b0010 |
写回类型 |
由寄存器C7定义 |
不支持内容锁定 |
0b0110 |
写回类型 |
由寄存器C7定义 |
支持格式A |
0b0111 |
写回类型 |
由寄存器C7定义 |
支持格式B |
cache块大小字段bits[1: 0]的含义如下所示:
编 码 |
cache块大小 |
0b00 |
2个字(8字节) |
0b01 |
4个字(16字节) |
0b10 |
8个字(32字节) |
0b11 |
16个字(64字节) |
CP15的寄存器C1
访问主标识符寄存器的指令格式如下所示:
mrc p15, 0, r0, c1, c0{, 0} ;将CP15的寄存器C1的值读到r0中
mcr p15, 0, r0, c1, c0{, 0} ;将r0的值写到CP15的寄存器C1中
CP15中的寄存器C1的编码格式及含义说明如下:
M |
0:禁止MMU或者PU;1:使能MMU或者PU |
A |
0:禁止地址对齐检查;1:使能地址对齐检查 |
C |
0:禁止数据/整个cache;1:使能数据/整个cache |
W |
0:禁止写缓冲;1:使能写缓冲 |
P |
0:异常中断处理程序进入32位地址模式;1:异常中断处理程序进入26位地址模式 |
D |
0:禁止26位地址异常检查;1:使能26位地址异常检查 |
L |
0:选择早期中止模型;1:选择后期中止模型 |
B |
0:little endian;1:big endian |
S |
在基于MMU的存储系统中,本位用作系统保护 |
R |
在基于MMU的存储系统中,本位用作ROM保护 |
F |
0:由生产商定义 |
Z |
0:禁止跳转预测功能;1:使能跳转预测指令 |
I |
0:禁止指令cache;1:使能指令cache |
V |
0:选择低端异常中断向量0x0~0x1c;1:选择高端异常中断向量0xffff0000~ 0xffff001c |
RR |
0:常规的cache淘汰算法,如随机淘汰;1:预测性淘汰算法,如round-robin淘汰算法 |
L4 |
0:保持ARMv5以上版本的正常功能;1:将ARMv5以上版本与以前版本处理器兼容,不根据跳转地址的bit[0]进行ARM指令和Thumb状态切换:bit[0]等于0表示ARM指令,等于1表示Thumb指令 |
CP15中的寄存器C2保存的是页表的基地址,即一级映射描述符表的基地址。
CP15中的寄存器C3定义了ARM处理器的16个域的访问权限。
CP15中的寄存器C5是失效状态寄存器,编码格式如下所示:
31 9 8 7 4 3 0 |
|||
UNP/SBZP |
0 |
域标识 |
状态标识 |
其中,域标识bit[7:4]表示存放引起存储访问失效的存储访问所属的域。
状态标识bit[3:0]表示放引起存储访问失效的存储访问类型,该字段含义如表4-3所示(优先级由上到下递减)。
表4-3 状态标识字段含义
引起访问失效的原因 |
状态标识 |
域标识 |
C6 |
终端异常(Terminal Exception) |
0b0010 |
无效 |
生产商定义 |
中断向量访问异常(Vector Exception) |
0b0000 |
无效 |
有效 |
地址对齐 |
0b00x1 |
无效 |
有效 |
一级页表访问失效 |
0b1100 |
无效 |
有效 |
二级页表访问失效 |
0b1110 |
有效 |
有效 |
基于段的地址变换失效 |
0b0101 |
无效 |
有效 |
基于页的地址变换失效 |
0b0111 |
有效 |
有效 |
基于段的存储访问中域控制失效 |
0b1001 |
有效 |
有效 |
基于页的存储访问中域控制失效 |
0b1101 |
有效 |
有效 |
基于段的存储访问中访问权限控制失效 |
0b1111 |
有效 |
有效 |
基于页的存储访问中访问权限控制失效 |
0b0100 |
有效 |
有效 |
基于段的cache预取时外部存储系统失效 |
0b0110 |
有效 |
有效 |
基于页的cache预取时外部存储系统失效 |
0b1000 |
有效 |
有效 |
基于段的非cache预取时外部存储系统失效 |
0b1010 |
有效 |
有效 |
CP15中的寄存器C6
CP15中的寄存器C5是失效地址寄存器,编码格式如下所示:
31 0 |
失效地址(虚拟地址) |
CP15中的寄存器C7
CP15的C7寄存器用来控制cache和写缓存,它是一个只写寄存器,读操作将产生不可预知的后果。
访问CP15的C7寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c7>, crm, <opcode_2> ;<rd>、<crm>和<opcode_2>的不同取值组合 实现不同功能
CP15中的寄存器C8
CP15的C8寄存器用来控制清除TLB的内容,是只写寄存器,读操作将产生不可预知的后果。
访问CP15的C8寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c8>, crm, <opcode_2> ;<rd>、<crm>和<opcode_2>的不同取值组合实现不同功能,见第4.2节
CP15中的寄存器C9
CP15的C9寄存器用于控制cache内容锁定。
访问CP15的C9寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c9>, c0, <opcode_2>
mrc p15, 0, <rd>, <c9>, c0, <opcode_2>
如果系统中包含独立的指令cache和数据cache,那么对应于数据cache和指令cache分别有一个独立的cache内容锁定寄存器,<opcode_2>用来选择其中的某个寄存器:
<opcode_2>=1选择指令cache的内容锁定寄存器;
<opcode_2>=0选择数据cache的内容锁定寄存器。
CP15的C9寄存器有A、B两种编码格式。编码格式A如下所示:
31 32-W 31-W 0 |
|
cache组内块序号index |
0 |
其中index表示当下一次发生cache未命中时,将预取的存储块存入cache中该块对应的组中序号为index的cache块中。此时序号为0~index-1的cache块被锁定,当发生cache替换时,从序号为index到ASSOCIATIVITY的块中选择被替换的块。
编码格式B如下所示:
31 30 W W-1 0 |
|||
L |
0 |
cache组内块序号index |
|
位 |
说 明 |
||
L=0 |
当发生cache未命中时,将预取的存储块存入cache中该块对应的组中序号为index的cache块中 |
续表
位 |
说 明 |
L=1 |
如果本次写操作之前L=0,并且index值小于本次写入的index,本次写操作执行的结果不可预知;否则,这时被锁定的cache块包括序号为0~index-1的块,当发生cache替换时,从序号为index到ASSOCIATIVITY的块中选择被替换的块 |
CP15的寄存器C10
CP15的C10寄存器用于控制TLB内容锁定。
访问CP15的C10寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c10>, c0, <opcode_2>
mrc p15, 0, <rd>, <c10>, c0, <opcode_2>
如果系统中包含独立的指令TLB和数据TLB,那么对应于数据TLB和指令TLB分别有一个独立的TLB内容锁定寄存器,<opcode_2>用来选择其中的某个寄存器:
<opcode_2>=1选择指令TLB的内容锁定寄存器;
<opcode_2>=0选择数据TLB的内容锁定寄存器。
C10寄存器的编码格式如下:
31 30 32-W 31-W 32-2W 31-2W 1 0 |
|||||
可被替换的条目起始地址的base |
下一个将被替换的条目地址victim |
0 |
P |
||
位 |
说 明 |
||||
victim |
指定下一次TLB没有命中(所需的地址变换条目没有包含在TLB中)时,从内存页表中读取所需的地址变换条目,并把该地址变换条目保存在TLB中地址victim处 |
||||
base |
指定TLB替换时,所使用的地址范围,从(base)到(TLB中条目数-1);字段victim的值应该包含在该范围内 |
||||
P |
1:写入TLB的地址变换条目不会受使整个TLB无效操作的影响,一直保持有效;0:写入TLB的地址变换条目将会受到使整个TLB无效操作的影响 |
CP15的寄存器C13
C13寄存器用于快速上下文切换FCSE。
访问CP15的C13寄存器的指令格式如下所示:
mcr p15, 0, <rd>, <c13>, c0, 0
mrc p15, 0, <rd>, <c13>, c0, 0
C13寄存器的编码格式如下所示:
31 25 24 0 |
|
PID |
0 |
其中,PID表示当前进程的所在的进程空间块的编号,即当前进程的进程标识符,取值为0~127。
0:MVA(变换后的虚拟地址)= VA(虚拟地址),禁止FCSE(快速上下文切换技术),系统复位后PID=0;
非0:使能FCSE。
二.MMU原理介绍
ARM地址转换过程中涉及三个概念:virtual addr(VA),变换后的虚拟地址(不同进程使用相同虚拟地址的问题)(MVA),物理地址(PA).
三.MMU编程实例
MMU是由协处理器(cp15)控制的,最多会用到两级页表:以段(Section,1MB)的方式进行转换时只用到一级页表,以页(page)的方式进行转换时用到两级页表。页的大小有3种:大页(64KB),小页(4KB),极小页(1KB)。
条目也称为"描述符"(Descriptor),有:段描述符,大页描述符,小页描述符,极小页描述符----它们保存段、大页、小页或极小页的起始物理地址;粗页表描述符、细页表描述符---他们保存二级页表的物理地址
TTB保存了一级页表所存放的实际物理地址,要求16KB对齐,以段的方式映射,4GB的虚拟地址空间,需要段描述符4096个(每个段描述符映射1M空间),每个描述符占用4byte,所以映射一级页表占用的空间为16KB。
我们假设一级页表存放在物理地址:0x30000000.
第一步:
获得虚拟地址所对应的段描述符所在的地址
addr = TTB&0xffffc000 | ((viraddr >> 20) << 2 ) = 0x30000000 & 0xfffc000 | ((0xa0004000 >> 20) << 2)= 0x30000000 | (0xa00 << 2) = 0x30002800
第二步:
从0x30002800取出虚拟地址所对应的段描述符
段描述的构造我们到后面再来讲解,这里我们假设我们把0xa0004000映射到实际的物理地址0x30004000,则这里的[31:20]为0x300
第三步:
组合成实际的物理地址
phyaddr = 0x300 << 20 | (0xa0004000 & 0xfffff) = 0x30004000
三.实验
目标:以段的方式映射s3c2410的地址空间,一级页表存放在0x30000000
流程:
A.计算每个虚拟地址对应段描述符所在的地址(addr),方法如下:
B.构造段描述符
注意:Section base address 存放的是实际的物理地址的[31:20]
C.存放段描述符
(unsigned int *)addr = section descriptor
实例代码:
/*页表项内容*/
#define PAGE_TABLE_SECTION_AP (0x01 << 10)
#define APGE_TABLE_SECTION_DOMAIN (0x0 << 5)
#define PAGE_TABLE_SECTION_CACHE_WB (0x0 << 2)
#define PAGE_TABLE_SECTION_4BIT (1 << 4)
#define PAGE_TABLE_SECTION_TYPE (0x2)
/*段大小*/
#define SECTION_SIZE 0x100000
//根据虚拟地址和页表基地址确定页表项所在的物理地址
unsigned int get_pgtindex_addr(unsigned int viraddr,unsigned int pgtaddr)
{
unsigned int addr;
/*[31:14]页表基地地址 [13: 2]虚拟地址>>20位得到的page index [1 : 0]总是为0,因为每一项占用4byte*/
addr = (pgtaddr & PAGE_TABLE_BASE_MASK) | (((viraddr & VIRADDR_MASK) >> 20) << 2);
return addr;
}
//获取页表项
unsigned int get_page_entry(unsigned int phyaddr)
{
unsigned int entry_value;
/*[31:20]section base address *[19:12] *[11:10]AP *[9] *[8:5]Domain
*[4]:1 *[3]:C *[2]:B *[1:0]:Type*/
entry_value = (phyaddr & PHYADDR_MASK) | PAGE_TABLE_SECTION_AP |\
PAGE_TABLE_SECTION_CACHE_WB | PAGE_TABLE_SECTION_4BIT|\
PAGE_TABLE_SECTION_TYPE;
return entry_value;
}
/*创建一级页表:段描述符*/
void create_page_table()
{int i;
unsigned int pgt_index_addr;
unsigned int viraddr,phyaddr,pgtaddr;
/*在这里我们将0x00000000开始的1M物理空间映射到0x00000000开始的虚拟地址空间*/
phyaddr = SRAM_START_ADDR;
viraddr = phyaddr;
pgtaddr = PAGE_TABLE_BASE;
pgt_index_addr = get_pgtindex_addr(viraddr,pgtaddr);
*(volatile unsigned int *)pgt_index_addr = get_page_entry(phyaddr);
/*映射64MSDRAM*/
for(phyaddr = SDRAM_ADDR_START,viraddr = VMRAM_ADDR_START;
phyaddr < SDRAM_ADDR_END;phyaddr += SECTION_SIZE,viraddr += SECTION_SIZE)
{
pgtaddr = PAGE_TABLE_BASE;
pgt_index_addr = get_pgtindex_addr(viraddr,pgtaddr);
*(volatile unsigned int *)pgt_index_addr = get_page_entry(phyaddr);
}
/*映射IO地址空间*/
phyaddr = PHIO_ADDR_START;
viraddr = VMIO_ADDR_START;
pgtaddr = PAGE_TABLE_BASE;
pgt_index_addr = get_pgtindex_addr(viraddr,pgtaddr);
*(volatile unsigned int *)pgt_index_addr = get_page_entry(phyaddr);
return;
}
void init_mmu()
{
unsigned long mmu_table_base = PAGE_TABLE_BASE;
asm(
/*set Translation Table Base(TTB) register*/
"mrc p15,0,r0,c2,c0,0\n"
"mov r0,%0\n"
"mcr p15,0,r0,c2,c0,0\n"
/*set Domain Access Control register*/
"mrc p15,0,r0,c3,c0,0\n"
"mvn r0,#0\n"
"mcr p15,0,r0,c3,c0,0\n"
/*Enable MMU*/
"mrc p15,0,r0,c1,c0,0\n"
"orr r0, #0x1\n"
"mcr p15,0,r0,c1,c0,0\n"
"mov r0,r0\n"
"mov r0,r0\n"
"mov r0,r0\n"
:
:"r"(mmu_table_base)
:"r0"
);
return;
}
adrl r1,SMRDATA @13个寄存器值存放的地址
.ltorg @声明一个数据缓冲池的开始
SMRDATA:
.word 0x2201d110 @BWSCON 设置BANK3位宽16,使能nWait,使能UB/LB
.word 0x0700 @BANKCON0
.word 0x700 @BANKCON1
.word 0x700 @BANKCON2
.word 0x700 @BANKCON3
.word 0x700 @BANKCON4
.word 0x700 @BANKCON5
.word (3 << 15) + (1 << 0) @BANKCON6
.word 0x18001 @BANKCON7
.word (1 << 23) + (2 << 18) + (1256 << 0) @REFRESH
.word (1 << 7) + (1 << 0) @BANKSIZE
.word (3 << 4) @MRSRB6
.word (3 << 4) @MRSRB7