3. ARMv8-A 页表格式:描述符结构与属性位详解

ARMv8-A 架构的页表采用多级查找结构,每一级页表条目(Page Table Entry, PTE)称为描述符。描述符不仅包含下一级页表的物理地址,还携带了内存属性、访问权限、安全状态等关键信息。理解描述符的格式是配置 MMU 和管理 TLB 的基础。

3.1 页表描述符通用结构

每个描述符占用 64 位(8 字节),其通用布局如下:

位域 宽度 (bit) 描述
[63:48] 16 物理地址高位(PA[47:32] 或 PA[35:32],取决于配置)
[47:12] 36 物理地址低位(PA[35:0] 或 PA[31:0]),页内偏移对齐
[11:10] 2 访问权限位(AP[2:1])
[9] 1 可共享位(SH)
[8:6] 3 内存属性索引(AttrIndx[2:0])
[5] 1 非安全位(NS)
[4] 1 访问标志位(AF)
[3:2] 2 提示位(Hint),如连续页表(Contiguous)
[1:0] 2 描述符类型(Type):00=无效,01=Table,10=Block/Page,11=保留
关键点:描述符的最低两位 [1:0] 决定了该条目的类型。硬件通过检查这两个位来区分当前级是继续查表(Table)还是直接映射(Block/Page)。

3.2 页表项类型:Table / Block / Page

ARMv8-A 页表项分为三种核心类型,分别对应不同的页表层级和映射粒度:

  • Table 描述符(类型 01):指向下一级页表的基地址。仅在非末级页表中出现。
  • Block 描述符(类型 10):直接映射一个连续的大内存块(如 2MB、1GB)。仅在 L1/L2 级页表中出现。
  • Page 描述符(类型 10):映射一个标准 4KB 页。仅在 L3(末级)页表中出现。
  • Invalid 描述符(类型 00):表示该条目未使用,访问将触发缺页异常。
注意:Block 和 Page 描述符在二进制编码上都是 10,硬件通过页表层级(L0/L1/L2/L3)来区分它们。L0/L1/L2 中的 10 视为 Block,L3 中的 10 视为 Page。

3.3 描述符类型与层级关系 SVG 图

下图展示了 4 级页表中描述符类型与层级之间的对应关系:

ARMv8-A 页表描述符类型与层级关系 页表描述符类型与层级关系 L0 页表 Table 描述符 指向 L1 基地址 L1 页表 Table / Block 1GB Block 或指向 L2 L2 页表 Table / Block 2MB Block 或指向 L3 L3 Page 4KB 页 映射粒度说明 • L1 Block:1GB 映射(仅当 VA 范围 ≥ 1GB 时可用) • L2 Block:2MB 映射(适合大块连续内存,如内核线性映射) • L3 Page:4KB 映射(标准页粒度,支持按页换入换出) 描述符类型编码([1:0] 位) • 00:Invalid —— 未映射,访问触发 Translation Fault • 01:Table —— 指向下一级页表,仅在非末级使用 • 10:Block/Page —— 最终映射条目,L0/L1/L2 为 Block,L3 为 Page

3.4 关键属性位详解

描述符中的属性位控制着内存的访问行为、缓存策略和安全隔离。以下是核心属性位的详细说明:

属性位 位域 功能描述 典型配置
Type [1:0] 描述符类型:Invalid / Table / Block-Page 01(Table)或 10(Block/Page)
AF [4] 访问标志位(Access Flag)。必须置 1,否则访问时触发 Access Flag 异常 1(已访问)
AP[2:1] [11:10] 数据访问权限:EL0/EL1 读写控制 00:EL0 无访问,EL1 读写;11:EL0/EL1 读写
AttrIndx [8:6] 内存属性索引,指向 MAIR 寄存器中的属性配置 000:Normal 内存;001:Device 内存
SH [9] 可共享性(Shareability):Non-shareable / Inner Shareable / Outer Shareable 11:Outer Shareable(多核共享)
NS [5] 非安全位(Non-Secure)。在安全世界中标记页表是否属于非安全空间 0:安全;1:非安全
Contiguous [3] 连续页表提示位。置 1 表示相邻 16 个条目构成连续映射,可合并为单 TLB 条目 0:非连续;1:连续(需 16 个连续条目同时置位)
PXN [53] 特权执行不可行(Privileged Execute Never)。禁止 EL1 执行该页代码 1:禁止特权执行
UXN [54] 用户执行不可行(User Execute Never)。禁止 EL0 执行该页代码 1:禁止用户执行
常见错误:忘记设置 AF 位([4]=1)是页表配置中最常见的错误之一。如果 AF 为 0,MMU 在第一次访问时会触发 Access Flag 异常,导致内核崩溃或性能下降(软件需手动置位并重试)。

