内存管理MMU实例分析

来源:互联网 发布:报关软件 购买 编辑:程序博客网 时间:2024/05/16 15:36

0、MMU概述
1、地址变换过程
2、访问权限
3、高速缓存
4、程序实例

 

0、MMU概述
    内存管理单元(Memory Management Unit)简称MMU,它负责虚拟地址到物理地址的映射,并提供硬件的内存访问权限检查。
    运行大型操作系统的平台,一般都采用MMU进行内存管理
    但对于带MMU的系统来说,内存中页命中率和换入换出所耗费的时间严重破坏了整个系统的确定性,这也是大多数实时操作系统采用直接内存管理,而不采用虚拟内存管理的原因

 

地址:
    虚拟地址-VA,这是可执行文件运行时section在内存中的运行地址
    变换后虚拟地址-MVA,gcc编译时使用同一个默认链接脚本,所以VA是相同的,为了得到不同的运行地址,所以需要结合PID通过FCSE单元再次转换
    物理地址-PA,这是代码运行所在的物理存储设备,在嵌入系统中通常比虚拟地址范围小
快速上下文切换,简称FCSE,用于避免在进程间切换时造成的虚拟地址到物理地址的重映射,将各进程的相同虚拟空间变换成不同的虚拟空间,从而避免重映射

 

例如:
    一个32位的CPU,它的地址范围是0-0xFFFFFFFF(4G)而对于一个64位的CPU,它的地址范围为0-0xFFFFFFFFFFFFFFFF (64T),这个范围就是我们的程序能够产生的地址范围,我们把这个地址范围称为虚拟地址空间,该空间中的某一个地址我们称之为虚拟地址。
    大多数时候系统所具备的物理地址空间只是虚拟地址空间的一个子集,对于一台内存为256MB的32bit x86主机来说,它的物理地址空间范围是0x000000000-0x0FFFFFFF(256M)。

    在没有使用虚拟存储器的机器上,虚拟地址被直接送到内存总线上,使具有相同地址的物理存储器被读写。
    在使用了虚拟存储器的情况下,虚拟地址不是被直接送到内存地址总线上,而是送到内存管理单元——MMU。
    由MMU把虚拟地址映射为物理地址,从而完成存储器读写,MMU由一个或一组芯片组成,一般存在协处理器中。

    大多数使用虚拟存储器的系统采用分页技术进行重映射,而相应的物理地址空间也被进行划分成同样大小的页。
映射关系如下图:

内存管理MMU实例分析

1、地址变换过程
    在ARM系统中,4GB虚拟空间被分成128个进程空间块,每个进程空间块大小为32MB
    每个进程空间块中可以包含一个进程(0x00000000-0x01ffffff),PID从0-127
    进程使用的VA(虚拟地址)空间为:
    (PID×0x02000000)——(PID×0x02000000+0x01ffffff)
过程如下:

内存管理MMU实例分析


页表:存在内存中的地址转换表,页表由一个个条目(描述符)组成
条目:每个条目存储了一段虚拟地址对应的物理地址及其访问权限,或者下一级页表地址
页号:从页表基址开始,每页的索引号
页内偏移:某一页的内部偏移地址
MVA被MMU分为2个部分:
    第一部分是页号索引(page Index)
    第二部分则是相对该页首地址的页内偏移量(offset)

内存管理MMU实例分析
TLB:快表,在CPU中开辟的RAM,访问速度与寄存器相当,大小为8-16字,用于缓存页表中的描述符,当CPU需要访问内存时,先在TLB中查找需要的地址变换条目,如果条目不存在,就从内存中的页表中查询,并将结果添加到TLB。

页表中条目(描述符)结构:
    Section base address:段基地址,内存中的物理段起始地址,可能是页表基址也可能是映射内存基址
    AP:2bit,访问权限控制位Access Permission
    Domain:4bit,域访问控制寄存器C3的索引,Domain与AP配合使用,对访问权限进行检查
    C:当C被置1时为write-through(WT)模式
    B:当B被置1时为write-back(WB)模式C,B两个位在同一时刻只能有一个被置1

内存管理MMU实例分析

当得到地址变换条目后,将进行的操作:
    通过条目得到该虚拟地址对应的物理地址
    根据条目中的C和B控制位决定是否缓存该内存访问的结果到cache
    根据存取权限控制位和域访问控制位确定该内存访问是否被允许,如果该内存访问不被允许,CP15向ARM处理器报告存储访问中止
    对于不允许缓存的存储访问,使用步骤一中得到的物理地址访问内存,对于允许缓存的存储访问,如果在cache中命中,则忽略物理地址,如果cache没有命中,则使用步骤一得到的物理地址访问内存,并把该块数据读取到cache中

 

