1、页表:

页表是实现虚拟地址到物理地址转换的一个重要手段
我们在使用MMU以前,需要在内存中新建一个页表页表中的每一行(即一个字的大小)存放的是一个物理内存页的基地址(该基地址需要根据当前的分页技术再还原到同位),该页的访问权限和缓冲特性等,这里将页表中这样的一行称为一个地址变换条目

SofTool’s Notes:

  1. 名词
    页表 的英文名称为 translation table
    条目 的英文名称为 entry
  2. 页表中的每行对应一个页号索引值,同时该行简称为条目entry;

页表存放在内存中,CP15的C2寄存器用来存放页表的基地址

2、页和页框:

多数使用虚拟存储器的系统都使用一种称为分页(paging)的技术。

分页技术原理:

  • 虚拟地址空间被划分,单位是页(page)
  • 相应的物理地址空间也被划分,单位是页框(frame)
  • 页(page)和页框(page frame)的大小必须相同

3、虚拟地址:

3.1 虚拟地址被MMU分为两部分

  1. 页号索引(page Index);
  2. 相对该页首地址的偏移量(offset);

3.2 CPU访问物理地址的变换流程:

当CPU访问一个地址时(注意:该地址是虚拟地址),首先该地址被送到MMU,MMU再根据虚拟地址的高几位作为页号索引在页表中查找对应的地址变换条目(entry)地址变换条目(entry)中找到物理地址的页基地址再加上虚拟地址中的偏移量便得到了真正的物理地址最后由MMU将物理地址发送到地址总线上,访问物理内存。

问:在页表中MMU如何使用页号索引找到对应的地址变换条目(entry)呢?
答:MMU利用CP15协处理器中的C2寄存器存放的页表基地址加上虚拟地址的页号索引值,然后便得到了页表中对应的地址变换条目的地址。
其实页号索引值就是相对于页表基地址的一个偏移量,然后使用基地址加偏移量的方式得到一个页表中的地址。

3.3 示例(该示例以”段”分页为例):

我们先来看看,当分页大小为1M(即:存储块大小为 段 的情况)时对应的转换示意图:

02_地址映射原理 - 图1

然后我们再以一个具体的实例来看看具体的转换过程:
假设 当前的虚拟地址为0x30000012,那么虚拟地址的二进制码为 00110000 00000000 00000000 00010010.

高12位(bit[31,20])为页号索引(page index)
低20位(bit[19,0])为偏移量(offset),因为220=1M2^{20} = 1M

高12位页号索引为00110000 0000(二进制) = 0x300 = 768(十进制),所以在页表中找到相对于页表基地址的偏移量为768的地址,然后得到地址变换条目,该条目的值为0x0300。于是0x0300 << 20位,便得到了物理页基地址,再加上虚拟地址中的偏移位 0000 00000000 00010010(二进制) = 0x12,便得到了真正的物理地址 0x30000012 。

02_地址映射原理 - 图2

4、TLB的概念:

从虚拟地址到物理地址的变换过程,其实就是查询页表的过程,由于页表存放在内存中,这个查询过程通常代价很大。而程序在执行过程中具有局部性,也就是说,一段时间内,对页表的访问只是局限在少数几个单元中。根据这个特点,采用一个容量更小、访问速度更快的存储器(该存储器可以简单理解为和寄存器速度相当的东西)来存放当前访问需要的地址变换条目。这个小容量的页表称为快表,也称TLB.

注:
TLB = translation lookaside buffer

当CPU访问内存时,现在TLB中查找需要的地址变换条目。如果该条目不存在,CPU从位于内存的页表中查询,并把相应的结果添加到TLB中。这样,当CPU下一次又需要该地址变换条目时,可以从TLB中直接得到,从而使地址变换的速度大大加快。

当内存中的页表内容改变 或者 通过修改CP15中的寄存器C2使用新的页表时,TLB的内容需要全部清除(MMU提供了相关的硬件支持这种操作)。CP15中的寄存器C8用来控制清除TLB内容的相关操作。

MMU可以将某些地址变换条目锁定在TLB中,从而使得进行与该地址变换条目相关的地址变换速度保持很快。在MMU中C10用于控制TLB内容的锁定。

