3. 页表描述符详解:Table Descriptor 与 Page Descriptor 的结构,以及属性位(AF, AP, XN, PXN)的含义

在 ARM64 的页表体系中,描述符(Descriptor)是页表项(PTE)的核心数据结构。根据页表层级和映射粒度的不同,描述符分为 Table Descriptor(表描述符)和 Page/Block Descriptor(页/块描述符)。理解这两类描述符的位域布局,是正确配置页表和初始化 MMU 的前提。

3.1 描述符类型与层级关系

ARM64 页表支持 4 级(TCR_EL1.TxSZ 配置)或 3 级查找。每一级页表项可能指向下一级页表(Table Descriptor),也可能直接指向物理内存块(Block Descriptor)或 4KB 页(Page Descriptor)。

关键概念: 描述符的最低 2 位(bit[1:0])用于区分类型:
  • 0b00:无效描述符(Fault)
  • 0b01:Table Descriptor(指向下一级页表)
  • 0b10:Block Descriptor(映射大块内存,如 2MB/1GB)
  • 0b11:Page Descriptor(映射 4KB 页)
ARM64 描述符类型与页表层级关系 描述符类型与页表层级关系 L0 页表 L1 页表 L2 页表 L3 页表 Table Descriptor Block Descriptor Page Descriptor 描述符类型说明: • Table Descriptor (bit[1:0]=01):指向下一级页表的基地址,用于多级页表遍历。 • Block Descriptor (bit[1:0]=10):在 L0/L1/L2 级使用,映射 1GB/2MB/4KB 块。 • Page Descriptor (bit[1:0]=11):仅在 L3 级使用,映射 4KB 页。

3.2 Table Descriptor 结构

Table Descriptor 用于非最后一级页表(L0/L1/L2),其核心作用是提供下一级页表的物理基地址。ARMv8-A 架构中,Table Descriptor 的位域布局如下:

位域 宽度 描述
[63:48] 16 下一级页表的物理地址高位(PA[47:32]),具体位数由 TCR_EL1.TxSZ 决定
[47:12] 36 下一级页表的物理地址低位(PA[31:12]),与高位拼接形成 4KB 对齐的基地址
[11:2] 10 保留位(RES0),必须为 0
[1] 1 类型位:1 表示 Table Descriptor
[0] 1 有效位:1 表示有效
实践提示: 在创建多级页表时,Table Descriptor 的下一级页表地址必须 4KB 对齐(即低 12 位为 0)。如果 TCR_EL1 配置了 48 位物理地址空间,则使用位 [47:12];若配置 36 位,则使用位 [35:12]。

3.3 Page/Block Descriptor 结构

Page Descriptor(L3 级)和 Block Descriptor(L0/L1/L2 级)共享相同的属性位布局,区别仅在于映射粒度。以下是标准 4KB 页描述符的位域结构:

位域 宽度 描述
[63:48] 16 物理地址高位(PA[47:32]),与低位拼接
[47:12] 36 物理地址低位(PA[31:12]),4KB 页对齐
[11] 1 nG:非全局位(Non-Global),TLB 条目是否全局
[10] 1 AF:访问标志位(Access Flag)
[9:8] 2 SH:可共享性属性(Shareability)
[7:6] 2 AP:访问权限位(Access Permission)
[5] 1 NS:安全位(Non-Secure)
[4] 1 AttrIndx[0]:属性索引低位(与 MAIR 配合)
[3] 1 AttrIndx[1]:属性索引高位
[2] 1 AttrIndx[2]:属性索引最高位(共 3 位,索引 8 个 MAIR 槽位)
[1] 1 类型位:1 表示 Page/Block Descriptor
[0] 1 有效位:1 表示有效
Page Descriptor 位域布局 Page Descriptor 位域布局(4KB 页) PA[47:32] PA[31:12] nG AF SH AP NS Attr T V 63:48 47:12 11 10 9:8 7:6 5 4:2 1 0 关键属性位说明: • AF (bit 10):访问标志位,MMU 在首次访问时自动置 1,用于页表遍历优化。 • AP (bit 7:6):访问权限位,控制读/写权限和异常等级访问限制。 • XN (bit 54):不可执行位,禁止在该页上执行指令。 • PXN (bit 53):特权不可执行位,禁止在 EL1/EL2/EL3 下执行该页指令。

3.4 核心属性位详解

3.4.1 AF(Access Flag,访问标志位)

AF 位位于描述符的 bit 10。当 MMU 启用且 AF 为 0 时,首次访问该页会触发 Access Flag Fault(访问标志故障)。操作系统通常利用此机制实现页表遍历的延迟优化:

  • 初始状态: AF = 0,表示该页尚未被访问。
  • 硬件行为: 当 MMU 成功完成地址翻译且 AF=0 时,硬件会自动将 AF 置 1(前提是未触发其他故障)。
  • 软件用途: 操作系统在页表创建时可将 AF 置 1 以避免初次访问故障,或利用 AF 实现页面置换算法(如近似 LRU)。
