文章目录
- 1.1 MMU
- 1.1.1 虚拟地址位宽配置
- 1.1.2 页面大小(grandule size)配置
- 1.1.3 AArch64 页表项描述符格式
- 1.1.4 内存属性配置
1.1 MMU
1.1.1 虚拟地址位宽配置
64 位虚拟地址中,并不是所有位都用上,除了高 16 位用于区分内核空间和用户空间的虚拟地址外,虚拟地址的有效位的配置可以是:36, 39, 42, 47。在代码中,可以看到寄存器 TCR_EL1, Translation Control Register (EL1)
有关 T0SZ
, T1SZ
的设置, 这个域就是用来配置这个项目的, 虚拟地址的有效位数为 64-TxSZ
(或者, 也可以说 TxSZ
是用来设置高位无效位数的):
图 1-1 TCR_EL1
- T1SZ, bits [21:16] 通过TTBR1寻址的内存区域的大小偏移量;
- T0SZ, bits [5:0] 通过TTBR0 寻址的内存区域的大小偏移量;
比如, 我们如果希望使用 48
位的虚拟地址, 就会将TxSZ
设置为 64-48=16
, 也即 TRC_ELx.TxSZ 设置为 16。如果需要使用 39bit 的虚拟地址那么就设置为 25。
比如我使用的内核中有效位配置为 CONFIG_ARM64_VA_BITS=39
:
用户空间地址范围:0x00000000_00000000 ~ 0x0000007f_ffffffff
,大小为 512G;
内核空间地址范围:0xffffff80_00000000 ~ 0xffffffff_ffffffff
,大小为 512G。
1.1.2 页面大小(grandule size)配置
支持 3 种页面大小:4KB, 16KB, 64KB
,见 TRC_ELx.TGx
:
三种不同的粒度及虚拟地址位宽会影响所需 translation table level 的 数量配置和大小配置。
以
4KB
grandule size且 虚拟地址为48bit
为例, 硬件可以使用四级查表。每一级的地址转换有9 bit
,所以每个页表2^9=512
项 (即 512个 entry),需要 VA 的 9位做索引。
9位,9位,9位,9位,12位,如下图:
图 1-2 VA=48 Grandule=4K
- VA的[47:39] 索引到 L0 表的 512项。每个表项对应
512GB(2^39)
范围,并指向 L1 表; - L1 table 中也有 512个 entry, 每一个entry指向 L1 table 或 1GB block;
- L2 table 的 entry 指向 L3 的 table 或 2M block;
- L3 table 的 entry 指向 4KB block 的基地址。
- VA的[47:39] 索引到 L0 表的 512项。每个表项对应
以
16KB
grandule size为例,每个页表2^11
项=2048项,需要VA
的11
位提供索引。
1位,11位,11位,11位,14位:
Level0 表仅包含两项,对应 128TB范围如下
图 1-3 VA=48 Grandule=16K
以
64KB
grandule size为例,每个页表2^13
项=8192项,需要 VA 的13 位提供索引。
13位,13位,13位,16位:
图 1-4 VA=48 Grandule=64K
- 以
4KB
grandule size且 虚拟地址为39bit
为例,如果要使用 leve0 table的话,那么只能使用BIT[38:38]
表示,我们从上文可以知道BIT[38:30]
已经给 level1用了,所以这种情况下不需要使用 level0,直接从 level1开始就可以完全表示整个39bit 的虚拟地址空间了。
图 1-5 VA=39 Grandule=64K
而如果虚拟地址空间只有 30 位,那么只需要从 level2 开始就可以完整表示整个地址空间了。也即, 虚拟地址空间越小,那么所需的level也就越小。
1.1.3 AArch64 页表项描述符格式
AArch64 描述符格式被用在所有级别的表中,从Level 0 到 Level 3。
Level 0 描述符仅能输出 Level 1表的地址。
Level 3 描述符不能指向其它表,仅能输出最终内存页的地址。因而 Level 3 格式稍有不同。
页表项的 [1:0]
位用于表示页表项的类型:
- bit[0] 为 0 表示表示该页表项无效, bit[1] 才表示该页表项有效;
- bit[0] 为 1,bit[1] 为 0 表示该页表项是个 Block descriptor, 也就是该页表项中的 Output address 填写的是物理地址,也即下图中[49:n]域填写的是物理地址,该物理地址加上 [n-1:0] 偏移即可获取实际物理地址。
- bit[0] 为 1,bit[1] 为 1 表示该页表指向下一级 table。
1.1.4 内存属性配置
UXN or XN Excute-never, 决定了descriptor指向的region是否excuteable
PXN privileged excute-never, 决定了descriptor指向的region在EL1是否excuteable
Contiguous 该表项是否为连续表项中的一项。即转换表在该表项前后是连续的,没有空洞。这样,这些连续的表项便有可能一次性加载到cache中(比如由一个TLB entry缓存)
DBM dirty bit modifier, dirty bit指示内存页有没有被修改
nG not global, 指明当前的 entry 是 global(nG=0,所有process都可以访问) 还是non-global(nG=1,only本process允许访问)。
- 如果是global类型,则 TLB 中不会 tag ASID;
- 如果是non-global类型,则 TLB 会 tag上 ASID,且 MMU 在 TLB 中查询时需要判断这个 ASID 和当前进程的 ASID 是否一致,只有一致才证明这条 entry 当前 process 有权限访问。
AF access flag,当该标志为0,标明对应的内存区域(一个block或者一个page)是第一次访问;
SH[1:0] shareable attribute: 指当前内存页表项的数据是否可以同步到其它CPU上,多核CPU调用带有该属性页表项的数据,一旦某个CPU修改了数据,那么系统将自动更新到其它CPU的数据拷贝,实现内存数据一致性。对于Normal类型的内存,有 3 种情况:
Inner Shareable, 该内存位置可以被InnerShareability domain 中的所有处理器访问,并且硬件保证该位置在这些处理器间的数据一致性,InnerShareability domain中的处理器一般被同一个虚拟机监视器或操作系统控制;
Outer Shareable, 该内存位置可以被OuterShareability domain中的所有处理器访问,并且硬件保证该位置在这些处理器间的数据一致性,InnerShareability domain 是OuterShareability domain的一个子集;
Non-shareable, 该内存位置一般只能被唯一处理器访问,如果还有其他处理器能访问该位置,可能需要软件用缓存一致性指令来保证缓存一致性。
AP[2:1] access permission, 设置数据访问的权限,可以设置为 4 种:
NS security bit, 对于从安全状态访问内存,指定输出地址是在安全地址映射中还是在非安全地址映射中:
- NS == 0 访问安全PA空间;
- NS == 1 访问非安全PA空间 。
对于从非安全状态进行的存储器访问,该位为RES 0,被PE忽略。
AttrIndx index into the MAIR_ELn, 指向内存区域的类型以及可缓存性(见下文)
推荐阅读:
https://developer.arm.com/documentation/102416/0100/Single-level-table-at-EL3?lang=en