将一个虚拟地址转换为物理地址,一般分为数学公式转换法和查表法,ARM采用的是查表法,且最多用到两级页表
物理内存可以划分为四种大小的块:
    段描述符保存着段的起始物理地址
    大页描述符保存着大页的起始物理地址
    小页描述符保存着小页的起始物理地址
    极小页描述符保存着极小页的起始物理地址
以段的方式进行转换时只用到一级页表,以页的方式进行转换时用到两级页表

 

段的大小为1M
页的大小分三种:
    大页,64KB
    小页,4KB
    极小页,1KB
粗页表描述符和细页表描述符都保存着二级页表的物理地址

 

转换过程描述:
    首先根据给定的虚拟地址找到一级页表中的条目
    如果此条目是段描述符,则返回对应的物理地址,转换结束
    否则如果此条目是二级页表描述符,继续利用虚拟地址在此二级页表中找到下一个条目
    如果上面的条目是页描述符,则返回物理地址,转换结束
    其它情况出错

内存管理MMU实例分析

只有一级页表的情况:
    虚拟地址:接下来均指的是MVA
    P1[31:20] :加上页表基址寄存器(C2)的[31:14]作为高位和MVA[31:20]作为低位组成一个低两位为0的32位地址,MMU利用这个地址找到段描述符
    由于p1是12bit,所以查找范围是4K个条目,如果是段转换方式,那么每一个条目对应1M物理空间
    P2[19:0]:p2是20bit,所以地址范围是1M,段描述符中的段地址(高12bit)加上p2构成映射后的物理地址

段地址转换过程:

内存管理MMU实例分析

具有两级页表的情况:
    P1[31:20] :加上页表基址寄存器(C2)的[31:14]和MVA[31:20]组成一个低两位为0的32位地址,MMU利用这个地址找到二级页表
    二级页表分为粗页和细页两种:
        粗页存放的页表:p2[19:16]4bit对应大页(64K),p2[19:12]8bit对应小页(4K)
        细页存放的页表:p2[19:16]4bit对应大页,p2[19:12]4bit对应小页p2[19:10]10bit对应极小页(1K)
    不管是大页、小页、极小页,都要读取二级页表条目,得到页描述符中的高位(大页16bit或小页20bit或极小页22bit)加上p3构成这些页映射后的物理地址

 

保存在粗页表中的大页地址转换过程:
    ①页表基址寄存器[31:14]和MVA[31:20]组成一个低两位为0的32位地址,MMU利用这个地址找到粗页表描述符
    ②取出粗页表描述符的[31:10](即粗页表基址),它和MVA[19:12]组成一个低两位为0的32位物理地址,通过这个地址找到大页描述符
    ③取出大页描述符的[31:16](即大页基址),它和MVA[15:0]组成一个32位的物理地址,即MVA对应的PA,步骤②和③中用于在粗页表中索引的MVA[19:12]和用于在大页内寻址的MVA[15:0]有重合的位[15:12],当位[15:12]从0b0000变化到0b1111时,步骤②得到的大页描述符相同(忽略低4位),所以粗页表中有连续16个条目保存同一个大页描述符

内存管理MMU实例分析

保存在粗页表中的小页地址转换过程:
①页表基址[31:14]和MVA[31:20]组成一个低两位为0的32位地址,MMU利用这个地址找到粗页表描述符
②取出粗页表描述符[31:10](即粗页表基址),它和MVA[19:12]组成一个低两位为0的32位物理地址,用这个地址找到小页描述符
③取出小页描述符的位[31:12](即小页基址),它和MVA[11:0]组成一个32位物理地址(即MVA对应的PA)

内存管理MMU实例分析
保存在粗页表中的极小页地址转换过程:
①页表基址寄存器[31:14]和MVA[31:20]组成一个低两位为0的32位地址,MMU通过这个地址找到细页表描述符
②取出细页表描述符[31:12](即细页表基址),它和MVA[19:10]组成一个低两位为0的32位物理地址,通过这个地址即可找到极小页描述符
③取出极小页描述符[31:10](即极小页基址),它和MVA[9:0]组成一个32位的物理地址(即MVA对应的PA)
内存管理MMU实例分析

