发 帖  
原厂入驻New
[经验]

ARM的内存管理(MMU)是如何实现的?

2020-10-23 15:29:49  717 MMU ARM
分享
1
嵌入式系统中,存储系统差别很大,可包含多种类型的存储器件,如 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 的映射分为两种,一级页表的变换和二级页表变换。两者的不同之处就是所实现的变换地址空间大小不同。一级页表变换支持 1M 大小的存储空间的映射,而二级可以支持 64KB 、 4KB 和 1KB 大小地址空间的映射。
要实现从虚拟地址到物理地址的映射,必然会遇到一个问题,如何找到这个页表。对于表的查找,要知道这个表的基地址和偏移地址,在具有 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 说明了域访问控制寄存器的位编码方式。
(域的作用即对于每一个存储块如节、大页和小页,设置能否访问这些存储块,或者访问这些存储块时是否需要进行在转换表中所设置的权限的检查)

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。

下面是程序的具体实现
  1. import write_mmu_table
  2.       
  3.         ldr r0,=table ;0x305f_c000

  4.         bl write_mmu_table ;
  5.         nop
  6.         nop
  7.         ldr      r2,=0x55555555
  8.     mcr      p15,0x0,r2,c3,c0,0 ;16个域均为0b01,客户模式
  9.    
  10.     nop
  11.     nop
  12.     nop
  13.     nop
  14.    
  15.     ldr r0,=table ;
  16.     mcr      p15,0x0,r0,c2,c0,0 ;变换表基地址写入cp15 r2
  17.     nop
  18.     nop
  19.     nop
  20.     nop
  21.     mov      r2,#0x7d ;0b0111 1101,使能cache,write buffer,MMU
  22.     mcr      p15,0x0,r2,c1,c0,0
  23.     nop
  24.     nop
  25.     nop
  26.     nop
  27.     nop
  28.     nop
复制代码
就这些,mmu初始化完了
write_mmu_table()是c的小程序,往ram写地址转换的描述
  1. void write_mmu_table(UINT32 *base)
  2. {
  3.         UINT32 *p_table;
  4.         UINT32 description;
  5.         UINT32 i;
  6.       
  7.         p_table = base;
  8.         description = 0x3000_C00E; //页表项的值
  9.          *p_table = description;

  10.      p_table++;
  11.         description = 0x31000c10  //下面使除了上面映射地址之外,所有的虚拟地址都为无效
  12.                                                         //地址..bits[1:0]==0b00,所关联的地址没有被映射
  13.         for (i=1;i<4096;i++)
  14.         {
  15.                 *p_table = description;
  16.                 description = description +0x00100000;
  17.                 p_table ++;   
  18.         }      

  19.     //return;
  20. }
复制代码


评论

高级模式
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发经验
关闭

站长推荐 上一条 /9 下一条

快速回复 返回顶部 返回列表