3.5 属性位组合与内存类型 SVG 图

下图展示了 AttrIndx、SH 和 AP 位如何共同决定最终的内存访问行为:

属性位组合与内存类型决策流程 属性位组合与内存类型决策流程 描述符属性位 AttrIndx[2:0] + SH[1:0] + AP[2:1] MAIR 寄存器查询 AttrIndx → 内存属性编码 Normal 内存 可缓存、可合并 Device 内存 不可缓存、严格顺序 可共享性 (SH) 00: Non-shareable 10: Inner Shareable / 11: Outer Shareable 权限控制 (AP + PXN/UXN)

3.6 连续页表(Contiguous Hint)

ARMv8-A 支持连续页表提示(Contiguous Bit),允许将相邻的 16 个页表条目合并为单个 TLB 条目,从而减少 TLB 压力。该特性对性能敏感的大块内存映射(如内核线性映射)尤为重要。

  • 条件:16 个连续描述符必须同时置位 Contiguous 位,且映射的物理地址连续、属性完全一致。
  • 效果:TLB 只需缓存 1 个条目即可覆盖 16 个页(4KB 页 → 64KB 范围;2MB Block → 32MB 范围)。
  • 限制:连续页表不能跨页表边界;软件必须保证 16 个条目的物理地址和属性完全一致。
性能收益:在 Linux 内核中,连续页表常用于 vmalloc 区域和线性映射区域。实测表明,启用连续页表可减少 TLB 缺失率 30%~50%,对数据库和 HPC 负载提升显著。

3.7 页表描述符配置示例

以下是一个 L2 Block 描述符的配置示例,映射 2MB 的 Normal 内存,可共享,EL0/EL1 可读写:

// L2 Block 描述符配置(64 位)
// 物理地址基址:0x80000000(假设)
// 属性:Normal 内存,Outer Shareable,EL0/EL1 读写,AF=1
uint64_t l2_block_desc = 0x0000008000000000ULL  // PA[47:12] = 0x80000000 >> 12
                        | (0x3ULL << 10)       // AP[2:1] = 11 (EL0/EL1 读写)
                        | (0x3ULL << 9)        // SH = 11 (Outer Shareable)
                        | (0x0ULL << 6)        // AttrIndx = 000 (Normal)
                        | (0x1ULL << 4)        // AF = 1
                        | (0x0ULL << 3)        // Contiguous = 0
                        | (0x2ULL << 0);       // Type = 10 (Block)
调试建议:在 QEMU 或真实硬件上调试页表时,建议先打印描述符的十六进制值,然后逐位解析 Type、AF、AP 和 AttrIndx,确保与预期一致。使用 readelf -l 或内核的 dump_page 工具辅助验证。

3.8 本章小结

  • ARMv8-A 页表描述符为 64 位,最低两位 [1:0] 决定类型:Invalid、Table、Block/Page。
  • Table 描述符指向下一级页表;Block 描述符用于大块映射(1GB/2MB);Page 描述符用于 4KB 标准页。
  • 关键属性位包括 AF(访问标志)、AP(权限)、AttrIndx(内存类型索引)、SH(可共享性)和 Contiguous(连续提示)。
  • 连续页表可合并 16 个条目为单 TLB 条目,是提升 TLB 覆盖范围的重要手段。
  • 属性位的组合最终通过 MAIR 寄存器、权限检查和可共享性逻辑决定内存访问行为。