学习了S3C2440内存管理单元MMU,主要参考了《嵌入式Linux应用开发完全手册》 (下载见)。有两篇文章也说得很详细,分别是 与感兴趣的可以参考一下,我就不重复内容了。但是它们在MMU地址变换过程这一块说得不太好理解。在此,我就按照我的理解将《嵌入式Linux应用开发完全手册》的相关内容解释一下,图片加点注释。如有错误,请大家不吝赐教,我一定马上改,谢谢。
S3C2440 MMU地址变换过程
1)地址的分类
ARM cpu地址转换涉及三种地址:虚拟地址(VA,Virtual Address)、变换后的虚拟地址(MVA,Modified Virtual Address)、物理地址(PA,Physical Address)
没有启动MMU时,CPU核心,cache,MMU,外设等所有部件使用的都是物理地址。
启动MMU后,CPU核心对外发出虚拟地址VA;VA被转换为MVA供cache、MMU使用,在这里MVA被转换成PA;最后使用PA读取实际设备
1、CPU核心看到和用到的只是虚拟地址VA,至于VA如果去对应物理地址PA,CPU核心不理会
2、caches和MMU看不到VA,他们利用MVA转换得到PA
3、实际设备看不到VA、MVA,读写它们使用的是物理地址PA
MVA是除CPU核心外的其他部分看到的虚拟地址,VA与MVA的变化关系如下:
if (VA < 32M) then
MVA = VA | (PID <<25)
else
MVA = VA
其中PID为进程标识号(通过读CP15的C13获得)。
使用MVA,而不使用VA的目的是:当有重叠的VA时,转换后的MVA地址并不重叠,减小转换为PA的代价
比如两个进程1、2,VA都是0-(32M-1),则MVA分别为0x02000000-0x03ffffff,0x04000000-0x05ffffff。
下文说到虚拟地址,如果没有特别指出,就是指MVA
2)虚拟地址到物理地址的转换过程
arm cpu使用页表来进行转换。页表由一个个描述符(每个4字节,32位)组成,每个描述符存储一段虚拟地址对应的物理地址及访问权限,或者下一级页表的地址
S3C2440可以以段(Section)的方式或页(Page)的方式进行转换。其中以段的方式进行转换时只用到一级页表,以页的方式进行转换时需用到两级页表:二级页表可分为粗页表、细页表;二级页表的映射按大小可映射大页(Large page 64KB)、小页(Small page 4KB)、极小页(Tiny page 1KB)。
下图为S3C2440的地址转换图(自己加了些东西,若有误,请指正,感激不尽)
需要注意的是:
1、粗页表只能映射大页和小页,细页表可以映射大页、小页和极小页。
2、TTBbase代表一级页表的地址,它由协处理器CP15的寄存器C2(称为页表基址寄存器)和MVA拼合生成。页表基址寄存器的地址必须16K对齐( [31:14]位存储页表基址,[13:0]为0)。
页表基址寄存器结构如下
3、一级页表使用4096个描述符来表示4GB空间。每个描述符存储它对应的1MB的物理空间的起始地址(段),或者下一级页表的地址。
概括的说一下MMU寻址的主要过程
首先由页表基址寄存器的[31:14]位和MVA的[31:20]位拼合成一个低两位为0的32位地址,MMU根据此地址在一级页表查询。接下来根据转换方式不同后续步骤有所不同。
若以段的方式转换, MMU在一级页表查询到段描述符。将段描述符的 [31:20]位(段基址),和MVA的[19:0]位组成一个32位的物理地址即MVA对应的PA。
若以页的方式(假设二级页表为粗页表,储存的是大页描述符)转换,MMU在一级页表查询到粗页表描述符。取出粗页表描述符的[31:10](即粗页表基址)位,和MVA的[19:12]位组成一个低两位为0的32位物理地址,通过这个地址在二级页表找到大页描述符。取出大页描述符的[31:16](即大页基址)位,和MVA[15:0]位组成一个32位的物理地址,即MVA对应的PA(其他形式只是拼接的位数略有不同、将在下面详细介绍)。
下面详细介绍下各级页表描述符的格式
一级页表描述符
最低两位:
0b00:无效
0b01:粗页表(Coarse page table)