注:
TLB中存放的是地址变换条目,相当于一个小页表。

4.1 使无效TLB内容

当内存中的页表内容改变,或者通过修改协处理器CP15的寄存器来使用新的页表时,TLB中的内容需要全部或者部分使无效。所谓使无效是指将TLB中的某个地址的地址变换条目表示成无效,从而在TLB中找不到该地址变换条目,而需要到内存页表中重新查找该地址变换条目。如果不进行TLB的使无效操作,可能造成同一个虚拟地址对应于不同的物理地址(TLB中保存的还是旧的地址映射关系,而内存中的页表已经存了新的地址映射关系)。

有时候页表可能只是部分内容改变了,只影响了很少的地址映射关系,这种情况下,可以只使无效TLB对应的单个地址变换条目可能会提高系统性能。

系统协处理器CP15的寄存器C8就是清除TLB内容的相关操作。C8是一个只写的寄存器

MCR    p15,0,Rd,c8,CRm,opcode_2

mcr指令用法,请参考: https://www.softool.cn/read/arm_assembly/mcr.html

Rd中为要写入C8寄存器的内容,CRm和opcode_2的不同组合决定指令执行的不同操作。

指令 Rd 含义
MCR p15, 0, Rd, c8, c5, 0 0 使无效整个指令TLB
MCR p15, 0, Rd, c8, c5, 1 虚拟地址 使无效指令TLB中的单个地址变换条目
MCR p15, 0, Rd, c8, c6, 0 0 使无效整个数据TLB
MCR p15, 0, Rd, c8, c6, 1 虚拟地址 使无效数据TLB中的单个地址变换条目
MCR p15, 0, , c8, c7, 0 0 使无效整个数据和指令TLB
MCR p15, 0, , c8, c7, 1 虚拟地址 使无效数据和指令TLB中的单个地址变换条目

4.2 锁定TLB的内容:

在MMU中寄存器C10用于控制TLB内容的锁定

5、存储访问过程:

5.1 使能MMU时的存储访问过程。

当ARM处理器请求存储访问时,首先在TLB中查找虚拟地址。如果系统中数据TLB和指令TLB是分开的,在取指令时,从指令TLB查找相应的虚拟地址,对于其他内存访问操作,从数据TLB中查找相应的虚拟地址。

如果虚拟地址对应的地址变换条目不在TLB中,CPU从位于内存的页表中查询,并把相应的结果添加到TLB中。如果TLB已经满了,还需要根据一定的淘汰算法进行替换。这样,当CPU下一次又需要该地址变换条目时,可以从TLB中直接得到,从而使地址变换的速度大大加快。

当得到了需要的地址变化条目以后,将进行以下操作:

  1. 得到该虚拟地址对应的物理地址;
  2. 根据条目entry中的C(cache)控制位和B(Bufferable)控制位决定是否缓存该内存访问的结果;
  3. 根据存取权限控制位和域访问控制位确定该内存访问是否被允许
    如果该内存访问不被允许,CP15向ARM处理器报告存储访问中止;
  4. 对于不允许缓存的存储访问,使用步骤1中得到的物理地址访问内存。
    对于允许缓存的存储访问,如果在cache命中,则忽略物理地址;
    如果cache没有命中,使用步骤1中得到的物理地址访问内存,并把该块数据读取到cache中;

02_地址映射原理 - 图3

5.2 禁止MMU时存储访问过程

  • 禁止MMU时,是否支持cache和write buffer由各个具体芯片的设计确定。如果芯片规定禁止MMU时禁止cache和write buffer,则存储访问将不考虑C、B控制位。如果芯片规定当禁止MMU时可以使能cache和write buffer,则数据访问时,C=0,B=0;指令读取时,如果使用分开的TLB则C=1,如果使用统一的TLB则C=0;
  • 存储访问不进行权限控制,MMU也不会产生存储访问中止信号
  • 所有的物理地址和虚拟地址相等,即使用平板模式