从段、大页、小页、极小页的地址转换过程总结如下:
①以段进行映射时,通过MVA[31:20]结合页表得到一段(1MB)的起始物理地址,MVA[19:0]用来在段中寻址
②以大页进行映射时,通过MVA[31:16]结合页表得到一个大页(64KB)的起始物理地址,MVA[15:0]用来在大页中寻址
③以小页进行映射时,通过MVA[31:12]结合页表得到一个小页(4KB)的起始物理地址,MVA[11:0]用来在小页中寻址
④以极小页进行映射时,通过MVA[31:10]结合页表得到一个极小页(1KB)的起始物理地址,MVA[9:0]用来在极小页中寻址

内存管理MMU实例分析

2、访问权限
    内存的访问权限检查,它决定一块内存是否允许读、写
    这由CP15寄存器C3(域访问控制)、描述符的域(Domain)、CP15寄存器C1的R/S/A位、描述符的AP位共同决定
    “域”决定是否对某块内存进行权限检查,“AP”决定如何对某块内容进行权限检查
    S3C2440有16个域,CP15寄存器C3中每两位对应一个域(一共32位),用来表示这个域是否进行权限检查
    Domain占用4位,用来表示内存属于0-15,哪一个域

 

寄存器C3中每两位数据的含义
    00:无访问权限(任何访问都将导致“Domain fault”异常)
    01:客户模式(使用段描述符、页描述符中AP进行权限检查)
    10:保留(保留,目前相当于“无访问权限”)
    11:管理模式(不进行权限检查,允许任何访问)

 

例如:
    段描述符中的“Domain”为b0011,表示这个条目对应的1MB内存属于域3,如果域访问控制寄存器的[7:6]等于b00,则访问这1MB空间都会产生“Domain fault”异常,如果等于b01,则使用描述符中的“AP”位进行权限检查
    粗页表中的“Domain”为b1100,表示这个条目对应的内存属于域12,如果域访问控制寄存器的[25:24]等于b01,则使用二级页表中的大页/小页描述符中的"ap3"、"ap2"、"ap1"、"ap0"位进行权限检查,如果等于b11,则允许任何访问,不进行权限检查。

 

一级页表描述符

内存管理MMU实例分析
二级页表描述符

内存管理MMU实例分析


    AP、ap3、ap2、ap1、ap0结合CP15寄存器C1的R/S位,决定如何进行访问检查。
    段描述符中AP控制整个段(1MB)访问权限
大页描述符每个ap(ap0-3)控制一个大页(64KB)中1/4内存的访问权限,即ap3对应大页高端的16KB,ap0对应大页低端的16KB
    小页描述符与大页描述符类似,每个ap(ap0-3)控制一个小页(4KB)的1/4内存的访问权限
    极小页中的ap控制整个极小页(1KB)的访问权限

内存管理MMU实例分析

3、高速缓存
    基于程序访问的局部性,在主存和CPU通用寄存器之间设置一个高速的、容量相对较小的存储器,把正在执行的指令地址附近的一部分指令或数据从主存调入这个存储器,供CPU在一段时间内使用,对提高程序的运行速度有很大作用,这个cache一般称为高速缓存。
    S2C2440内置了指令Cache(ICaches)、数据Cache(DCaches)、写缓存(Write buffer),需要用到页表中描述符的C位和B位

 

分为两种操作:
    写穿式(Write Through)任一CPU发出写信号送到Cache的同时,也写入主存,保证主存的数据同步更新。优点是操作简单,但由于主存速度慢,降低了系统的写速度并占用了总线的时间。
    回写式(Write Back)数据一般只写到Cache,这样可能出现Cache中的数据得到更新而主存中的数据不变(数据陈旧)的情况。此时可在Cache中设一个标志地址及数据陈旧的信息,只有当Cache中的数据被换出或强制进行”清空“操作时,才将原更新的数据写入主存相应的单元中,保证了Cache和主存中数据一致。

 

数据处理:
    清空(clean):把Cache或Write buffer中已经脏的(修改过,但未写入主存)数据写入主存
    使无效(Invalidate):使之不能再使用,并不将脏的数据写入主存。

 

指令Cache(ICaches)
    系统刚上电或复位时,ICaches中的内容是无效的,并且ICaches功能关闭。
    往Icr位(CP15协处理器中C1的第12位)写1可以启动ICaches,写0停止ICaches
    ICaches一般在MMU开启后使用,此时描述符的Ctt位用来表示一段内存是否可以被Cache。若Ctt=1,允许Cache,否则不允许。如果MMU没有开启,ICaches也可以被使用,此时CPU读取指令时所涉及的内存都被当做允许Cache
    ICaches关闭时,CPU每次取指都要读取主存,性能低,所以通常尽早启动ICaches

    ICaches开启后,CPU每次取指时都会先在ICaches中查看是否能找到所用指令,而不管Ctt是0还是1。如果找到成为Cache命中,找不到称为Cache丢失
