分类: LINUX
2015-05-18 17:23:51
原文地址:内存管理单元(MMU)介绍 作者:tomoowang
内存管理单元(MMU)介绍
MMU是存储器管理单元的缩写,是用来管理虚拟内存系统的器件。MMU通常是CPU的一部分,本身有少量存储空间存放从虚拟地址到物理地址的匹配表。此表称作TLB(转换旁置缓冲区)。所有数据请求都送往MMU,由MMU决定数据是在RAM内还是在大容量存储器设备内。如果数据不在存储空间内,MMU将产生页面错误中断。
MMU的两个主要功能是:
1. 将虚地址转换成物理地址。
2. 控制存储器存取允许。MMU关掉时,虚地址直接输出到物理地址总线。
在实践中,使用MMU解决了如下几个问题:
①使用DRAM作为大容量存储器时,如果DRAM的物理地址不连续,这将给程序的编写调试造成极大不便,而适当配置MMU可将其转换成虚拟地址连续的空间。
②ARM内核的中断向量表要求放在0地址,对于ROM在0地址的情况,无法调试中断服务程序,所以在调试阶段有必要将可读写的存储器空间映射到0地址。
③系统的某些地址段是不允许被访问的,否则会产生不可预料的后果,为了避免这类错误,可以通过MMU匹配表的设置将这些地址段设为用户不可存取类型。
启动程序中生成的匹配表中包含地址映射,存储页大小(1M,64K,或4K)以及是否允许存取等信息。
例如:目标板上的16兆DRAM的物理地址区间为0xc000,0000~0xc07f,ffff;0xc100,0000~0xc17f,ffff;16兆ROM的虚拟地址区间为:0x0000,0000~0x00ff,ffff。匹配表配置如下:
可以看到左边是连续的虚拟地址空间,右边是不连续的物理地址空间,而且将DRAM映射到了0地址区间。 MMU通过虚拟地址和页面表位置信息,按照转换逻辑获得对应物理地址,输出到地址总线上。
应注意到的是使能MMU后,程序继续运行,但是对于程序员来说程序计数器的指针已经改变,指向了ROM所对应的虚拟地址。
MMU的作用有两个
MMU的作用有两个:地址翻译和地址保护 软件的职责是配置页表,硬件的职责是根据页表完成地址翻译和保护工作。 那三个函数是用来访问页表的。如果cpu没有硬件MMU那么这张表将毫无意义。 你必须从cpu的角度去理解内存映射这个概念。内存映射不是调用一个函数,然后读取返回值。而是cpu通过MMU把一条指令中要访问的地址转换为物理地址,然后发送到总线上的过程。 有本书叫做understand linux kernel,耐心看,那本书写的非常好。
MMU是处理器复杂到一定程度出现的产物。这个东西和操作系统的内存管理如果结合起来学习和理解,效果最好。
嵌入式系统中,存储系统差别很大,可包含多种类型的存储器件,如FLASH,SRAM,SDRAM,ROM等,这些不同类型的存储器件速度和宽度等各不相同;在访问存储单元时,可能采取平板式的地址映射机制对其操作,或需要使用虚拟地址对其进行读写;系统中,需引入存储保护机制,增强系统的安全性。为适应如此复杂的存储体系要求,ARM处理器中引入了存储管理单元来管理存储系统。
一 内存管理单元(MMU)概述
在ARM存储系统中,使用MMU实现虚拟地址到实际物理地址的映射。为何要实现这种映射?首先就要从一个嵌入式系统的基本构成和运行方式着手。系统上电时,处理器的程序指针从0x0(或者是由0Xffff_0000处高端启动)处启动,顺序执行程序,在程序指针(PC)启动地址,属于非易失性存储器空间范围,如ROM、FLASH等。然而与上百兆的嵌入式处理器相比,FLASH、ROM等存储器响应速度慢,已成为提高系统性能的一个瓶颈。而SDRAM具有很高的响应速度,为何不使用SDRAM来执行程序呢?为了提高系统整体速度,可以这样设想,利用FLASH、ROM对系统进行配置,把真正的应用程序下载到SDRAM中运行,这样就可以提高系统的性能。然而这种想法又遇到了另外一个问题,当ARM处理器响应异常事件时,程序指针将要跳转到一个确定的位置,假设发生了IRQ中断,PC将指向0x18(如果为高端启动,则相应指向0vxffff_0018处),而此时0x18处仍为非易失性存储器所占据的位置,则程序的执行还是有一部分要在FLASH或者ROM中来执行的。那么我们可不可以使程序完全都SDRAM中运行那?答案是肯定的,这就引入了MMU,利用MMU,可把SDRAM的地址完全映射到0x0起始的一片连续地址空间,而把原来占据这片空间的FLASH或者ROM映射到其它不相冲突的存储空间位置。例如,FLASH的地址从0x0000_0000-0x00ff_ffff,而SDRAM的地址范围是0x3000_0000-0x31ff_ffff,则可把SDRAM地址映射为0x0000_0000-0x1fff_ffff而FLASH的地址可以映射到0x9000_0000-0x90ff_ffff(此处地址空间为空闲,未被占用)。映射完成后,如果处理器发生异常,假设依然为IRQ中断,PC指针指向0x18处的地址,而这个时候PC实际上是从位于物理地址的0x3000_0018处读取指令。通过MMU的映射,则可实现程序完全运行在SDRAM之中。
在实际的应用中,可能会把两片不连续的物理地址空间分配给SDRAM。而在操作系统中,习惯于把SDRAM的空间连续起来,方便内存管理,且应用程序申请大块的内存时,操作系统内核也可方便地分配。通过MMU可实现不连续的物理地址空间映射为连续的虚拟地址空间。
操作系统内核或者一些比较关键的代码,一般是不希望被用户应用程序所访问的。通过MMU可以控制地址空间的访问权限,从而保护这些代码不被破坏。
二MMU地址映射的实现
MMU的实现过程,实际上就是一个查表映射的过程。建立页表(translate table)是实现MMU功能不可缺少的一步。页表是位于系统的内存中,页表的每一项对应于一个虚拟地址到物理地址的映射。每一项的长度即是一个字的长度(在ARM中,一个字的长度被定义为4字节)。页表项除完成虚拟地址到物理地址的映射功能之外,还定义了访问权限和缓冲特性等。
1、映射存储块的分类
MMU 支持基于节或页的存储器访问,MMU可以用下面四种大小进行映射:
节(Section) 构成1MB 的存储器块
支持3 中不同的页尺寸:
微页(Tiny page) 构成1KB 的存储器块
小页(Small page) 构成4KB 的存储器块
大页(Large page) 构成64KB 的存储器块
其中对于节映射使用一级转换表就可以了,而对于微页、小页、大页则需要使用两级转换表。
存在主存储器内的转换表有两个级别:
2、第一级转换表
(注:本文中的页表与转换表同义)
存储节转换表和指向第二级表的指针。
注: 上图中粗糙页表栏中的最后一项应为‘01’
第一级表的每个入口是一个描述它所关联的1MB 虚拟地址是如何映射的描述符。见表3-1,根据bits[1:0]的组合,有四种可能:
· 如果bits[1:0]==0b00,所关联的地址没有被映射,试图访问他们将产生一个转换错(fault)。因为他们被硬件忽略,所以软件可以利用这样的描述符的bits[31:2]做自己的用途。推荐为描述符继续保持正确的访问权限。
· 如果bits[1:0]==0b10,这个入口是它所关联地址的节描述符。见节描述符和转换节参考中的细节。
· 如果bits[0]==1,这个入口给出粗糙第二级表(bit[1]==0),或精细第二级表(bit[1]==1)。
每一种类型的表描述了它所关联的1MB 存储区域的映射。粗糙第二级表较小,每个表1KB,每个精细第二级表4KB。然而粗糙第二级表只能映射大页和小页,精细第二级表可以映射大页、小页和微页。
节描述符和转换节参考
l 如果第一级描述符是节描述符,那么各个字段有如下的意义:
Bits[1:0] 描述符类型标识(0b10 表示节描述符)
Bits[3:2] 高速缓存和缓冲位
Bits[4] 由具体实现定义
Bits[8:5] 这个描述符控制的节的16 种域之一
Bits[9] 现在没有使用,应该为零
Bits[11:10] 访问控制,见表3-3
Bits[19:12] 现在没有使用,应该为零
Bits[31:20] 节基址,形成物理地址的高12 位
l 如果第一级描述符是粗糙页表描述符,那么各个字段有如下的意义:
Bits[1:0] 描述符类型标识(0b01 表示粗糙页表描述符)
Bits[4:2] 由具体实现定义
Bits[8:5] 这个描述符控制的页的16 种域之一
Bits[9] 现在没有使用,应该为零
Bits[31:10] 页表基地址是一个指向第二极粗糙页表的指针,
l 如果第一级描述符是精细页表描述符,那么各个字段有如下的意义:
Bits[1:0] 描述符类型标识(0b11 表示精细页表描述符)
Bits[4:2] 由具体实现定义
Bits[8:5] 这个描述符控制的页的16 种域之一
Bits[11:9] 现在没有使用,应该为零
Bits[31:10] 页表基地址是一个指向第二级精细页表的指针,它给出第二级表
访问的基地址。而第二级精细页表必须在4KB 边界对齐。
3、第二级转换表
存储大页和小页的转换表。一种类型的第二级表存储微页转换表。
每个粗糙第二级表对映着以4KB 为单位的虚拟地址范围市怎么映射的,每个精细第二级表对映着以1KB 为单位的虚拟地址范围市怎么映射的。那些入口是页描述符,他们能够分别描述大于4KB 或1KB 的页。在这种情况下,这个描述符必须被重复足够次,以保证这个页始终使用相同的描述符,不论访问这个页中的哪个虚拟地址。对于一个第二级描述符,有四种可能,由描述符的bits[1:0]选择。见表3-2:
· ?如果bits[1:0]==0b00,说关联的虚拟地址没有被映射,任何对这些虚拟地
址的访问将会导致转换错(fault)。软件可以利用这样的描述符的bits[31:2]做自己的用途,因为他们被硬件忽略。推荐为描述符继续保持正确的访问权限。
· ?如果bits[1:0]==0b01,这个入口是大页描述符,描述64KB 的虚拟地址。
见转换大页参考。一个大页描述符在精细第二级表中必须被重复64 次,在粗
糙第二级表中必须被重复16 次以保证所有的虚拟地址都被描述。
· ?如果bits[1:0]== 0b10,这个入口是小页描述符,描述4KB 的虚拟地址。
见转换小页参考。一个小页描述符在精细第二级表中必须被重复4 次,以保
证所有的虚拟地址都被描述。在粗糙第二级表中只有一个实例。
· ?如果bits[1:0]== 0b11,这个入口是微页描述符,描述1KB 的虚拟地址。
见转换微页参考。在精细第二级表中只需要一个微页描述符的实例。微页描
述符不能在粗糙第二级表中出现,如果出现了,结果不可预测。
大页描述符字段
大页描述符的字段有如下意义:
bits[1:0] 表示描述符的类型
bits[3:2] 高速缓促和缓冲位
bits[11:4] 访问权限位。这些为控制对页的访问。关于这些位的解释见表3-3。
大页被分成4 各子页。
AP0 编码对第一个子页的访问权限。
AP1 编码对第二个子页的访问权限。
AP2 编码对第三个子页的访问权限。
AP3 编码对第四个子页的访问权限。
bits[15:12] 现在没有使用,应该为零。
bits[31:16] 用来形成物理地址的对应位。
?
小页描述符字段
小页描述符的字段有如下意义:
bits[1:0] 表示描述符的类型
bits[3:2] 高速缓促和缓冲位
bits[11:4] 访问权限位。这些为控制对页的访问。关于这些位的解释见表3-3。
小页被分成4 各子页。
AP0 编码对第一个子页的访问权限。
AP1 编码对第二个子页的访问权限。
AP2 编码对第三个子页的访问权限。
AP3 编码对第四个子页的访问权限。
bits[31:12] 用来形成物理地址的对应位。
微页描述符字段
微页描述符的字段有如下意义:
bits[1:0] 表示描述符的类型
bits[3:2] 高速缓促和缓冲位
bits[5:4] 访问权限位。这些为控制对页的访问。关于这些位的解释见表3-3 关于微页的解释。
bits[9:6] 现在没有使用,应该为零。
bits[31:10] 用来形成物理地址的对应位。
MMU 把CPU 产生的虚拟地址转换成物理地址去访问外部存储器,同时继承并检查访问权限。地址转换有四条路径。路径的选取由这个地址是被标记成节映射访问还是页映射访问确定。页映射访问可以是大、小和微页的访问。
MMU的映射分为两种,一级页表的变换和二级页表变换。两者的不同之处就是所实现的变换地址空间大小不同。一级页表变换支持
要实现从虚拟地址到物理地址的映射,必然会遇到一个问题,如何找到这个页表。对于表的查找,要知道这个表的基地址和偏移地址,在具有MMU功能的处理器中,集成了一个被称为CP15的协处理器,该协处理器的C2寄存器中用于保存页表的基地址,
下面以一级页表变换为例说明MMU实现地址变换的过程。
4、节访问的转换过程
节和大页是支持允许只用一个TLB 入口去映射大的存储器区间。小页和大页有附加的访问控制:小页分成1KB 的子页,和大页分成16KB 的子页。微页没有子页,对微页的访问控制是对整个页。
然而,转换过程总是由下面所描述的那样由第一级表的获取开始。节映射的访问只需要读取第一级表,页映射的访问还需要读取第二级表。
1 转换表基址
当片上(on-chip)的TLB 中不包含被要求的虚拟地址的入口时,转换过程被启动。转换表基址寄存器(CP15 的寄存器2)保存着第一级转换表基址的物理地址。只有bits[31:14]有效,bits[13:0]应该是零(SBZ)。所以第一级表必须在16KB 的边界。
2 取第一级表
转换表基址寄存器的bits[31:14]与虚拟地址的bits[31:20]和两个0 位连接形成32 为物理地址,如图3-2。这个地址选择了一个四字节的转换表入口,它是第一级描述符或是指向第二级页表的指针。
当处理器访问一个虚拟地址时,该虚拟地址的[31:20]作为偏移地址与页基地址结合(基地址必须是64KB对齐的,因此基地址的[13:0]位都为0),得到一个32位的页表项地址(因为页表项为4字节对齐,[1:0]两位为0)。通过这个页表项地址可以检索到该页表项。页表项的格式见前面第一级转换表。
查找到页表项后,根据页表项的访问特性(缓冲以及是否允许访问等)协处理器决定是否允许访问。如不允许访问,则协处理器向CPU报告出错信息;反之,由页表项的[31:20]位与虚拟地址的[19:0]一起组成实际的物理地址,实现从虚拟地址到物理地址的映射。如下图所示:
5、粗糙二级表中的小页转换
如果从第一级读取到的是二级粗糙页表描述符,那么会象下图3-7 所示执行第二级描述符读取。
6、精细二级表中的微页转换
如果从第一级读取到的是二级精细页表描述符,那么会象图3-5 所示执行第
二级描述符读取。
7、存储器访问的顺序
查找整个转换表的过程叫转换表遍历。它由硬件制动进行,并需要大量的执行时间(至少一个存储器访问,通常是两个)。为了减少存储器访问的平均消耗,转换表遍历结果被高速缓存在一个或多个叫作Translation Lookaside Buffers(TLBs)的结构中。通常在ARM 的实现中每个内存接口有一个TLB。
因此,当ARM 要访问存储器时,MMU 先查找TLB 中的虚拟地址表,如果ARM 的结构支持分开的地址TLB 和指令TLB,那么它用:
· 取指令使用指令TLB
· 其它的所有访问类别用数据TLB
如果TLB 中没有虚拟地址的入口,则转换表遍历硬件从存在主存储器中的转换表中获取转换和访问权限,一旦取到,这些信息将被放在TLB 中,它会放在一个没有使用的入口处或覆盖一个已有的入口。
一旦为存储器访问的TLB 的入口被拿到,这些信息将被用于:
1. C(高速缓存)和B(缓冲)位被用来控制高速缓存和写缓冲,并决定是否高速缓存。(如果系统中没有高速缓存和写缓冲,则对应的位将被忽略)
2. 访问权限和域位用来控制访问是否被允许。如果不允许,则MMU 将向ARM 处理器发送一个存储器异常;否则访问将被允许进行。
3. 对没有高速缓存的系统(包括在没有高速缓存系统中的所有存储器访问),物理地址将被用作主存储器访问的地址。对有高速缓存的系统,在高速缓存没有选中的情况下,物理地址将被用行取(line fetch)的地址。如果选中了高速缓存,则物理地址将被忽略。图3-1 说明了这种高速缓存系统
三、协处理器CP15
MMU 由系统控制寄存器的2、3、4、5、6、8、10 号寄存器和1 号寄存器的一些位控制。
5.1 对协处理器寄存器的操作
ARM寄存器到协处理器的数据传诵指令和反向传送指令分别为MCR MRC
l MCR
MCR指令将ARM处理器的寄存器中的数据传送到协处理器的寄存器中。若协处理器不能成功执行该操作,将产生未定义指令异常中断。指令格式如下:
MCR{cond} coproc,opcode1,Rd,CRn,CRm{,opcode2}
其中 coproc 指令操作的协处理器的名称,标准名为pn,n为0~15,这里为p15
opcode1 协处理器的特定操作码
Rd 做源的ARM处理器寄存器
CRn 存放第一个操作数的协处理器寄存器
CRm 存放第二个操作数的协处理器寄存器
opcode2 可选的协处理器操作码
指令举例如下:
MCR p6,2,R7,c1,c2
MCR p7,0,R1,c3,c2,1
l MRC
MRC指令将协处理器的寄存器中的数据传送到ARM理器的寄存器中。若协处理器不能成功执行该操作,将产生未定义指令异常中断。指令格式如下:
MRC{cond} coproc,opcode1,Rd,CRn,CRm{,opcode2}
其中 coproc 指令操作的协处理器的名称,标准名为pn,n为0~15,这里为p15
opcode1 协处理器的特定操作码
Rd 做目标的ARM处理器寄存器
CRn 存放第一个操作数的协处理器寄存器
CRm 存放第二个操作数的协处理器寄存器
opcode2 可选的协处理器操作码
指令举例如下:
MRC p6,2,R7,c1,c2
MCR p7,0,R1,c3,c2,1
CP15寄存器0, ID代码及缓存类型
访问:只读
CP 寄存器0包含详细的硬件信息。读访问内容由opcode_2 域值确定。对寄存器0 写入结果无法预计。
将opcode_2 域置0 后读寄存器0 访问ID 代码寄存器 。
将opcode_2 域置1后读寄存器0访问缓存类型寄存器。缓存类型寄存器包含缓存大小与架构信息。
CP15寄存器1,控制
访问:读/ 写
CP15寄存器1或或称为控制寄存器包含ARM920T 控制位
各个控制位的作用:
? M[0]: MMU 使能
0 = MMU 禁用
1 = MMU 使能
? A[1]: 队列故障使能
0 = 故障校验禁用
1 = 故障校验使能
? C[2]: DCache 使能
0 = DCache 禁用
1 = DCache 使能
? B[7]: Endianness
0 = 小endian 模式
1 = 大endian 模式
? S[8]: 系统保护
修改MMU 保护系统
详见ARM920T技术参考手册Rev. DDI0151C。
? R[9]: ROM 保护
修改MMU 保护系统
详见ARM920T技术参考手册Rev. DDI0151C。
? I[12]: ICache控制
0 = ICache 禁用
1 = ICache使能
? V[13]: 异常寄存器基地址
0 = 低地址,为0x00000000
1 = 高地址,为0xFFFF0000
? RR[14]: Round Robin 置换
0 = 随机置换
1 = Round robin 置换
CP15寄存器2, TTB
访问:读/ 写
CP15寄存器2,或转换表基(TTB) 寄存器,定义转换表第一级,用于存放页表基址
读CP15 寄存器2 时,在bits[31:14]返回当前活动的第一级转换表的物理地址,bits[13:0]不确定。读CP15 寄存器2 时,CRm 和操作数2 被忽略,并应该是0。
写CP15 寄存器2 时,在bits[31:14]更新当前活动的第一级转换表的物理地址,bits[13:0]应该写0 或先前读回的值。写CP15 寄存器2 时,CRm 和操作数2 被忽略,并应该是0。
CP15寄存器3,域访问控制寄存器
访问:读/ 写
CP 15 寄存器3,或域访问控制寄存器,定义允许域访问。
使用16域进行MMU 访问优先级控制。
寄存器3中的每两位对应一个域。
域是节、大页和小页的集合。ARM 结构支持16 个域。对域的访问由域访问控制寄存器的两个位字段控制。因为每个字段对访问对应的域的使能非常迅速,所以整个存储器区间能很快地交换进出虚拟存储器。这里支持2 种域访问方式:
客户域的用户(执行程序,访问数据),被形成这个域的节或页来监督访问权限。
管理者控制域的行为(域中的当前节和页,对域的访问),不被形成这个域的节或页来监督访问权限。
一个程序可以是一些域的客户,也是另外一些域的管理者,同时没有对其它域的访问权限。这允许对程序访问不同存储器资源的非常灵活的存储器保护。表3-4 说明了域访问控制寄存器的位编码方式。
(域的作用即对于每一个存储块如节、大页和小页,设置能否访问这些存储块,或者访问这些存储块时是否需要进行在转换表中所设置的权限的检查)