5.3 禁止/使能MMU时应注意的问题

  • 在使能MMU之前,要在内存中建立页号表,同时CP15中的各相关寄存器必须完成初始化。
  • 如果使用的不是平板存储模式(物理地址和虚拟地址相等),在禁止/使能MMU时,虚拟地址和物理地址的对应关系会发生改变,这时应该清除cache中的当前地址变换条目。
  • 如果完成禁止/使能MMU的代码的物理地址和虚拟地址不相同,则禁止/使能MMU时会造成很大麻烦,因此强烈建议完成禁止/使能 MMU的代码的物理地址和虚拟地址最好相同。

6、MMU中的地址变换过程

在ARM中,虚拟地址到物理地址的映射有两种方式:一级映射和二级映射。

6.1 一级映射

当使用一级映射时,只会用到一张页表,我们将它称为 一级页表,用 L1 表示

一级映射时,虚拟空间被划分成 段 的单位,每段的大小为 1M。而相应的物理空间也被进行这样的划分,单位是 段框,段和段框的大小必须相同 。

于是,首先在内存中建立一张页表(这个页表由我们自己建立),页表中的每一项存放的是一个物理段基地址,该页的访问权限和缓冲特性等。页表中每一项的大小为4字节,所以每一项的地址是字对齐。我们将页表中的每一格称为一个项。

因为ARM的可寻址范围为4G,且虚拟空间的每段大小为 1M,所以如图所示,页表有4096个项。每一项对应一个段,每一项中存放的是一个物理段基地址,该页的访问权限和缓冲特性等。

虚拟地址被MMU分为两部分,第一部分为 页索引号(bits[31:20]),第二部分是相对物理地址的 偏移量(bits[0:19])。

所以当访问一个地址时,此地址是虚拟地址。MMU 会用协处理器CP15的C2寄存器中的 页表基地址+页索引号便查到了页表中对应的一项,从页表中相应的项中找到物理段基地址,然后: 物理段基地址 + 偏移量(这个是虚拟地址的第二部分) = 物理地址

注:
虚拟空间并不真实存在,只是为方便理解才这么说。

示例:
CPU要访问 0x300008 的地址,此地址为虚拟地址。MMU会根据页索引号(也就是 0x3 )找到相对页表基地址偏移量为 0x3 的项。这个项中的物理段基地址为 0x006
*物理地址 = (0x006<<20)+0x8=0x600008 *

02_地址映射原理 - 图4

一级页表中一项的详细内容如下表所示:

02_地址映射原理 - 图5

段基地址:也就是物理空间的段首地址,1M大小对齐
AP:    访问控制位Access Permission
域:     标明了当前段属于哪个域 。Domain与AP配合使用,对访问权限进行检查
C:    如下表所示
B:     如下表所示

02_地址映射原理 - 图6


bits[1:0]:
00:相应1M的虚拟空间并没有被映射到物理空间,因此访问该存储空间将会产生地址变换失效信号,所以bits[31:2]的内容无效
10:这是一个一级映射的地址变换,所以存储的是要访问的物理段基地址
01:这是一个二级映射的地址变换,所以存储的是粗粒度的二级页表的基地址(后面会讲)11:这是一个二级映射的地址变换,所以存储的是细粒度的二级页表的基地址(后面会讲)

域标明了当前 段属于哪个域。然后该段便具有了和该域一样的访问权限。

CP15 的寄存器 C3:

02_地址映射原理 - 图7

在 CP15的C3寄存器中,划分了 16个域,每个区域由两位构成,这两位说明了当前内存的检查权限:
00:当前级别下,该内存区域不允许被访问,任何的访问都会引起一个domain fault,这时 AP位无效
01:当前级别下,该内存区域的访问必须配合该内存区域的段描述符中AP位进行权检查
10:保留状态(我们最好不要填写该值,以免引起不能确定的问题)
11:当前级别下,对该内存区域的访问都不进行权限检查。 这时 AP位无效

所以只有当相应域的编码为 01 时,才会根据 AP位 和协处理器CP15中的C1寄存器的S,R位进行权限检查

02_地址映射原理 - 图8

6.2 二级映射

