打印
[应用相关]

ARM内存管理(MMU)详解

[复制链接]
1196|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wowu|  楼主 | 2019-7-9 09:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

嵌入式系统中,存储系统差别很大,可包含多种类型的存储器件,如 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 可以控制地址空间的访问权限,从而保护这些代码不被破坏。


使用特权

评论回复
沙发
wowu|  楼主 | 2019-7-9 10:00 | 只看该作者
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 边界对齐。

使用特权

评论回复
板凳
wowu|  楼主 | 2019-7-9 10:01 | 只看该作者
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 实现地址变换的过程。  

使用特权

评论回复
地板
wowu|  楼主 | 2019-7-9 10:01 | 只看该作者
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
wowu|  楼主 | 2019-7-9 10:01 | 只看该作者
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 说明了这种高速缓存系统

使用特权

评论回复
6
wowu|  楼主 | 2019-7-9 10:02 | 只看该作者
四、设置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。

使用特权

评论回复
7
wowu|  楼主 | 2019-7-9 10:02 | 只看该作者
下面是程序的具体实现
;init MMU
;写MMU表到on chip sram from 0x60010000 to 0x60014000   

        import write_mmu_table
        
        ldr r0,=table ;0x305f_c000

        bl write_mmu_table ;
        nop
        nop
        ldr      r2,=0x55555555
    mcr      p15,0x0,r2,c3,c0,0 ;16个域均为0b01,客户模式
   
    nop
    nop
    nop
    nop
   
    ldr r0,=table ;
    mcr      p15,0x0,r0,c2,c0,0 ;变换表基地址写入cp15 r2
    nop
    nop
    nop
    nop
    mov      r2,#0x7d ;0b0111 1101,使能cache,write buffer,MMU
    mcr      p15,0x0,r2,c1,c0,0
    nop
    nop
    nop
    nop
    nop
    nop
    就这些,mmu初始化完了
write_mmu_table()是c的小程序,往ram写地址转换的描述
void write_mmu_table(UINT32 *base)
{
        UINT32 *p_table;
        UINT32 description;
        UINT32 i;
        
        p_table = base;
        description = 0x3000_C00E; //页表项的值
         *p_table = description;

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

    //return;
}

使用特权

评论回复
8
磨砂| | 2019-8-7 09:54 | 只看该作者
非常好的帖子

使用特权

评论回复
9
晓伍| | 2019-8-7 10:00 | 只看该作者
感谢楼主分享

使用特权

评论回复
10
八层楼| | 2019-8-7 10:06 | 只看该作者
我有点看不进去 长篇大论啊

使用特权

评论回复
11
观海| | 2019-8-7 10:33 | 只看该作者
感觉是很深入的东西

使用特权

评论回复
12
guanjiaer| | 2019-8-7 10:38 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
13
heimaojingzhang| | 2019-8-7 10:47 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
14
keaibukelian| | 2019-8-7 10:52 | 只看该作者
支持一下楼主

使用特权

评论回复
15
wowu|  楼主 | 2019-8-7 11:36 | 只看该作者
感谢各位支持

使用特权

评论回复
16
bsz84| | 2019-8-7 20:42 | 只看该作者
支持一下楼主

使用特权

评论回复
17
wowu|  楼主 | 2019-8-8 13:03 | 只看该作者
再次感谢各位支持

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

90

主题

4081

帖子

1

粉丝