注意: 如果 TCR_EL1 的 HA(Hardware Access Flag)和 HD(Hardware Dirty Flag)位被使能,MMU 硬件会自动管理 AF 和 DBM(Dirty Bit Modifier)。否则,AF 必须由软件在页表初始化时显式置 1,否则第一次访问会产生故障。

3.4.2 AP(Access Permission,访问权限位)

AP 位位于描述符的 bit 7:6,共 2 位,用于控制页面的读写权限以及异常等级(Exception Level)的访问限制。AP 位的编码与权限映射如下:

AP[2:1] EL1/EL2/EL3 权限 EL0 权限 典型用途
0b00 读/写 无访问 内核私有数据
0b01 读/写 读/写 用户共享数据
0b10 只读 无访问 内核只读数据
0b11 只读 只读 用户只读代码/数据
权限组合技巧: 在 MMU 初始化阶段,通常将内核空间的页表项设置为 AP=0b00(EL1 读写,EL0 无访问),用户空间设置为 AP=0b01(EL0 读写)或 AP=0b11(EL0 只读)。这样可以有效隔离内核与用户空间。

3.4.3 XN(Execute Never,不可执行位)

XN 位位于描述符的 bit 54(在 64 位描述符的高位区域)。当 XN=1 时,禁止在该页上取指执行。这是 ARM64 实现 NX(No-Execute) 内存保护机制的核心位:

  • XN=0: 允许在该页上执行指令。
  • XN=1: 禁止在该页上执行指令,任何取指操作都会触发 Instruction Abort。

典型应用场景:

  • 数据页(堆、栈、全局变量)必须设置 XN=1,防止代码注入攻击。
  • 代码页(.text 段)设置 XN=0,允许执行。

3.4.4 PXN(Privileged Execute Never,特权不可执行位)

PXN 位位于描述符的 bit 53。与 XN 类似,但 PXN 仅限制特权级(EL1/EL2/EL3)的执行权限:

  • PXN=0: 允许特权级在该页上执行指令。
  • PXN=1: 禁止特权级在该页上执行指令,但 EL0 用户态仍可执行(如果 XN=0)。

PXN 提供更细粒度的权限控制,常用于:

  • 用户态代码页:设置 PXN=1,防止内核意外跳转到用户空间代码执行(Kernel 到 Userspace 的防护)。
  • 内核某些敏感数据页:设置 PXN=1 且 XN=1,双重保护。
AF/AP/XN/PXN 属性位权限控制 AF/AP/XN/PXN 属性位权限控制 页表描述符 AF (bit 10) 访问标志,硬件自动置位 AP (bit 7:6) 读/写权限控制 XN (bit 54) 不可执行(所有异常等级) PXN (bit 53) 特权不可执行

3.5 属性位组合示例

在实际的 MMU 初始化代码中,页表描述符的属性位通常通过宏定义或位操作组合而成。以下是一个典型的页表项属性配置示例:

/* 页表描述符属性位宏定义 */
#define PAGE_DEFAULT_ATTRS  ( \
    (1UL << 10) |  /* AF = 1,访问标志有效 */ \
    (0UL << 7)  |  /* AP[2:1] = 00,EL1 读写,EL0 无访问 */ \
    (1UL << 54) |  /* XN = 1,不可执行 */ \
    (1UL << 53) |  /* PXN = 1,特权不可执行 */ \
    (0UL << 4)  |  /* AttrIndx = 0,指向 MAIR 第 0 槽 */ \
    (3UL << 0)     /* 类型位 = 0b11,Page Descriptor,有效位 = 1 */ \
)

/* 内核代码段属性:可执行,特权可执行 */
#define PAGE_KERNEL_CODE_ATTRS  ( \
    (1UL << 10) |  /* AF = 1 */ \
    (0UL << 7)  |  /* AP = 00,EL1 读写 */ \
    (0UL << 54) |  /* XN = 0,允许执行 */ \
    (0UL << 53) |  /* PXN = 0,允许特权执行 */ \
    (2UL << 2)  |  /* AttrIndx = 2,Normal 内存属性 */ \
    (3UL << 0)     /* Page Descriptor,有效 */ \
)
关键总结:
  • Table Descriptor 用于非最后一级页表,提供下一级页表基地址;Page/Block Descriptor 用于最后一级或块映射,包含物理地址和属性位。
  • AF 位控制访问标志,硬件可自动置位;AP 位控制读写权限和异常等级隔离。
  • XN 位禁止所有异常等级执行,PXN 位仅禁止特权级执行,两者结合可实现完整的 W^X(Write XOR Execute)保护。
  • 在 MMU 初始化阶段,必须正确设置这些属性位,否则会导致权限故障或安全漏洞。