当使用二级映射时,一级页表L1仍然存在,但是一级页表中不再存放物理段基地址了,而是存放了二级页表的基地址,也就是二级页表的首地址。

一级页表要表示4G的地址范围,一共4096项,每一项都表示1M 的大小。二级页表相当于对一级页表这1M的范围作更详细的划分,所以每个二级页表要表示1M 的地址范围。

对这1M地址范围进行分页,有三种分法:
大页:将这1M地址范围分成单位为64KB大小
小页:将这1M地址范围分成单位为4KB大小
极小页:将这1M地址范围分成单位为1KB大小

注:
二级页表分为两类:粗粒度的二级页表和细粒度的二级页表。

粗粒度的二级页表:
当二级页表为粗粒度时,一级页表中一项的内容如下表所示:

02_地址映射原理 - 图9


因为不论是一级页表还是二级页表,页表中的每一项都是四个字节,所以页表中每一项的地址都是字对齐的,也就是最低两位的值都为 0。所以因为粗粒度的二级页表的基地址为22位,而偏移量只能为8位,则粗粒度的二级页表中只能有256个项,大小为 1KB。而这256个项要表示1M大小,所以粗粒度二级页表中的每个项要表示4KB的物理空间范围。

细粒度的二级页表:
当二级页表为细粒度时,一级页表中一项的内容如下表所示:

02_地址映射原理 - 图10


因为不论是一级页表还是二级页表,页表中的每一项都是四个字节,所以页表中每一项的地址都是字对齐的,也就是最低两位的值都为 0。所以因为细粒度的二级页表的基地址为20位,而偏移量只能为10位,则细粒度的二级页表中能有1024个项,大小为4 KB。而这 1024 个项要表示1M大小,所以细粒度二级页表中的每个项要表示1KB的物理空间范围。

首先讨论粗粒度的二级页表:分页方式为大页64KB。上面已经说了一个粗粒度的二级页表中每一项能表示的物理地址范围只能为4KB,那么64KB的地址范围怎么表示呢?这时其实已经把4KB的地址范围变为了64KB的地址范围,也就是页表中的一项能表示64KB的地址范围。这时物理地址偏移量要占用二级页表索引号的bits[15:12] ,这样才能表示64KB的物理地址范围。

因为现在二级页表的一项中存放的是64KB地址范围的物理基地址,则物理地址偏移量使用的是bits15:0, 所以bits[15:12]在0b0000—0bFFFF范围变化时,物理基地址仍然相同。但是随着bits[15:12]的变化,二级索引号也会发生变化,那么得到的项的地址就会变化。所以为了让物理基地址相同,必须在连续16个项中都存放相同的内容,这样根据二级页表索引号所找到的连续16个项地址虽然不同,但每一个项中的物理基地址都相同。再与物理地址偏移量(虚拟地址的bits[15:0])相加,就会得到物理地址。

所以当当分页方式为大页64KB时,粗粒度二级页表用16个项对应一页,

02_地址映射原理 - 图11

粗粒度二级页表中一项的详细内容如下表:

02_地址映射原理 - 图12


大页基地址:就是64KB页的首地址
一个大页分为4个子页:
AP0 子页1的访问控制权限位
AP1 子页2的访问控制权限位
AP2 子页3的访问控制权限位
AP3 子页4的访问控制权限位
C:    如下表所示
B:     如下表所示

02_地址映射原理 - 图13


bits[1:0] :当前页表的分页方式:01:大页 10:小页 11:极小页

当分页方式为小页4KB时,粗粒度二级页表的一项正好对应一页。其地址变换方式和一级映射相似。
当分页方式为极小页1KB时,粗粒度二级页表无法表示。

接下来是细粒度的二级页表:
因为细粒度二级页表的一项只能表示1KB的物理地址范围,所以:
当分页方式为大页64KB时,细粒度二级页表的64个项对应一页。其地址变换方式参考粗粒度二级页表的大页变换方式
当分页方式为小页4KB时,细粒度二级页表的4个项对应一页。其地址变换方式参考粗粒度二级页表的大页变换方式
当分页方式为极小页1KB时,细粒度二级页表的一项正好对应一页,其地址变换方式与一级映射相似。