📖
🎥 B 站博文精讲视频:点击链接,配合视频深度学习
四级页表通俗讲解与实践(以 64 位 ARM Cortex-A 为例)
本文面向希望彻底理解现代 64 位架构下四级页表的开发者,结合 ARM Cortex-A 系列处理器,详细讲解虚拟地址到物理地址的映射全过程。结构清晰,细节完整,结合真实虚拟地址与物理地址举例,适合学习与实践。
一、四级页表是什么?
1. 概念引入
- 在现代 64 位处理器(如 ARMv8-A Cortex-A 系列)中,内存管理单元(MMU)将 虚拟地址(VA) 转换为 物理地址(PA)。
- 为了高效管理大空间内存,ARMv8-A 采用四级页表结构,层层映射。
- 页表本质是多级查找的“索引表”,每一级根据虚拟地址的一部分找到下一级页表或物理页框。
2. 四级页表的结构
-
每一级页表存放固定数量的表项,每个表项保存下一级页表的物理基地址及权限/属性等。
-
常见配置下:
- 每级索引 9 位,512 个表项(2⁹ = 512)
- 最后 12 位为页内偏移(支持 4KB 页大小)
-
总共:9 + 9 + 9 + 9 + 12 = 48 位虚拟地址
| LVL0 | LVL1 | LVL2 | LVL3 | Offset |
|------|------|------|------|--------|
| 9bit | 9bit | 9bit | 9bit | 12bit |
|<---------- 48 位虚拟地址 ------------>|
-
在 ARM 文档/代码中,四级页表常称为:
- Level 0 table(L0)
- Level 1 table(L1)
- Level 2 table(L2)
- Level 3 table(L3)
- 每一级页表项均为 8 字节(64 位),其中高位用于存储下一级物理基地址。
二、虚拟地址如何拆分?(以 Cortex-A 64 位为例)
假设一个 48 位虚拟地址:
0x0000_1234_5678_9ABC
拆解如下:
位段 | 位数 | 含义 | 示例值 |
---|---|---|---|
47 ~ 39 | 9 | L0 索引(表项) | 0x0000000000000002 |
38 ~ 30 | 9 | L1 索引 | 0x0000000000000046 |
29 ~ 21 | 9 | L2 索引 | 0x00000000000000B0 |
20 ~ 12 | 9 | L3 索引 | 0x0000000000000123 |
11 ~ 0 | 12 | 页内偏移(4KB 页) | 0x00000000000009ABC |
(示例值以实际拆分得到的二进制高/低位为例,便于理解)
三、查表过程:虚拟地址到物理地址的详细流程
1. 分解虚拟地址
- 每一级用虚拟地址的 9 位做索引,查找该级表的第 N 项。
- 最后 12 位为页内偏移。
2. 四级查找过程(ARM 通用流程)
- L0 表基地址(由 TTBR0/TTBR1 寄存器给出,物理地址)
- 用 L0 索引查表,得到 L1 表物理地址(通常 4KB 对齐)
- 用 L1 索引查表,得到 L2 表物理地址
- 用 L2 索引查表,得到 L3 表物理地址
- 用 L3 索引查表,得到最终物理页框地址(高位)
- 用页内偏移补齐低 12 位,拼出完整物理地址
3. 图示结构
VA [47:39] [38:30] [29:21] [20:12] [11:0]| | | | |v v v v v+-------------------------------------------------+| L0 | L1 | L2 | L3 | Offset |+-------------------------------------------------+
四、完整举例:Cortex-A 64 位四级页表查找过程
例子设定
假设有如下参数:
- TTBR0_EL1 = 0x4000_0000(L0 页表物理基地址)
- 虚拟地址 VA = 0x0000_1234_5678_9ABC
1. 拆分虚拟地址
- L0 索引 = (VA >> 39) & 0x1FF = (0x0000_1234_5678_9ABC >> 39) & 0x1FF = 0x2
- L1 索引 = (VA >> 30) &
F = (0x0000_1234_5678_9ABC >> 30) & 0x1FF = 0x46 - L2 索引 = (VA >> 21) & 0x1FF = (0x0000_1234_5678_9ABC >> 21) & 0x1FF = 0xB0
- L3 索引 = (VA >> 12) & 0x1FF = (0x0000_1234_5678_9ABC >> 12) & 0x1FF = 0x123
- Offset = VA & 0xFFF = 0x9ABC
2. 查找过程
-
Step 1:L0(TTBR0_EL1 + 2 × 8)
- L0表的第2项,假设内容为 0x0000_6000_0003 (L1表物理基地址 0x6000_0000)
-
Step 2:L1(0x6000_0000 + 0x46 × 8)
- L1表的第70项,内容为 0x0000_7F00_0003 (L2表物理基地址 0x7F00_0000)
-
Step 3:L2(0x7F00_0000 + 0xB0 × 8)
- L2表的第176项,内容为 0x0000_9000_0003 (L3表物理基地址 0x9000_0000)
-
Step 4:L3(0x9000_0000 + 0x123 × 8)
- L3表的第291项,内容为 0x0000_A200_3003 (物理页框基地址 0xA200_3000)
-
Step 5:加上 offset
- 物理地址 = 0xA200_3000 + 0x9ABC = 0xA200_CABC
3. 总结查表过程
- 虚拟地址 VA = 0x0000_1234_5678_9ABC
- 物理地址 PA = 0xA200_CABC
- 每一级查表都用虚拟地址的 9 位,+ 8 字节(64 位表项大小)
- 终极目标:虚拟地址的页内偏移直接对应物理地址的低 12 位,高位来自页表递归查找结果。
五、总结与实战要点
- 四级页表让大内存空间管理变得高效且灵活,支持细粒度权限和属性控制。
- 只要搞懂“每一级 9 位索引 + 最后 12 位偏移”,四级页表的本质其实非常直观。
- ARM Cortex-A(v8 64 位)架构四级页表结构和 x86_64 类似,易于类比和移植理解。
- 实际开发中,如需分析虚拟地址映射,结合 TTBR0/TTBR1、页表物理地址、虚拟地址拆分即可快速定位。
小结:四级页表是一种多级查找机制,核心在于“索引分段 + 递归查表”,只要学会虚拟地址的二进制拆分与索引对应,每一级表项的物理地址拼接,配合工具观测,就能轻松掌握虚拟到物理的完整映射流程。
视频教程请关注 B 站:“嵌入式 Jerry”