ICaches被开启后,CPU的取指有如下三种情况:
    Cache命中且Ctt为1时,从ICaches中取指,返回CPU
    Cache丢失且Ctt为1时,CPU从主存中取指,并且把指令缓存到Cache中
    Ctt为0时,CPU从主存中取指,但不会把指令缓存到Cache中

 

数据Cache(DCaches)
    与ICaches相似,系统刚上电或复位时,DCaches中的内容无效,并且DCaches功能关闭,Write buffer中的内容也是被废弃不用的。
    往Ccr位(CP15协处理器中C1的第2位)写1启动DCaches,写0停止DCaches。
    Write buffer和DCaches紧密结合,CP15有专门的控制寄存器来开启和停止它
    与ICaches不同,DCaches功能必须在MMU开启之后才能被使用。

    DCaches被关闭时,CPU每次都去内存取数据,DCaches和Write buffer被完全忽略。
    DCaches被开启后,CPU每次读写数据时都会先在DCaches中查看是否能找到所要的数据,不管Ctt是0还是1,找到了成为Cache命中,找不到成为Cache丢失。


通过下表可知DCaches和Write buffer在Ccr,Ctt,Btt各种取值下,如何工作,Ctt and Ccr 表示 Ctt与Ccr进行逻辑与后的值:

内存管理MMU实例分析
内存管理MMU实例分析


使用Cache时需要保证Cache、Write buffer的内容和主存内容一致,保证下面两个原则:
    清空DCaches,使主存数据得到更新
    使无效ICaches,使CPU取指时重新读取主存
在实际编写程序时,要注意如下几点:
    开启MMU前,使无效ICaches,DCaches和Write buffer
    关闭MMU前,清空ICaches、DCaches,即将”脏“数据写到主存上

    如果代码有变,使无效ICaches,这样CPU取指时会从新读取主存
    使用DMA操作可以被Cache的内存时,将内存的数据发送出去时,要清空Cache;将内存的数据读入时,要使无效Cache
    改变页表中地址映射关系时也要慎重考虑
    开启ICaches或DCaches时,要考虑ICaches或DCaches中的内容是否与主存保持一致
    对于I/O地址空间,不使用Cache和Write buffer

 

4、程序实例

    通过一个实例将MMU开启,并将虚拟地址0xA0000000-0xA0100000映射到物理地址0x56000000-0x56100000(GPGCON物理地址为0x56000060,GPGDAT物理地址为0x56000064),来驱动LED。
    将虚拟地址0xB0000000-0xB3FFFFFF映射到物理地址0x30000000-0x33FFFFFF,在连接程序时,将一部分代码的运行地址指定为0xB0004000。

 

    这个程序只使用一级页表,以段的方式进行地址映射,32位CPU虚拟地址空间达到4G,一级页表使用4096个描述符来表示4G空间(每个描述符对应1MB),每个描述符占4字节,所以一级页表占16KB。
    这个程序使用SDRAM的开始16KB存放一级页表,所以剩下的内存开始地址就为0x30004000,这个地址最终会对应虚拟地址0xB0004000(所以代码运行地址为0xB0004000)

程序分为两部分:

    第一部分的运行地址为0,它用来初始化SDRAM,复制第二部分的代码到SDRAM中(存放在0x30004000)、设置页表、启动MMU,最后跳到SDRAM中(地址0xB0004000),第二部分运行地址设为0xB0004000,用来驱动LED

先看看连接文件mmu.lds

内存管理MMU实例分析

程序分两个段:first和second。first由head.o和init.o组成,加载和运行地址都是0,second由leds.o组成,加载地址为2048,重定位地址为0xB0004000。

 

head.S
功能:
    关闭看门狗,设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU
    最后跳到SDRAM继续执行
具体代码如下:

内存管理MMU实例分析

init.c
功能:
    实现一些初始化接口函数,在Steppingstone中运行
    它和head.S同属第一部分程序,在没开启MMU之前使用的是物理地址


leds.c
功能:
    循环点亮3个LED
    属于第二部分程序,此时MMU已开启,使用虚拟地址

 

当前MMU源码实例:

http://iask.sina.com.cn/u/2487717952/ish