对于刚刚学习ARM嵌入式的人来说,遇到的第一个难点我觉得就是地址映射的原理,往往会被一些概念弄得稀里糊涂(比如像我这种智商不高的)。所以就静下心自己好好研读了以下杜春雷《ARM体系结构与编程》有关MMU和地址映射的讲解,个人感觉写得比较清晰,以下是自己在读的时候理解的内容,如有不正,请指出! 对于32为ARM处理器,最大寻址空间为4GB(2^32),但是物理空间并没有配置到这么大,所以对于VA来说,其地址为0x00000000~0xFFFFFFFF,对于PA来说,其地址应小于或等于0xFFFFFFFF。 地址映射原理:
把虚拟地址划分为一定大小空间的存储块,同样,物理空间也划分为同样大小的块。
然后,依照存储块的大小,可分为:1、段(1MB) 2、大页(64KB) 3、小页(4KB) 4、极小页(1KB)
第一种称为段模式,后面三种称为页模式
这些映射,都是通过页表实现的,页表又可可以分为:一级页表(用于段模式)
二级页表(用于页模式)
什么是页表呢?页表就是存储在内存中(会被拷贝到SDRAM中存放,以供MMU查询),用于表示VA与PA
的映射关系的一个表格。表格中每项称为条目,条目里的内容称为描述符(段描述符和页描述符)。
页表(存储单元cell) | 条目n | 条目n-1 | …… | …… | 条目1(物理基址bit[31,12]+描述符bit[11,0]) |
段模式:
以段模式映射时,因为VA大小位4GB,段模式每个条目表为1MB大小的空间,所以全映射时,
条目总数(全映射时页表所占内存空间)=4GB / 1MB =4096条(每条32位,即4字节,共 4 KB)。
其中,所谓的每个条目大小为1MB,意思是,CPU发出的一段地址范围为1MB的VA(假如0x00000000~0x000FFFFF),这一段VA经过MMU变换,都会索引(查找)到同一个条目。该条目再次结合VA(PA的[19:0]位,称为段内地址偏移量),形成真正的PA地址。具体请看下图
对于段模式,其只需要使用一级页表。页表中,条目中存储的描述符格式如下:
31 20 | 19 12 | 11 10 | 9 | 8 5 | 4 | 3 | 2 | 1 | 0 | 段基址 | 0 | AP | 0 | Domain域 |
| C | B | 1 | 0 |
1、段基址: 在设计地址映射时,要映射的物理地址要1MB对齐,段基址就是这段1MB物理地址起始地址的
高[31:20]位,每个条目中的描述符的段基址都不一样(以段来说,相差1MB)。
2、AP: AP是用来设置权限的,与C1的R/S位结合使用。
3、Domain域: 不管是段模式还是页模式,系统都把4GB空间分为16个域,每个域有相同的权限检查
(在C3设置 ),这里的Domain是用来标识本段所在的域
4、C/B: C/B位是控制位,与本条目(描述符)所在域的Cache和Buffer有关(是否允许本域开启Cache和Buffer)
5、[1:0]=0b10: 表示本描述符是表示段模式(段描述符标识)
设置页表的思路:
1、确定那段VA映射到那段PA,以及映射方式(段/页)
以段为例:VA(0xB0000000~0xB0100000【1MB】)映射到PA(0xA0000000~0xA0100000)
2、确定段基址: PA=0xA0000000
同时记录VA=0xB0000000
3、确定页表存放在那个位置,然后确定页表基址(页表存储位置起始地址及C2设置值):
如存放在内存 0x00000000处。
则页表基址(设置为指针)
unsigned long *page_table_base=(unsigned long *)0x00000000
4、提前把条目中的描述符的低[11:0]位设置好,假设为MMU_DECSET
5、根据公式把条目描述符与段基址整合成完整条目存储到页表所在内存地址:
*(page_table_base+(VA>>20))=(PA&0xFFF00000)|MMU_DECSET; //页表所在偏移地址,指向页表存储的位置
这样,就把描述符(条目)(PA&0xFFF00000)|MMU_DECSET 存储到 *(page_table_base+(VA>>20))
指向的地址。
6、如果设置多个条目, 使用循环,每次将PA和VA的值增加1MB(0x10 0000),再存储到页表中。
|