15.5 存储管理单元MMU
在创建多任务嵌入式系统时,最好有一个简单的方式来编写、装载及运行各自独立的任务。目前大多数的嵌入式系统不再使用自己定制的控制系统,而使用操作系统来简化这个过程。较高级的操作系统采用基于硬件的存储管理单元MMU来实现上述操作。
MMU提供的一个关键服务是使各个任务作为各自独立的程序在其自己的私有存储空间中运行。在带MMU的操作系统控制下,运行的任务无须知道其他与之无关的任务的存储需求情况,这就简化了各个任务的设计。
MMU提供了一些资源以允许使用虚拟存储器(将系统物理存储器重新编址,可将其看成一个独立于系统物理存储器的存储空间)。MMU作为转换器,将程序和数据的虚拟地址(编译时的连接地址)转换成实际的物理地址,即在物理主存中的地址。这个转换过程允许运行的多个程序使用相同的虚拟地址,而各自存储在物理存储器的不同位置。
这样存储器就有两种类型的地址:虚拟地址和物理地址。虚拟地址由编译器和连接器在定位程序时分配;物理地址用来访问实际的主存硬件模块(物理上程序存在的区域)。
15.5.1 MMU概述
内存管理单位MMU对处理器内存提供了很好的管理。这种管理主要是通过一个叫作传输表的数据结构来实现的。这个传输表存在于内存中,它有多个称为Entry的入口,每个入口定义了存储空间的一个页,页的大小从1KB到1MB,同时定义了这些页的属性。
ARM系统中,MMU主要完成以下工作:
① 虚拟存储空间到物理存储空间的映射,它能够实现从虚拟地址到物理地址的转换;
② 存储器访问权限的控制;
③ 设置虚拟存储空间的缓存特性。
MMU通过它的协处理器寄存器来确定传输表在内存中的位置,并通过这些寄存器来向ARM处理器提供内存访问错误信息。
从虚拟地址到物理地址的变换过程是查询传输表的过程,由于传输表放在内存中,这个查询过程通常代价很大。这个访问时间通常是1~2个内存周期。为了减少平均内存访问时间,ARM结构体系中采用一个容量更小(通常为8~16个字)、访问速度和CPU中通用寄存器相当的存储器件来存放当前访问需要的地址变换条目,它是一个小容量的Cache。这个小容量的页表Cache称为TLB(Translation Lookaside Buffer)。
注意 |
如果系统中使用数据和指令统一存储系统,那么TLB也将是统一的。如果系统是数据和指令分开的存储系统,那么TLB也将分为数据TLB和指令TLB。 |
MMU可以将整个存储空间分为最多16个域(domain)。每个域对应一定的内存区域,该内存区域具有相同的访问控制属性。MMU中寄存器c3用于控制与域有关的属性配置。
表15.20列出了与MMU有关的协处理器寄存器及其作用。
表15.20 与MMU有关的协处理器寄存器
协处理器寄存器 |
作 用 |
c1中某些位 |
配置MMU中的一些操作 |
c2 |
保存内存中页表基地址 |
c3 |
设置域访问权限 |
c4 |
保留 |
c5 |
内存访问失效状态标准 |
c6 |
内存访问失效时失效地址 |
c8 |
控制与清除TLB内容相关的操作 |
c10 |
控制与锁定TLB内容相关的操作 |
15.5.2 MMU与MPU
在ARM体系结构中,MMU将MPU的功能大大地增加,使系统内存管理更加灵活、方便。在MPU中引入了“域”的概念来管理内存,而且域是在专用寄存器中设置的。而MMU将域设置从寄存器移到了内存单位,这样使域的设置更加灵活,但同时也增加了系统访问时间。
另外,除了提供内存保护功能外,MMU还增加了虚拟地址到物理地址的映射。在只有MPU的系统中,每个任务被编译和运行在彼此不同的、固定的主存地址空间,每个任务只能在一个进程空间中运行,任何两个任务都不能在主存中有重叠地址。为了运行一个任务,一个保护区域被设置在固定地址的程序上,以允许任务访问由该区域定义的一段存储空间。保护区域的放置使得该任务得以运行,而其他任务空间被保护。
而使用MMU中虚拟地址到物理地址的映射功能,即使任务被编译、连接、运行在主存中有重叠地址的区域中,它们仍然可以运行。MMU中对虚存的支持可使构建后的嵌入式系统具有多个虚拟存储映射和单个物理存储器映射。每个任务拥有自己的虚拟存储器映射,以编译和连接组成此任务的代码和数据。内核层管理各个任务在物理存储器中的放置,使得它们在物理存储器中拥有彼此不同的地址,这个地址与其设计时的虚拟运行地址不一样。
15.5.3 内存访问过程
当处理器产生一个内存访问请求时,将传输一个虚拟地址给MMU,MMU首先遍历TLB(如果使用分离的存储系统,它将分别遍历数据TLB和指令TLB)。如果TLB中不保护虚拟地址入口(Entry),那么它将转入保存在内存中的传输主表,来获得所有访问地址的物理地址和访问权限。一旦访问成功,它将新的虚拟地址入口(Entry)信息保存在TLB中,以备下次查询使用。
当得到了地址变换入口(Entry)后,将进行以下操作:
① 根据入口(Entry)中的C(cachable)控制位和B(Bufferable)控制位决定是否缓存该内存访问结果。
② 根据访问权限控制位和域访问控制位确定该内存访问是否被允许。如果该内存访问不被允许,CP15向ARM处理器报告存储访问中止。
③ 对应不允许缓存的存储访问,直接得到物理地址访问内存。对于允许缓存的存储访问,如果在Cache命中,则忽略物理地址;如果Cache没有命中,则使用物理地址访问内存,并把该数据块读到Cache中。
图15.23为带Cache的MMU存储访问示意图。
图15.23 带Cache的MMU存储访问示意图
15.5.4 MMU的使能与禁止
MMU的使能/禁止可以通过CP15寄存器的c1的bit[0]来控制。
· bit[0]=0,MMU禁止。
· bit[0]=1,MMU使能。
下面的例子显示了典型的MMU使能过程。
【例15.4】典型的MMU使能过程。
MRC p15,0,r0,c1,0,0
ORR r0,#01
MCR p15,0,r0,c1,0,0
当MMU被禁止时,存储访问执行下列过程。
① 当禁止MMU时,存储系统是否支持Cache和写缓存,根据不同芯片设计不同而有所不同(ARM公司将设计权交给芯片厂商)。
· 如果芯片规定当禁止MMU时禁止Cache和写缓存,则存储访问不考虑C、B控制位。
· 如果芯片规定禁止MMU时使能Cache和写缓存,则数据访问被视为无Cache(uncachable)和写缓存(unbufferable)的,即C=0、B=0。读取指令时,如果系统是统一的TLB,则C=0;如果使用分开的TLB,则C=1。
② 存储访问不受权限控制,MMU也不会产生存储访问中止信号。
③ 所有物理地址和虚拟地址相等,即使用平板存储模式。
使能/禁止MMU时需要注意以下几个问题。
· 在使能MMU之前,正确的传输表要在内存中事先建立,CP15的相关寄存器必须完成初始化操作。
· 如果使用的不是平板存储模式(物理地址和对应虚拟地址相等),在禁止/使能MMU时,虚拟地址和物理地址的对应关系发生变化,这时应该清除(Flush)Cache中的当前地址变换入口(Entry)。
· 如果完成禁止/使能MMU的代码的物理地址和虚拟地址不同,则禁止/使能MMU将带来很大麻烦,因此建议完成使能/禁止MMU的代码的物理地址和虚拟地址相同。
15.5.5 虚拟地址到物理地址的转换
(1)地址重定位
为了使任务有各自的虚拟存储器映射,MMU硬件采用地址重定位,在地址访问主存之前,转换有处理器输出的虚拟地址。当处理器产生一个虚拟地址时,MMU取出这个虚拟地址的高位,遍历传输表,从而形成一个物理地址。
虚拟存储空间到物理存储空间的映射是以内存块为单位进行的。也就是说,虚拟存储空间中一块连续的存储空间被映射到物理存储空间中同样大小的一块连续存储空间。
虚拟存储空间到物理存储空间地址重映射过程如图15.24所示。
图15.24 虚拟存储空间到物理存储空间地址重映射过程
ARM支持的存储块的大小有以下几种。
· 段(Sections):大小为1M的存储块。
· 大页(Large pages):大小为64KB。
· 小页(Small pages):大小为4KB。
· 极小页(Tiny Pages):大小为1KB。
段和大页只需通过一次映射就可以将虚拟地址转换成物理地址,也可以根据需要增加一级映射,采用两级映射的方式再将大页分成16KB的子页,小页分成1KB的子页。极小页不能再分,只能以1KB大小的整页为单位。
ARM在内存中存在两级页表以实现上述地址映射过程。
· 一级页表:一级页表包括两种类型的页表项,即保持指向二级页表起始地址的页表项和保存用于转换段(Section)地址的页表项。一级页表也称为段页表(section page table)。
· 二级页表:二级页表包含以大页和小页为单位的地址变换页表项。
一级页表将4G地址空间划分为多个1MB的段(Section),因此一级页表包含4096个页表项。一级页表是一个混合表,可以作为二级页表的目录表,也可以作为用于转换1MB段(也可视为1MB的虚拟页)的普通页表。当一级页表作为页目录时,其页表项包含的是代表1MB虚拟空间的二级页表指针。二级页表分为粗页表(Coarse)和细页表(Fine)。当一级页表用于转换一个1MB的段时,其页表项包含的是物理存储器中对应1MB页帧(page frame)的首地址。
注意 |
目录页表项和1MB的段页表项可以共存于一级页表中。 |
一个粗二级页表(Coarse)包含256个页表项,占有1KB的主存空间,每个页表项将一个4KB的虚拟存储块转换成一个4KB的物理存储块。粗二级页表支持4KB和64KB的页,页表项包含的是4KB或64KB的页帧地址。如果转换的是一个64KB的页,则对于每个64KB的页,同一个页表项必须在页表中重复16次。
一个细二级页表(Fine)有1024个页表项,占有4KB的主存空间,每个页表项转换一个1KB的存储块。细页表支持1KB、4KB、64KB虚存页,每个页表项包含1KB、4KB或64KB的物理页帧首地址。如果转换的是4KB的页,则同一个页表项必须在页表中连续重复4次;如果转换的是64KB的页,则同一个页表项需要在页表中连续重复64次。
一级页表和二级页表的特征如表15.21所示。
表15.21 一级页表和二级页表特征
类 型 |
页表占用的存储空间 (单位:KB) |
支持的页大小 (单位:KB) |
页表项数目 |
一级页表 |
16 |
1024 |
4096 |
粗二级页表 |
1 |
1,4,64 |
1024 |
细二级页表 |
4 |
1,4,64 |
256 |
(2)传输表基地址
当处理器发出地址请求信号,而其要求的虚拟地址没有包含在TLB中时,MMU将会初始化一个产生过程。传输过程需要的地址转换表——传输表的基地址存放在协处理器寄存器c2中,MMU通过此基地址找到传输表,准备一次地址传输过程。
(3)基于一级页表的地址变换过程
基于一级页表的地址变换过程是指从虚拟地址到物理地址的转换只需要一级页表就能完成的地址转换。一级页表地址转换过程如图15.25所示。
图15.25 一级页表地址转换过程
图15.25中,CP15寄存器c2中存放的是内存中一级页表的基地址。因为一级页表大小为16KB,也就是说,一级页表是16KB地址对齐的,所以c2中bits[13∶0]=0,bits[31∶14]为内存中页表基地址。
CP15的寄存器c2的bits[31∶14]和虚拟地址的bits[31∶20]结合作为一个31位数的高30位值,忽略32位值的最后两位,可以使用该值从页表中查到一个4字节的地址页表项。
一级页表支持以下4种类型的页表项。
· 1MB段转换项;
· 指向细二级页表的目录项;
· 指向粗二级页表的目录项;
· 产生中止异常的错误项。
系统通过页表项的低两位bits[1:0]来确定页表项的类型。页表项的格式要求二级页表的地址必须与其页大小的倍数对齐。一级页表的各种页表项的格式如图15.26所示。
图15.26 一级页表项
如果bits[1:0]=0b10时,该页表项为段描述符(Section Descriptor),段描述符定义了对应的1MB的虚拟存储空间的地址映射关系。
如果bits[1:0]=0b01时,该页表项包含了粗二级页表的物理地址。该粗二级页表定义了对应的1MB虚拟存储空间的地址映射关系。它可以实现以大页和小页为单位的地址映射。
如果bits[1:0]=0b11时,该页表项包含了细二级页表的物理地址。该细二级页表定义了对应的1MB虚拟存储空间的地址映射关系。它可以实现以大页、小页和极小页为单位的地址映射。
如果bits[1:0]=0b00时,说明此页表项是一个错误页表项。它将产生一个存储页错误。错误条件会导致预取指令中止或数据中止,这取决于具体的存储器访问类型。
(4)段描述符及其地址变换过程
如果一级页表页表项的bits[1∶0]=0b10,说明此页表项指向一个1MB的存储段。页表项的高12位代替虚拟地址的高12位来产生物理地址。该页表项还包含域属性、Cahche属性、缓冲器属性和访问权限属性。具体定义如表15.22所示。
表15.22 段页表项中各字段含义
字 段 |
含 义 |
bits[1:0] |
段页表项标识 |
bits[3:2] |
定义段的Cache和写缓存属性 |
bit[4] |
生产商定义 |
bits[8:5] |
本段所在的域 |
bit[9] |
当前未被使用,设置成0 |
bits[11:10] |
访问权限控制AP位,见表15.23 |
bits[19:12] |
当前未被使用,设置成0 |
bits[31:20] |
该段对应的物理空间基地址的高12位 |
表15.23 访问权限控制位的编码及其含义
访问权限控制AP |
S |
R |
特 权 模 式 |
用 户 模 式 |
0b00 |
0 |
0 |
不可访问 |
不可访问 |
0b00 |
1 |
0 |
只读 |
不可访问 |
0b00 |
0 |
1 |
只读 |
只读 |
0b00 |
1 |
1 |
不可预知 |
不可预知 |
0b01 |
X |
X |
读/写 |
无访问 |
0b10 |
X |
X |
读/写 |
只读 |
0b11 |
X |
X |
读/写 |
读/写 |
表中S和R位是CP15寄存器c1中的控制位,它们分别对应系统(S)和ROM(R)位。这两位用来在不同模式加速系统中访问大的存储块。
设置S位使得所有页具有不可访问权限,从而允许特权模式任务对页有读访问权限。因此通过改变CP15寄存器c1中的一位,所有标识为不可访问的空间一下子变为可用,而不需要改变每个页表项的AP位,节省了开销。
改变R位使得所有页具有不可访问权限,因而特权模式任务和用户模式任务对页都有读访问权限。同样,这一位可以加速对大块存储块的访问,而不需要修改许多页表项的值。
注意 |
地址转换过程中,在物理地址产生之前,将会按表2.22的编码对访问地址的权限进行检测。 |
基于段的地址变换过程如图15.27所示。
图15.27 基于段的地址变换过程
(5)粗二级页表描述符及其地址变换过程
如果一级页表项的bits[1∶0]=0b01,说明此页表项包含一个粗二级页表首地址指针,同时还包含一级页表项代表的1MB虚存段的域信息。粗页表必须与1KB的倍数地址对齐。页表项具体定义见表15.24。
表15.24 粗二级页表项中各字段含义
字 段 |
含 义 |
bits[1:0] |
粗二级页表描述符标识 |
bits[4:2] |
生产商定义 |
bits[8:5] |
域标识符 |
bit [9] |
当前未被使用,设置成0 |
bits[31:10] |
粗二级页表基地址,该地址1KB对齐 |
基于粗二级页表的地址变换过程如图15.28所示。
(6)细二级页表描述符及其地址变换过程
如果一级页表项的bits[1:0]=0b11,说明此页表项包含一个细二级页表首地址指针,同时还包含一级页表项代表的1MB虚存段的域信息。细页表必须与4KB的倍数地址对齐。页表项具体定义如表15.25所示。
图15.28 基于粗二级页表的地址变换过程
表15.25 细二级页表项中各字段含义
字 段 |
含 义 |
bits[1:0] |
细二级页表描述符标识 |
bits[4:2] |
生产商定义 |
bits[8:5] |
域标识符 |
bits [11:9] |
当前未被使用,设置成0 |
bits[31:12] |
细二级页表基地址,该地址4KB对齐 |
基于细二级页表的地址变换过程如图15.29所示。
(7)基于二级页表的地址变换过程
二级页表有4种可能的页表项:
· 定义64KB页帧属性的大(Large)页表项;
· 定义4KB页帧属性的小(Small)页表项;
· 定义1KB页帧属性的微(tiny)页表项;
· 访问中止异常的错误项。
系统通过页表项的最低位[1:0]来确定页表项的类型。二级页表的页表项格式如图15.30所示。
当bits[1:0]=0b01时,该页表项为大页表项,它包含了一个64KB物理存储块的基地址。如果页表是细二级页表,那么大页表项将在表中重复64次;如果页表是粗二级页表,那么大页表项将在表中重复16次。
图15.29 基于细二级页表的地址变换过程
图15.30 二级页表的页表项格式
当bits[1:0]=0b10时,该页表项为小页表项,它保存一个4KB物理存储块的基地址。如果页表是细二级页表,那么小页表项将在表中重复4次;如果页表是粗二级页表,那么大页表项只需在表中出现1次。
当bits[1:0]=0b11时,该页表项为微页表项,它保存一个1KB物理存储块的基地址。如果页表是细二级页表,那么微页表项只需在表中重复1次;微页表项不会出现在粗二级页表中,如果出现,那么访问结果不可预知。
当bits[1:0]=0b00时,该页表项产生存储页访问错误。错误条件会导致预取指中止或数据中止,这取决于具体的存储器访问类型。
(8)大页表描述符及其地址变换过程
如果二级页表项bits[1:0]=0b01,说明该页表项为大页表项,它不仅包含了一个64KB物理存储块基地址,同时还含有4组权限位域以及页的Cache和写缓存属性。每一组访问权限域代表虚存页的1/4,这些页表项可以看成是16KB子页,以更好的控制64KB页的访问权限。
具体定义如表15.26所示。
表15.26 大页表项中各字段含义
字 段 |
含 义 |
bits[1:0] |
大页表项类型标识符 |
bits[3:2] |
Cache和写缓存属性 |
bits[11:4] |
访问权限控制位,具体编码见表15.27。 一个大页分为4个子页 AP0子页0的访问权限 AP1子页1的访问权限 AP2子页2的访问权限 AP3子页3的访问权限 |
bits [15:12] |
当前未使用,应为0 |
bits[31:16] |
该大页对应的物理页帧的基地址的高16位 |
图15.31说明了基于大页表的地址变换过程。
图15.31 基于大页表的地址变换过程
(9)小页表描述符及其地址变换过程
如果二级页表项bits[1∶0]=0b10,说明该页表项为小页表项,它不仅包含了一个4KB物理存储块基地址,同时还含有4组权限位域以及页的Cache和写缓存属性。每一组访问权限域代表虚存页的1/4,这些页表项可以看成是1KB子页,以更好的控制4KB页的访问权限。
页表项的具体定义如表15.27所示。
表15.27 小页表项中各字段含义
字 段 |
含 义 |
bits[1:0] |
小页表项类型标识符 |
bits[3:2] |
Cache和写缓存属性 |
bits[11:4] |
访问权限控制位,具体编码见表15.22。 一个小页分为4个子页 AP0子页0的访问权限 AP1子页1的访问权限 AP2子页2的访问权限 AP3子页3的访问权限 |
bits [15:12] |
当前未使用,应为0 |
bits[31:16] |
该小页对应的物理页帧的基地址的高20位 |
图15.32说明了基于小页表的地址变换过程。
图15.32 基于小页表的地址变换过程
(10)微页表描述符及其地址变换过程
如果二级页表项bits[1∶0]=0b11,该二级页表项是微页表项,它提供了一个1KB物理存储块的基地址,同时含有一个访问权限位域以及页的Cache和写缓存属性。微页表项的具体含义如表15.28所示。
表15.28 微页表项中各字段含义
字 段 |
含 义 |
bits[1:0] |
微页表项类型标识符 |
bits[3:2] |
Cache和写缓存属性 |
bits[5:4] |
访问权限控制位,具体编码见表15.29 |
bits [9:6] |
当前未使用,应为0 |
bits[31:10] |
该微页对应的物理页帧的基地址的高22位 |
图15.33说明了基于微页表的地址变换过程。
图15.33 基于微页表的地址变换过程
注意 |
ARMv6体系结构不包含微页,如果打算创建一个很容易移植到以后体系结构的系统,则建议在该系统中避免使用1KB微页。 |
15.5.6 域(domain)和存储器访问权限
域指的是一些段、大页或者小页的集合。编程的中,设计者最多可以使用16个域,每个域的访问控制特征由CP15中的c3中的两位控制。
CP15中的寄存器c3的格式如图15.34。
图15.34 CP15寄存器c3编码格式
其中,每两个位控制一个域的访问控制特性,其编码及对应的含义如表15.29所示。
表15.29 域访问控制字段编码及含义
控制位编码 |
访问类型 |
含 义 |
0b00 |
无访问权限 |
这时访问该域将产生访问失效 |
0b01 |
客户类型(client) |
根据页表中地址变换页表项的域访问权限控制位决定是否允许特定的存储访问 |
0b10 |
保留 |
使用该值会产生不可预知的结果 |
0b11 |
管理者权限(Manager) |
不考虑页表中页表项内的访问控制权限位,所以这种情况下不产生访问失效 |
综上所述,有两种不同的控制来管理一个任务的存储器访问权限。
· 管理者(manager)用于主控(primary control),不考虑每个段、大页和小页的访问权限。
· 客户(client)使用页表中的访问权限用于次控(secondary control)。
当多个段或者页从属于一个域时,这些段或者页的访问权限可以很容易的由域来统一控制。存储器采用这种管理策略将不同的存储单元“打包”。
注意 |
即使不使用MMU提供的虚拟存储功能,仍然可以把这些内核用作简单的存储保护单元。首先将虚拟存储空间直接映射到物理存储空间,然后为每个任务分配一个不同的域,最后使用这些域来保护睡眠任务(通过将它们的域访问设置成不可访问)。 |
15.5.7 与TLB相关的操作
(1)清除TLB
如果操作系统改变了页表中的数据,那么缓存在TLB中的转换数据可能就不再有效了。存储器核有一些CP15命令用于清除TLB,从而使TLB中的数据作废。表15.30是一些可用的命令:清除所有TLB数据,清除指令TLB,清除数据TLB,也可以一次只清除一行TLB数据。
表15.30 清除TLB的CP15命令
命 令 |
MCR指令 |
Rd的值 |
支持的内核 |
使所有TLB无效 |
MCR p15,0,Rd,c8,c7,0 |
0 |
ARM720T、ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
按行使TLB无效 |
MCR p15,0,Rd,c8,c7,1 |
要使之无效的虚拟地址 |
ARM720T |
使指令TLB无效 |
MCR p15,0,Rd,c8,c5,0 |
要使之无效的虚拟地址 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
按行使指令TLB无效 |
MCR p15,0,Rd,c8,c5,1 |
要使之无效的虚拟地址 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
使数据TLB无效 |
MCR p15,0,Rd,c8,c6,0 |
要使之无效的虚拟地址 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
按行使数据TLB无效 |
MCR p15,0,Rd,c8,c6,1 |
要使之无效的虚拟地址 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
下面的例子显示了一个使TLB无效的过程。
【例】一个使TLB无效的过程。
MOV r1,0;
MCR p15,0,r1,c8,c7,0
(2)锁定TLB
由于对TLB表的查询经常会使系统访问内存(要查询的段、页不在TLB中),这就使得系统的平均访问时间大大增加。对于实时系统,就需要将一些关键的页表项锁定在访问速度相对较快的TLB中。
ARM920T、ARM922T、ARM926EJ-S、ARM1022E和ARM1026EJ-S内核版本支持TLB转换数据的锁定。如果TLB中的某一行是锁定的,则当TLB清除命令发出时,它仍然保留在TLB中。
与TLB锁定相关的操作可以通过对CP15寄存器r10编程来实现。
各种ARM核的可用锁定命令如表15.31所示。
表15.31 访问TLB锁定寄存器的命令
命 令 |
MCR指令 |
Rd的值 |
支持的内核 |
读数据TLB锁定寄存器 |
MRC p15,0,Rd,c10,c0,0 |
TLB锁定 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
写数据TLB锁定寄存器 |
MCR p15,0,Rd,c10,c7,1 |
TLB锁定 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
读指令TLB锁定寄存器 |
MRC p15,0,Rd,c8,c5,0 |
TLB锁定 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
写指令TLB锁定寄存器 |
MCR p15,0,Rd,c8,c5,1 |
TLB锁定 |
ARM920T、ARM922T、ARM926EJ-S、ARM1022E、ARM1026EJ-S、StrongARM、Xscale |
其中Rd的格式如图15.35所示。
图15.35 Rd格式详解
其中,
· W=log2N,N为TLB中入口(entry)的个数。对ARM920T、ARM922T、ARM926EJ-S、ARM1022E版本的内核来讲,W=6;而对于ARM1026EJ-S内核版本,W=3。
· victm位域:确定下次被换出的TLB入口(entry)。
· base位域:从第0个入口(entry)到base −1入口的TLB值,被锁定。
锁定TLB中N条地址入口的操作序列如下。
① 确保在整个锁定过程中不会发生异常中断,可以通过禁止中断等方法实现。
② 如果锁定的是指令TLB或指令/数据统一的TLB,将base=N、victim=N、P=0写入寄存器c10。
③ 使整个将要锁定的TLB无效。
④ 如果要锁定指令TLB,确保与锁定过程有关的指令地址变换地址入口已经加载到指令TLB中。
注意 |
在此过程中,TLB的一个地址变换入口可以涵盖所有与锁定TLB相关的指令。这通常是由使整个TLB无效后的第一条指令实现的。 |
如果要锁定的是数据TLB,确保与锁定过程有关的数据地址变换地址入口已经加载到数据TLB中。
注意 |
在此过程中避免使用内嵌语法(inline literal)。所有锁定TLB用到的数据可以被TLB中一个地址变换条目所覆盖。 |
如果系统使用统一的数据TLB和指令TLB,上述两条都要保证。
⑤ 对于I=0到N,重复执行下列操作:
· 将base=I、victim=I、P=1写入寄存器c10中;
· 将每一条想要锁定到TLB的变换地址入口读取到TLB中。对于数据TLB和数据/指令统一的TLB可以使用LDR指令读取一个涉及该变换地址入口的数据,将该地址变换入口读取到TLB中。对于指令TLB,通过操作寄存器c7,将相应的变换地址读取到指令TLB中。
⑥ 将base=N、victim=N、P=0写入寄存器c10中。
要解除TLB中被锁定的变换地址入口,可以使用下面的操作序列。
① 通过操作寄存器c8,使TLB中各被锁定的变换地址入口无效。
② 将base=0、victim=0、P=0写入寄存器c10中。
15.5.8 存储访问失效
ARM中有两种存储访问失效(Fault)可以导致处理器停止执行。
· MMU失效(MMU Fault):由MMU检测到失效(Fault)并通知处理器。
· 外部存储器访问中止(External Abort):由外部存储器向存储器报告无效的存储器访问请求。
上述两种情况统称为存储访问中止(Abort)。如果存储访问中止发生在数据访问周期,CPU将产生数据访问中止异常中断(Data Abort);如果存储访问发生在指令预取周期,当该指令执行时,CPU产生指令预取异常中断(Prefetch Abort)。
注意 |
预取指令时发生错误,只有当该指令执行时,CPU才会产生指令预取异常中断。 |
(1)MMU失效
MMU可以产生4种类型的访问失效,分别是:
· 地址对齐失效(Alignment Fault);
· 地址变换失效(Translation Fault);
· 域控制失效(Domain Fault);
· 访问权限控制失效(Permission Fault)。
存储系统可以中止3种类型的存储访问:
· Cache行预取(line fetch);
· 无Cache和写缓存的存储器访问(uncached or unbuffered accesses);
· 传输表访问(translation table accesses)。
MMU失效优先于外部存储器访问中止请求。当存储访问失效发生时,系统控制协处理器中有两个寄存器分别负责保存发生中止的失效状态和地址。
注意 |
如果一条指令在预取阶段发生错误,它仍将进入指令流水线,直到该条指令被执行时,预取异常才发生。但当预取错误指令在进入执行阶段前,指令发生跳转,那么该预取异常不会发生,协处理器错误寄存器的状态也不会被更新。 |
(2)MMU中与存储访问失效相关的寄存器
MMU中与存储访问失效相关的寄存器有两个:
· 失效状态寄存器(FSR,Fault Status Register);
· 失效地址寄存器(FAR,Fault Address Register)。
失效状态寄存器是协处理器寄存器c5。失效地址寄存器为协处理器寄存器c6。
当存储访问失效发生时,失效状态寄存器中的字段被更新以反映所发生的存储访问失效的相关的信息,包括存储访问所属的域以及存储访问的类型。同时存储访问失效的虚拟地址被保存到地址寄存器c6中。
在数据访问周期发生存储访问失效更新了失效状态寄存器后,如果系统尚未进入存储异常模式,这时发生了指令预取引起的存储失效,则该指令预取引起的访问失效将不会更新失效状态寄存器的值。这样就保证了数据访问周期发生的存储访问失效状态信息不会被指令预取周期发生的存储访问失效破坏。
引起存储访问失效的存储访问类型如表15.32所示。
表中,对齐失效的编码可以为0b0001或0b0011。
表15.32 存储访问失效的存储访问类型
优先级 |
引起存储访问失效的原因 |
失效状态字段 |
域字段 |
失效地址寄存器c6 |
|
最高 |
极端异常(Terminal Exception) |
0b0010 |
无效 |
生产商定义 |
|
中断向量访问异常(Vector Exception) |
0b0000 |
无效 |
有效 |
||
地址对齐(Alignment) |
0b00x1 |
无效 |
有效 |
||
扩展地址变换失效(页表访问失效) |
一级页表 |
0b1100 |
有效 |
有效 |
|
二级页表 |
0b1110 |
无效 |
有效 |
||
地址变换失效 |
段失效 |
0b0101 |
无效 |
有效 |
|
页失效 |
0b0111 |
有效 |
有效 |
||
域控制失效 |
段失效 |
0b1001 |
有效 |
有效 |
|
页失效 |
0b1011 |
有效 |
有效 |
||
访问权限控制失效 |
段失效 |
0b1101 |
有效 |
有效 |
|
页失效 |
0b1111 |
有效 |
有效 |
||
基于Cache的外部存储访问系统异常 |
段失效 |
0b0100 |
有效 |
有效 |
|
页失效 |
0b0110 |
有效 |
有效 |
||
最低 |
非Cache预取时外部存储访问异常 |
段失效 |
0b1000 |
有效 |
有效 |
页失效 |
0b1010 |
有效 |
有效 |
在域控制字段(bits[3:0])中存在无效值,是因为无效发生在域访问之前。
当不同的存储访问类型同时引起存储访问失效时,按照优先级由高到低的次序,先保存优先级高的存储访问失效相关信息,在表中各存储访问优先级由上到下依次递减。
图15.36显示了判断存储访问失效的全过程。
下面分别介绍各种类型的存储访问失效方式。
① 极端异常(terminal exception)
极端异常指的是发生了不可恢复的存储访问失效。具体属于哪种情况,有生产商定义。
② 中断向量访问异常(vector exception)
在数据访问周期,如果访问异常中断向量表(地址0x0到0x1f)时发生存储访问失效,这种存储访问失效称为中断向量访问异常。当MMU被禁止时是否产生中断向量访问异常由生产商决定。
③ 地址对齐失效
在数据访问周期,如果访问字单元地址时地址bits[1:0]位不是0b00,或者访问半字单元时地址bits[0]位不是0b0,则产生的存储访问失效称为地址对齐失效。在指令预取周期不会产生地址对齐失效。在数据访问周期,如果访问字节单位,不会产生地址访问失效。
④ 地址变换失效
有两种类型的地址变换失效。一种是基于段的地址变换失效,它指当一级页表描述符的位bits[1:0]=0b00时,表示该一级描述符页表项无效,这时产生基于段的地址变换失效。第二种是基于页的地址变换失效。当二级描述符的位bits[1:0]=0b00时,表示该二级描述符页表项无效,这时产生基于页的地址变换失效。
图15.36 判断存储访问失效的全过程。
⑤ 域控制位失效
域控制位失效包括两种类型。一种基于段的存储访问域控制失效。在一级描述符中包含4位的域标识符。该标识符指定了本段所属的域,在MMU读取一级描述符时,它检查域访问控制寄存器c3中对应于该域的控制位,如果相应的两位控制位为0b00,说明该域不允许存储访问,这时,就产生了基于段的存储访问域控制失效。第二种是基于页的存储访问中域控制位失效。在一级描述符中包含4位的域标识符。该标识符指定了本页所属的域,在MMU读取一级描述符时,它检查域访问控制寄存器c3中对应于该域的控制位,如果相应的两位控制位为0b00,说明该域不允许存储访问,这时就产生了基于页的存储访问域控制失效。
⑥ 访问权限失效
访问权限失效的检查是在域控制位失效检查时进行的。这时如果域访问控制器中对应于该域的控制位为0b01,则要进行相应的权限检查。访问权限失效有两种类型。一种基于段的存储访问权限控制失效,对于基于段的存储访问,在一级描述符中包含一个两位的访问权限控制位AP。如果字段AP标识了不允许进行相关存储访问时,产出基于段的存储访问权限控制失效。第二种是基于页的存储访问控制失效。对于基于页的存储访问,在二级描述符中定义的可能为大页、小页或者微页。当二级描述符中定义的为微页时,该二级描述符中包含一个对应于该微页的访问控制字段AP,如果字段AP标识了不允许进行相关的存储访问,这时产生基于子页的存储访问权限控制失效。同样,当二级页表描述符中定义的为小页或大页时,操作过程同微页。
(3)外部存储访问失效
除处理器内部MMU向CPU报告错误外,ARM体系结构还定义了一个外部访问中断引脚。该引脚可以用于外部存储器向CPU访问失效异常。但是,并不是所有失效异常都可以通过这种方式报告,所以该引脚在连线时要非常注意。下面列举了存储访问操作,可以通过这种机制中止和重启动。
· 读操作(reads)。
· 非缓存的写操作(unbuffered writes)。
· 一级描述符预取(first-level descriptor fetch)。
· 二级描述符预取(second-level descriptor fetch)。
· 非缓存的信号量操作(semaphores in uncachable/unbufferablememory areas)。
在Cache预取时,可以在任意字时终止存储访问过程。如果存储访问发生在存储器想要获取的数据中,这时该存储访问将立即被中止。如果产生中止的数据是在Cache预取时,从存储器顺序读出的,那么直到这些数据被存储器访问时,该存储访问才会被中止。
带缓存的写操作不能通过这种方式向CPU报告异常。因此,在系统中标记为可外部中止的存储区域不要进行可缓存的写操作。
15.5.9 快速上下文切换扩展(FCSE,Fast Context Switch Extension)
(1)快速上下文切换扩展原理
快速上下文切换扩展(FCSE,Fast Context Switch Extension)是MMU中的一个附加硬件,用于提高ARM嵌入式系统的系统性能。FCSE使得多个独立任务可以运行在一个固定的重叠存储空间中,而在上下文切换时,不需要清理(clean)或清除(flush)Cache和TLB。FCSE主要特征就是不需要清除Cache和TLB。
通常情况下,如果两个进程占有的虚拟地址空间有重叠,系统在两个进程之间进行切换时,必须进行虚拟地址到物理地址的重映射。而虚拟地址到物理地址重映射涉及到重建MMU中页表,而且Cache及TLB中的内容都必须使无效。这样操作将带来巨大的系统开销,一方面重建MMU和使无效Cache及TLB的内容需要很大的开销,另一方面重建Cache和TLB内容也需要很大的开销。
快速上下文切换扩展的引入避免了这种开销。它位于CPU和MMU之间,如果两个进程使用了同样的虚拟地址空间,则对CPU而言,两个进程的空间地址是一样的。快速上下文切换扩展对各进程的虚拟地址进行变换,这样系统中CPU之外的部分看到的是经过快速上下文切换扩展变换的虚拟地址。快速上下文切换扩展将各进程的虚拟空间变换成不同的虚拟空间。这样在进行进程间切换时就不需要进行虚拟地址到物理地址的重映射。
快速上下文切换扩展将CPU发出的每个虚拟地址按照上述的规则进行变换,然后发送到系统中的其他部分。变换过程如图15.37所示。
图15.37 快速上下文切换扩展变换过程
使用快速上下文切换扩展,虚拟存储管理增加了一次地址转换。快速上下文切换扩展在虚拟地址到达Cache和TLB前,使用一个特殊的、包含进程ID值的重定位寄存器来修改虚地址。把第一次变换前的地址称为虚地址VA(Virtual Address),把第一次变换后的地址称为修改后虚拟地址MVA(Modified virtual Address)。
这样,任务间的切换就不用涉及到改变页表,只需简单地将新任务的进程ID写到位于CP15地FCSE进程ID寄存器。正是因为任务切换不需要改变页表,因而切换后Cache和TLB中的值依然保持有效,不需要清除。
ARM系统中,4GB的虚拟空间被分为128个进程空间快,每个进程空间块大小为32MB。每个进程空间块中可以包含一个进程,该进程可以使用虚拟地址空间0x00000000~0x01ffffff,这个地址范围也就是CPU看到的进程的虚拟空间。系统128个进程空间块的编号为0~127,编号为1的进程空间块中的进程实际使用虚拟地址空间为1×0x02000000~1×0x02000000+0x01ffffff。这个地址空间是系统中除CPU之外的其他部分看到的该进程所占有的虚拟地址空间。
由地址VA到MVA的变换算法如下所示。
MVA=VA+(ox02000000×进程ID)
保存在CP15寄存器c13寄存器中的值包含进程ID,c13中从bit[31]~bit[25]共7位标识进程ID,因此可以有128个进程。寄存器格式如图15.38。
图15.38 快速上下文切换寄存器c13
访问寄存器c13的指令格式如下所示:
MCR p15,0,<Rd>,<c13>,c0,0
MRC p15,0,<Rd>,<c13>,c0,0
其中,在读操作时,结果中位[31:25]返回PID,其他位的数值是不可预知的。写操作将设置PID的值。
当PID=0时,MVA=VA,相当于禁止了FCSE。系统复位后PID为0。
当正在运行的进程访问别的进程时,被访问的进程标识不能为0。这时,CPU发生的地址VA的高7位不是全0。
完整的VA到MVA的变换算法如下所示。
If (VA[31:25]==0b0000000)then
MVA=VA|(PID<<25=
Else
MVA=VA
(2)一个快速上下文切换的例子
图15.39显示了一个从任务1切换到任务2之前和之后的存储器布局。
任务1正在运行
任务2正在运行
图15.39 快速上下文切换扩展例子
从图中可以看出,任务1和任务2都运行在0x00000000~0x01ffffff的地址空间。从任务1切换到任务2域控制要做相应的改变。通过在CPU和MMU之间加FCSE使系统的虚拟地址空间映射没有改变,所以不需要清除(Flush)或清理(Clean)Cache或TLB。
使用FCSE时执行一次上下文切换需要的步骤:
① 保存执行任务的上下文,并将执行任务设置为睡眠态;
② 将唤醒任务的进程ID写到CP15的寄存器c13中;
③ 通过写CP15的寄存器c3,将当前任务的域设置为不可访问,而唤醒任务的域设置为客户访问;
④ 恢复唤醒任务的上下文;
⑤ 继续执行被恢复的任务。
下面是关于FCSE的一些提示。
① 任务在大小上有固定的最大32MB的限制。
② 存储管理必须使用有固定起始地址(32MB的倍数)的固定32MB分区。
③ 除非想为每个任务管理一个异常向量表,否则使用CP15寄存器c1的V位将异常向量表放置在虚拟地址0xffff0000。
④ 必须定义和使用一个活跃的域控制系统。
⑤ 如果使用域来保护各个任务,则除非修改一级页表中域的相应位,并在上下文切换时清除TLB,否则最多只能有16个并发任务。