3. ARMv7-A L1页表项格式:一级页表描述符结构
ARMv7-A 架构使用两级或三级页表实现虚拟地址到物理地址的转换。L1(一级)页表是整个转换过程的入口点,其描述符格式直接决定了地址映射的粒度与后续查找路径。本章详细解析一级页表描述符的三种类型:节描述符、粗页表描述符和细页表描述符。
3.1 一级页表描述符通用结构
一级页表(L1 Translation Table)包含 4096 个描述符项,每个描述符占用 32 位(4 字节)。虚拟地址的高 12 位(bits[31:20])作为索引,从 L1 页表中选取对应的描述符。描述符的最低 2 位(bits[1:0])用于区分描述符类型:
| bits[1:0] | 描述符类型 | 映射粒度 | 后续查找 |
|---|---|---|---|
| 0b00 | 无效(Fault) | — | 产生转换错误 |
| 0b01 | 粗页表描述符(Coarse Page Table) | 4KB / 64KB / 1MB | 指向二级粗页表 |
| 0b10 | 节描述符(Section) | 1MB | 直接映射(无二级表) |
| 0b11 | 细页表描述符(Fine Page Table) | 4KB / 64KB / 1MB / 16MB | 指向二级细页表 |
关键提示: bits[1:0] = 0b10 是节描述符,直接完成 1MB 块映射,无需二级页表,是性能最优的映射方式。粗页表和细页表描述符则需要进一步查找二级页表。
3.2 节描述符(Section Descriptor)
节描述符用于将 1MB 的虚拟地址块直接映射到物理地址块。当 bits[1:0] = 0b10 时,描述符格式如下:
31 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+-------------------------------------------------------------------------------------------------------+
| 节基地址[31:20] | 0 | 0 | 0 | nG | S | APX | TEX[2:0] | AP[2:1] | 0 | 0 | 0 | C | B | 1 | 0 |
+-------------------------------------------------------------------------------------------------------+
| 位域 | 宽度 | 说明 |
|---|---|---|
| [31:20] | 12 bits | 物理地址高位(物理节基地址),与虚拟地址低 20 位拼接形成 1MB 物理地址 |
| [19] | 1 bit | SBZ(应为 0),架构保留 |
| [18:17] | 2 bits | 域(Domain),用于访问控制检查 |
| [16] | 1 bit | nG(非全局位),用于 TLB 标记 |
| [15] | 1 bit | S(可共享位),用于缓存一致性 |
| [14] | 1 bit | APX(访问权限扩展),与 AP 共同决定权限 |
| [13:11] | 3 bits | TEX(类型扩展),与 C/B 共同决定内存类型和缓存策略 |
| [10:9] | 2 bits | AP(访问权限),控制读写权限 |
| [8:5] | 4 bits | SBZ(应为 0) |
| [4] | 1 bit | C(缓存位),与 TEX/B 配合 |
| [3] | 1 bit | B(缓冲位),与 TEX/C 配合 |
| [1:0] | 2 bits | 类型标识 = 0b10 |
节映射示例: 若虚拟地址 0x10000000 对应的 L1 描述符中节基地址为 0x20000,则虚拟地址 0x10000000~0x100FFFFF 映射到物理地址 0x20000000~0x200FFFFF。虚拟地址的低 20 位直接作为物理地址的低 20 位偏移。
3.3 粗页表描述符(Coarse Page Table Descriptor)
粗页表描述符指向一个二级粗页表(Coarse Page Table),该二级表包含 256 个描述符项,每个项对应 4KB 页面。当 bits[1:0] = 0b01 时,描述符格式如下:
31 10 9 8 7 6 5 4 3 2 1 0
+-------------------------------------------------------------------+
| 粗页表基地址[31:10] | 域[2:0] | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
+-------------------------------------------------------------------+
| 位域 | 宽度 | 说明 |
|---|---|---|
| [31:10] | 22 bits | 二级粗页表的物理基地址(1KB 对齐) |
| [9:7] | 3 bits | 域(Domain),用于访问控制检查 |
| [6:2] | 5 bits | SBZ(应为 0) |
| [1:0] | 2 bits | 类型标识 = 0b01 |
注意: 粗页表描述符的基地址必须 1KB 对齐(即 bits[9:0] 为 0)。二级粗页表的大小为 1KB(256 项 × 4 字节),因此整个二级表恰好占用 1KB 空间。
粗页表描述符的二级查找流程:
- 从 L1 描述符中提取粗页表基地址(bits[31:10]),拼接 10 位 0 得到二级表物理地址。
- 虚拟地址的 bits[19:12](8 位)作为索引,从二级粗页表中选取对应的二级描述符。
- 二级描述符可以是 4KB 页描述符、64KB 大页描述符或无效描述符。
3.4 细页表描述符(Fine Page Table Descriptor)
细页表描述符指向一个二级细页表(Fine Page Table),该二级表包含 1024 个描述符项,每个项对应 1KB 页面。当 bits[1:0] = 0b11 时,描述符格式如下:
31 12 11 10 9 8 7 6 5 4 3 2 1 0
+-----------------------------------------------------------------------+
| 细页表基地址[31:12] | 0 | 域[2:0] | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
+-----------------------------------------------------------------------+
| 位域 | 宽度 | 说明 |
|---|---|---|
| [31:12] | 20 bits | 二级细页表的物理基地址(4KB 对齐) |
| [11] | 1 bit | SBZ(应为 0) |
| [10:8] | 3 bits | 域(Domain),用于访问控制检查 |
| [7:2] | 6 bits | SBZ(应为 0) |
| [1:0] | 2 bits | 类型标识 = 0b11 |
细页表 vs 粗页表: 细页表支持 1KB 最小页面粒度,二级表大小为 4KB(1024项 × 4字节),基地址要求 4KB 对齐。粗页表支持 4KB 最小粒度,二级表大小为 1KB,基地址要求 1KB 对齐。细页表提供更细的映射粒度,但页表开销更大。
3.5 三种描述符对比总结
| 特性 | 节描述符 | 粗页表描述符 | 细页表描述符 |
|---|---|---|---|
| bits[1:0] | 0b10 | 0b01 | 0b11 |
| 映射粒度 | 1MB(直接映射) | 4KB / 64KB(二级表) | 1KB / 4KB / 64KB / 16MB(二级表) |
| 二级表大小 | 无 | 1KB(256项) | 4KB(1024项) |
| 基地址对齐 | 1MB | 1KB | 4KB |
| 页表开销 | 最小(仅L1表) | 中等(L1 + 1KB二级表) | 最大(L1 + 4KB二级表) |
| 适用场景 | 大块连续内存(内核、设备) | 通用进程地址空间 | 需要1KB细粒度映射(嵌入式) |
| TLB效率 | 最高(单级查找) | 中等(两级查找) | 较低(两级查找,项多) |
实践建议: 在 ARMv7-A 的 Linux 内核实现中,默认使用粗页表描述符(L1类型=0b01),配合二级4KB页表。节描述符常用于线性映射区域(如内核直接映射区)。细页表描述符由于页表开销大且硬件支持有限,在实际系统中很少使用。