MMU(memory management unit)存储管理单元
早期的嵌入式系统的存储系统中地址空间的分配是固定,各个软硬件直接使用武力地址,将程序全部装载到物理内存中,CPU对数据和指令进行操作时也是使用的物理地址,这种方式简单,实用,但是当我们的程序大于内存容量的时候,导致不可能将全部程序代码装载到内存当中去。事实上,我们没必要将程序全部装载到内存中,我们运行哪个部分,就装载哪个部分。
通常在内存容量不变的时候,通过虚拟地址空间来扩大程序的可访问空间。此处我们谈到了虚拟地址空间,在32位CPU系统中,虚拟地址空间为0~0xFFFFFFFF(4GB),也就是说有4GB个虚拟地址。于此对应的是物理地址空间,像我们的512M内存,物理地址空间为0~0x1FFFFFFF,也就是说含有512M个物理地址。
虚拟地址通过映射到具体的物理地址上才能访问数据。通常将虚拟地址空间和物理地址空间划分成同样大小的一块块的空间,然后为这些空间建立映射关系,由于虚拟地址空间大于物理地址空间,因此有多个虚拟地址映射到同一个物理地址空间上。。。
那么MMU就来具体将虚拟地址映射到物理地址上
MMU的主要功能有:
1、上面讲述的将虚拟地址映射到物理地址
2、控制存储器访问权限
3、设置虚拟存储空间的缓冲特性
在进行映射时涉及到三个地址:物理地址PA,虚拟地址VA,修正后的虚拟地址MVA
ARM内核使用的是VA,它根本不管你怎么映射,VA经过C13寄存器修正为MVA,进入MMU出来后是PA物理地址,然后访问外设。
在ARM中每个进程最大可使用的虚拟内存空间为32MB,每个进程都有一个PID,为什么用这个PID?这是由于不同进程的虚拟地址空间是重叠,用PID来区分每个用户进程。这有个程序将不同进程进行区分
if(VA<32M)
MVA=PID<<25+VA;
else
MVA=VA;
为什么PID左移25位,这是因为32MB为2的25次幂,故虚拟地址地址的低25位有效,高7位没什么用,但是由于有重叠,而PID各不相同,故将PID加到地址的前面就可以区别不同进程虚拟地址。VA到MVA是硬件自动完成的,只要给出PID,告诉CP15的C13寄存器即可。。。
那么MMU如何将MVA映射为PA的呢?下面进一步分析
在MMU中,有个页表,其实就是一数组,里面的元素称为页表项。那么,想要在这个数组里面找到相应的页表项,首先要知道这个数组的首地址,其次是得到某个页表项的数组下标。我们将页表的首地址称为页表转换基址,简称页表基址。
而页表基址是存放在协处理器CP15的C2寄存器中的。只要读取C2寄存器就可以得到页表基址。而页表基址是16KB对齐的,也就是从C2寄存器中读出来的值低14位为0.至于为什么为16KB对齐,还未弄清楚。至于数组下表,我们将MVA的高12取出,用来作为寻找页表的偏移量。将页表基址加上偏移量得到低两位为0的32地址,可以定位到具体的页表项,此页表项又称为以及描述符,根据一级描述符的低两位的取值又可以分为:无效页表项【低两位未设置】,段描述符【1:0】,粗页表【0:1】,细页表【1:1】。例如低两位为【1:0】,该描述符对段地址空间进行描述。那么此描述符的高12位作为段地址空间的首地址,也称为段基址,将段基址与MVA的低20位相加,组成32位地址,这个地址就是我们要求的物理地址。示意图如下