MMU是Memory Management Unit的缩写,中文名是
内存管理单元,有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。它是一种负责处理
中央处理器(CPU)的
内存访问请求的
计算机硬件。它的功能包括
虚拟地址到
物理地址的转换(即
虚拟内存管理)、内存保护、中央处理器
高速缓存的控制,在较为简单的计算机体系结构中,负责
总线的
仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。
历史
许多年以前,当人们还在使用
DOS或是更古老的
操作系统的时候,计算机的内存还非常小,一般都是以K为单位进行计算,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序。但随着图形界面的兴起还有用户需求的不断增大,
应用程序的规模也随之膨胀起来,终于一个难题在程序员的面前,那就是
应用程序太大以至于内存容纳不下该程序,通常解决的办法是把程序分割成许多称为
覆盖块(
overlay)的片段。
覆盖块0首先运行,结束时他将调用另一个覆盖块。虽然覆盖块的交换是由
OS完成的,但是必须先由
程序员把程序先进行分割,这是一个费时费力的工作,而且相当枯燥。人们必须找到更好的办法从根本上解决这个问题。不久人们找到了一个办法,这就是
虚拟存储器(
virtual memory)。
虚拟存储器的基本思想是程序,数据,
堆栈的总的大小可以超过物理存储器的大小,
操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上。比如对一个16MB的程序和一个内存只有4MB的机器,
操作系统通过选择,可以决定各个时刻将哪4M的内容保留在
内存中,并在需要时在内存和磁盘间交换程序片段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了。而这个16M的程序在运行前不必由
程序员进行分割。
简介
内存管理单元通常应用在桌面型
计算机或者
服务器,通过
虚拟存储器使得
计算机可以使用比实际的物理内存更多的存储空间。同时,内存
管理单元还对实际的物理内存进行分割和保护,使得每个软件任务只能访问其分配到的内存空间。如果某个任务试图访问其他任务的内存空间,内存管理单元将自动产生异常,保护其他任务的程序和数据不受破坏。概述图显示了一个典型的使用内存
管理单元为多个任务划分的
内存映射图。内存管理单元的这个机制是调试指针错误或数组下标越界等错误的非常强大的工具。
基本概念
MMU位于
处理器内核和连接
高速缓存以及
物理存储器的
总线之间。当处理器
内核取指令或者存取数据的时候,都会提供一个有效地址(effective address),或者称为
逻辑地址、
虚拟地址。这个地址是
可执行代码在编译的时候由链接器生成的。不同于开发
嵌入式处理器系统的程序员,桌面型计算器的程序开发人员通常对硬件的物理配置信息所知甚少。将
存储器系统虚拟化,程序员就不需要了解存储器的物理配置细节。当应用代码需要使用存储空间时,操作系统通过MMU为其分配合适的物理存储空间。
有效地址不需要和系统的实际硬件物理地址相匹配,而是通过MMU将有效地址映射成对应的
物理地址,以访问指令和数据。
每条MMU匹配规则所对应的
存储器的大小定义为页。页的大小通常设定为不会对程序的性能造成显著影响的最小的程序和代码的长度。当暂时不使用
物理内存的内容时,可将其保存到硬盘等
外部存储器里,将其空间用于其他程序;当再次使用这部分内容时再从外部存储器写回到实际物理内存中。通过这种方法,系统就可以提供多于实际物理内存容量的“
虚拟内存”。如果MMU定义的页太大,那么进行
虚拟内存页面替换所花费的时间就太长;如果页太小,就会引起过于频繁的页面替换。通常最小的页设定为4 KB。
为了加快MMU规则匹配的处理过程,
有效地址和实际
物理地址的对应表通常保存在一块单独的高速缓存中,称为对应查找表(Translation Lookaside Buffer,TLB),
TLB和实际物理存储器可以同时进行并行的访问。有效地址的高位作为在
TLB进行匹配查找的依据,而
有效地址的低位作为页面内的偏址。
TLB可以包含很多个表项(
entry),每个表项对应一个MMU的页。操作系统或者应用启动代码必须正确的初始化TLB的所有表项。当应用程序提供的有效地址正好位于某个
TLB表项制定的地址范围内时,称为产生了一次TLB命中;如果这个有效地址没有位于任何一个
TLB表项制定的地址范围内,称为一个TLB
缺失,或者TLB未
命中。TLB未命中往往发生在应用程序出现错误的时候,所以TLB未命中所引发的
异常处理可以很有效的发现和调试这类错误。虚拟内存利用TLB未命中的异常来完成页面交换,并根据交换的内容对应的调整TLB表项的参数。通常TLB表项还会指定一些
存储器读写的其他参数,只有当这些参数也和当前的存储器读写的参数符合的时候,才能产生TLB命中。
MMU属性
MMU符合
Power体系结构的规范。TLB表项都是相连映射的,并且提供了额外的硬件来加速
TLB未命中异常的处理。有几条特殊的指令用于管理TLB表项。
页面大小
TLB表项映射的
存储器范围就是页面。这个属性具体包括:
①指定的有效映射地址。
②读写权限。
MMU具有32个TLB表项,可以支持32个页面。每个页面的容量可以指定为4 KB,16 KB,64 KB,256 KB,1 MB,4 MB,16 MB,64 MB和256 MB。
实际页面地址 (RealPageNumber,
RPN) 确定了页面对应的起始
物理地址。这个起始地址必须是页面大小的整数倍,例如16 KB的页面的起始地址必须位于0,16 KB,32 KB或48KB的边界上。这样,将页面和MPC 5554 / 5553的实际
物理地址对应起来的时候,就需要格外注意。
实际上,存储器
分配表也考虑到了这一点,仔细地分配了每个片上模块的起始地址和模块地址空间,使得需要用到的TLB表项尽可能少。实际上,
BAM代码中只需要使用前5个
TLB表项就可以覆盖微处理器的全部地址空间。多个页面也允许占用相同的
物理地址空间。
例如,可以将片内的一段64KB的
FLASH存储器映射成一个64 KB的
只读页面;另外将一段16 KB的读写页面映射到这64 KB的起始地址。这样,这64KB的
地址空间实际上就被分成了48KB和16KB两个部分,如图1所示。虽然这两个页面有可能产生相同的
物理地址,但是通过结合其他的页面属性可以避免多个页面同时命中。注意读写权限并不能用来避免多页面命中。
在这种配置方式下,48 KB的
只读部分可以用于保存
常数和表等固定数据,而16 KB的读写部分则可以用于模拟EEP-
ROM存储区。应用程序必须非常仔细的确认那些对48KB常数段进行操作的代码不会错误的访问到前面的16KB区域,因为在这种情况下MMU无法检查对48KB区域的访问
越界。如果要实现对48 KB区域的访问越界检查,将一共需要使用4个
TLB表项才能实现。使用3个
TLB表项将这48 KB空间必须映射到3个独立的16 KB页面,并且和原来的16 KB页面没有任何重叠。
通过配置
TLB表项,也可以将全部的片
内存储器和I/O空间都映射成一个大的连续的
虚拟地址空间。MPC 5554 / 5553 的
I/O模块的地址空间分散在整个4 GB
寻址空间里。图2的例子里,eTPU模块的16 KB双口共享RAM和片内的64 KB
RAM被映射成了一个连续的80KB
虚拟空间。
当然此时就不能再使用
eTPU模块了。通过配置
TLB表项,也可以将应用中
处理器需要频繁访问的外设的地址映射到那些可以使用更高效的
寻址方式的页面空间。例如将eMIOS模块的
地址空间映射到0地址开始的页面,处理器就可以使用高效的
立即数间接寻址,而不必使用复杂的
寄存器间接寻址方式。
TS地址空间类型指示
根据
Power体系规范的规定,有效地址还包含了两个额外的位分别用于指明当前的有效地址是否是指令获取操作和
数据读写操作。对于指令操作,这个额外的位保存在MSR寄存器的IS位;对于数据操作,这个额外的位保存在
MSR寄存器的DS位。这两个位可以通过程序指令进行修改,但是当发生中断的时候,MSR寄存器中的这两个位都会被清除为0。
当
处理器进行指令获取或数据读写操作时,IS和DS位会分别和
TLB表项中保存的TS位进行比较,比较的结果将对是否产生
TLB命中产生影响。
由于在发生中断时,MSR
寄存器中IS和DS位都被清为0,所以对于中断处理程序所在的页面,其TS必须置为0.正常的应用程序所在的页面的TS就需要置为1。
使用地址空间类型指示可以将映射到同一段
有效地址的多个
程序模块区分开来。例如可以将
中断服务程序放置在
地址空间的前32KB,并且具有系统态运行的属性;而应用程序的固定
数据表也可以映射到这32 KB,具有普通态
只读的属性。
TID TLB处理ID号
根据
Power体系规范的规定,MMU还提供了PID(ProcessID)的特性。当TLB进行
有效地址映射处理的时候,
PID寄存器的值也和TLB表项中的TID值进行比较。不管是指令操作还是数据操作,都要进行PID和TID的比较。
如果
TID被设置为0值,那么将忽略PID和TID比较的结果,也不会对
TLB命中的处理产生影响。
多个
TLB表项对应相同的
有效地址的情况,可以通过TID来进行区分。通过修改TID寄存器的值,可以很容易地在运行时切换存储器.例如当应用程序运行时,通过
NEXUS调试接口修改TID寄存器的值后,相同的有效地址所对应的数据将变成从另外--个物理存储空间得到。这对于调试是非常有用的。
EPN、RPN有效页面地址,实际页面地址
在每个
TLB表项中,必须满足下面的条件才能正确进行
有效地址的映射:
●
有效地址的特定位数的内容和TLB表项中有效页面地址EPN相同。
●MSR
寄存器的IS位(对于指令操作)或DS位(对于数据操作)和TLB表项中的TS位相同。
●PID
寄存器的值和TLB表项中TID的值相同,或者TID的值为零。
图3给出了有效TLB命中的逻辑处理结构图。
对一个有效地址,如果没有任何一个
TLB表项满足上述条件,就产生了一个TLB
缺失,这可以引起一个指令或数据的
TLB缺失异常。
TLB表项中定义的页大小决定了
有效地址的多少个位的信息需要和TLB表项中的EPN进行比较。当TLB命中后,TLB表项中的
RPN就替换了有效地址中的对应位,而构成实际的物理地址。
存储器访问权限
程序可以为每个虚拟页面指定一定的
访问权限,包括是系统态还是普通态,是否允许读、写和
运行指令。对于某些应用,这些
访问权限设定只能在系统复位后配置一次。
例如,程序代码所在区域被配置为只能运行,数据
变量区被设置为读写非运行,数据
常数区被配置为只读非运行。对于另一些应用,这些
访问权限由操作系统根据应用程序的需要和系统运行的策略进行动态的修改。
UX,SX,UW,SW,UR和SR访问权限位用于设定一个虚拟页面的访问权限。这些位的具体描述如下:
●SR--系统态读权限:在系统态下(MSR[PR=0]),允许进行存储区读操作和读取形式的缓存管理操作。
●SW--系统态写权限:在系统态下(MSR[PR=0]),允许进行
存储器写操作和写入形式的缓存管理操作。
●SX--系统态运行权限:在系统态下(MSR[PR= 0]) ,允许从
存储器获取和执行指令。
●UR--普通态读权限:在普通态下(MSR[PR=1]),允许进行存储区读操作和读取形式的缓存管理操作。
●UW--普通态写权限:在普通态下(MSR[PR= 1]),允许进行
存储器写操作和写入形式的缓存管理操作。
●UX--普通态运行权限:在普通态下(MSR[PR= 1]) ,允许从
存储器获取和执行指令。
在地址比较和页面属性比较完成后,还需要检查这些
访问权限设定。如果产生了权限冲突,会引发一个指令或数据存储
中断(ISI或DSI)。
相关概念
任何时候,计算机上都存在一个程序能够产生的地址集合,我们称之为地址范围。
地址范围的大小由CPU的位数决定,例如一个32位的CPU,它的地址范围是0~0xFFFFFFFF (4G),而对于一个64位的CPU,它的地址范围为0~0xFFFFFFFFFFFFFFFF (16E)。这个范围就是我们的程序能够产生的地址范围,我们把这个地址范围称为
虚拟地址空间,该空间中的某一个地址我们称之为虚拟地址。
与虚拟地址空间和虚拟地址相对应的则是物理地址空间和物理地址,大多数时候我们的系统所具备的物理地址空间只是虚拟地址空间的一个子集。这里举一个最简单的例子直观地说明这两者,对于一台内存为256M的32bit x86主机来说,它的虚拟地址空间范围是0~0xFFFFFFFF(4G),而物理地址空间范围是0x00000000 ~ 0x0FFFFFFF(256M)。
在没有使用
虚拟存储器的机器上,
地址被直接送到内存总线上,使具有相同地址的物理存储器被读写;而在使用了虚拟存储器的情况下,虚拟地址不是被直接送到
内存地址总线上,而是送到
存储器管理单元MMU,把虚拟地址映射为物理地址。
大多数使用虚拟存储器的系统都使用一种称为
分页(paging)机制。虚拟地址空间划分成称为页(page)的单位,而相应的
物理地址空间也被进行划分,单位是页帧(frame).页和页帧的大小必须相同。在这个例子中我们有一台可以生成32位地址的机器,它的
虚拟地址范围从0~0xFFFFFFFF(4G),而这台机器只有256M的物理地址,因此他可以运行4G的程序,但该程序不能一次性调入内存运行。这台机器必须有一个达到可以存放4G程序的外部
存储器(例如磁盘或是FLASH),以保证程序片段在需要时可以被调用。在这个例子中,页的大小为4K,页帧大小与页相同——这点是必须保证的,因为内存和外围
存储器之间的传输总是以页为单位的。对应4G的虚拟地址和256M的物理存储器,他们分别包含了1M个页和64K个页帧。
功能
1)将线性地址映射为物理地址
现代的多用户
多进程操作系统,需要MMU,才能达到每个用户进程都拥有自己独立的
地址空间的目标。使用MMU,操作系统划分出一
段地址区域,在这块地址区域中,每个进程看到的内容都不一定一样。例如MICROSOFT
WINDOWS操作系统将地址范围4M-2G划分为用户地址空间,进程A在地址0X400000(4M)映射了
可执行文件,进程B同样在地址0X400000(4M)映射了可执行文件,如果A进程读地址0X400000,读到的是A的可执行文件映射到RAM的内容,而进程B读取地址0X400000时,则读到的是B的可执行文件映射到RAM的内容。
这就是MMU在当中进行地址转换所起的作用。
2)提供硬件机制的内存访问授权
多年以来,
微处理器一直带有片上
存储器管理单元(MMU),MMU能使单个软件线程工作于硬件保护
地址空间。但是在许多商用
实时操作系统中,即使系统中含有这些硬件也没采用MMU。
当应用程序的所有线程共享同一
存储器空间时,任何一个线程将有意或无意地破坏其它线程的代码、数据或
堆栈。异常线程甚至可能破坏内核代码或内部数据结构。例如线程中的指针错误就能轻易使整个
系统崩溃,或至少导致系统工作异常。
就安全性和可靠性而言,基于进程的实时操作系统(RTOS)的性能更为优越。为生成具有单独地址空间的进程,RTOS只需要生成一些基于RAM的数据结构并使MMU加强对这些数据结构的保护。基本思路是在每个关联转换中“接入”一组新的
逻辑地址。MMU利用当前映射,将在指令调用或数据读写过程中使用的逻辑地址映射为
存储器物理地址。MMU还标记对非法逻辑地址进行的访问,这些非法逻辑地址并没有映射到任何物理地址。
这些进程虽然增加了利用查询表访问存储器所固有的
系统开销,但其实现的效益很高。在进程边界处,疏忽或错误操作将不会出现,
用户接口线程中的缺陷并不会导致其它更关键线程的代码或数据遭到破坏。在可靠性和安全性要求很高的复杂嵌入式系统中,仍然存在采无存储器保护的操作系统的情况,这实在有些不可思议。
采用MMU还有利于选择性地将页面映射或解映射到
逻辑地址空间。物理存储器页面映射至逻辑空间,以保持当前进程的代码,其余页面则用于数据映射。类似地,物理存储器页面通过映射可保持进程的线程
堆栈。RTOS可以在每个线程堆栈解映射之后,很容易地保留逻辑地址所对应的页面内容。这样,如果任何线程分配的堆栈发生溢出,将产生硬件
存储器保护故障,内核将挂起该线程,而不使其破坏位于该地址空间中的其它重要存储器区,如另一线程堆栈。这不仅在线程之间,还在同一地址空间之间增加了存储器保护。
存储器保护(包括这类
堆栈溢出检测)在
应用程序开发中通常非常有效。采用了存储器保护,
程序错误将产生异常并能被立即检测,它由
源代码进行跟踪。如果没有存储器保护,程序错误将导致一些细微的难以跟踪的故障。实际上,由于在扁平
存储器模型中,RAM通常位于
物理地址的零页面,因此甚至NULL指针引用的解除都无法检测到。
系列介绍
INTEL出品的80386CPU或者更新的CPU中都集成有MMU. 可以提供32BIT共4G的
地址空间。
X86 MMU提供的寻址模式有4K/2M/4M的PAGE模式(根据不同的CPU,提供不同的能力),此处提供的是大部分操作系统使用的4K
分页机制的描述,并且不提供ACCESS CHECK的部分。
1.涉及的寄存器:
a) GDT
b) LDT
c) CR0
d) CR3
e) SEGMENT REGISTER
a) SEGMENT REGISTER作为GDT或者LDT的INDEX,取出对应的GDT/LDT ENTRY。
注意: SEGMENT是无法取消的,即使是FLAT模式下也是如此。 说FLAT模式下不使用SEGMENT REGISTER是错误的.。任意的RAM寻址指令中均有DEFAULT的SEGMENT假定。
ENTRY格式
共有4种ENTRY格式,此处提供的是CODE SEGMENT和DATA SEGMENT的ENTRY格式. FLAT模式下的ENTRY在base_0_15,base_16_23处为0,而limit_0_15,limit_16_19处为0xfffff. granularity处为1。表名SEGMENT
地址空间是从0到0XFFFFFFFF的4G的地址空间。
b) 从SEGMENT处取出BASE ADDRESS 和LIMIT. 将要访问的ADDRESS首先进行ACCESS CHECK,是否超出SEGMENT的限制。
c) 将要访问的ADDRESS+BASE ADDRESS,形成需要32BIT访问的
虚拟地址. 该地址被解释成如下格式:
d) pdbr_index作为CR3的INDEX,获得到一个如下定义的数据结构
e) 从中取出PAGE TABLE的地址. 并且使用page_index作为INDEX,得到如下数据结构
f) 从PTE中获得PAGE的真正物理地址的BASE ADDRESS. 此BASE ADDRESS表名了物理地址的.高20位. 加上
虚拟地址的offset就是物理地址所在了.
ARM出品的CPU,MMU作为一个协处理器存在。根据不同的系列有不同搭配。需要查询DATASHEET才可知道是否有MMU。如果有的话,一定是编号为15的协处理器。可以提供32BIT共4G的地址空间。
ARM MMU提供的
分页机制有1K/4K/64K 3种模式,这里介绍的是
操作系统通常使用的4K模式。
ARM cpu地址转换涉及三种地址:
虚拟地址(VA,Virtual Address),变换后的虚拟地址(MVA,Modified Virtual Address),
物理地址(PA,Physical Address)。没有启动MMU时,
CPU核心、cache、MMU、外设等所有部件使用的都是物理地址。启动MMU后,CPU核心对外发出的是虚拟地址VA,VA被转换为MVA供cache、MMU使用,并再次被转换为PA,最后使用PA读取实际设备。
ARM没有SEGMENT的寄存器,是真正的FLAT模式的CPU。给定一个ADDRESS,该地址可以被理解为如下数据结构:
从MMU寄存器2中取出BIT14-31,pdbr_index就是这个表的索引,每个入口为4BYTE大小,结构为
获得的PDE地址,获得如下结构的ARRAY,用page_index作为索引,取出内容。
从PTE中获得的基地址和上offset,组成了
物理地址。
PDE/PTE中其他的BIT,用于访问控制。这边讲述的是一切正常,物理地址被正常组合出来的状况。
ARM/X86 MMU使用上的差异:
⒈X86始终是有SEGMENT的概念存在. 而ARM则没有此概念(没有SEGMENT REGISTER.).
⒉ARM有个DOMAIN的概念. 用于访问授权. 这是X86所没有的概念. 当通用OS尝试同时适用于此2者的CPU上,一般会抛弃DOMAIN的使用。
工作机理
现代的内存管理单元是以页的方式,分割虚拟
地址空间(处理器使用的地址范围)的;页的大小是2的n次方,通常为几
KB(千字节)。地址尾部的n位(页大小的2的次方数)作为页内的偏移量保持不变。其余的地址位(address)为(虚拟)页号。
页表条目
内存管理单元通常借助一种叫做转译旁观缓冲器(Translation Lookaside Buffer,缩写为TLB)的相联高速缓存(associative cache)来将虚拟页号转换为物理页号。当后备缓冲器中没有转换记录时,则使用一种较慢的机制,其中包括专用硬件(hardware-specific)的数据结构(Data structure)或软件辅助手段。这个数据结构称为分页表,页表中的数据就叫做分页表项(page table entry,缩写为PTE)。物理页号结合页偏移量便提供出了完整的物理地址。
页表或转换后备缓冲器中数据项包括的信息有:
一、“脏位”(页面重写标志位,dirty bit)——表示该页是否被写过。
二、“访问位”(accessed bit)——表示该页最后使用于何时,以便于
最近最少使用页面置换算法(least recently used page replacement algorithm)的实现。
三、哪种进程可以读写该页的信息,例如用户模式(user mode)进程还是
特权模式(supervisor mode)进程。
四、该页是否应被高速缓冲的信息。
有时,TLB或PTE会禁止对虚拟页的访问,这可能是因为没有物理
随机存取存储器(random access memory)与虚拟页相关联。如果是这种情况,MMU将向CPU发出
页错误(page fault)的信号。
操作系统(operating system)将进行处理,也许会尝试寻找RAM的空白帧,同时创建一个新的PTE将之映射到所请求的虚拟地址。如果没有空闲的RAM,可能必须关闭一个已经存在的页面,使用一些替换算法,将之保存到磁盘中(这被称之为页面调度(paging)。在一些MMU中,PTEs或者TLB也存在一些缺点,在这样的情况下操作系统将必须释放空间以供新的映射。
益处
有些情况下,页错误的出现表示可能存在软件错误,并能够被应用内存管理单元的内存保护特性通过禁止出错程序避免出现非法访问其他程序内存。通常地, 操作系统会为每个程序分配虚拟内存地址。
此外,内存管理单元能够减少程序的内存碎片化现象。当程序分配并释放内存块后,释放的内存可能出现碎片化,从而导致最大的连续可用内存块远小于已分配内存总量。在虚拟内存实现后,虚拟内存可以映射多个不连续的物理内存区块为一个连续区块,而这种不连续分配机制得益于内存分页。