4. ARMv7-A L2页表项格式:二级页表描述符结构

在ARMv7-A的经典两级页表架构中,L2页表(二级页表)负责将L1页表项指向的1MB节段进一步细分为更小的内存粒度。L2页表包含4种描述符类型,分别对应不同的页面大小和属性编码。本章将详细解析L2描述符的通用结构,以及大页、小页、极小页三种数据页描述符的差异。

核心概念: L2页表描述符的格式由TTBCR(Translation Table Base Control Register)和SCTLR(System Control Register)中的配置位共同决定。在经典短描述符格式下,L2描述符始终为32位(4字节)。

4.1 L2页表描述符通用结构

每个L2描述符占用4字节,其最高2位(bit[1:0])用于区分描述符类型。ARMv7-A定义了以下四种类型:

bit[1:0]值 描述符类型 页面大小 说明
0b00 无效描述符(Fault) — 访问该页表项将触发Translation Fault
0b01 大页描述符(Large Page) 64 KB 需L1节描述符配合,支持子页权限
0b10 极小页描述符(Tiny Page) 1 KB 仅在SCTLR.TRE=1时可用,兼容性受限
0b11 小页描述符(Small Page) 4 KB 最常用的L2页表项,支持子页权限
兼容性注意: 极小页(Tiny Page)仅在使能TEX remap(SCTLR.TRE=1)时有效。在大多数现代ARMv7-A实现中,TRE通常为0,此时0b10被保留为Fault,极小页不可用。建议新设计优先使用小页(4KB)以获得最佳兼容性。
L2页表描述符类型选择流程 读取L2描述符[1:0] 00 → Fault(无效) 01 → 大页(64KB) 10 → 极小页(1KB) 11 → 小页(4KB) 需SCTLR.TRE=1 否则视为Fault

4.2 小页(Small Page)描述符详解

小页(4KB)是ARMv7-A中最常用的L2页表项。其描述符格式如下:

位域 宽度 功能描述
[31:12] 20 bits 物理页帧号(PFN):4KB对齐的物理地址高20位
[11:9] 3 bits AP[2:0]:访问权限位(与SCTLR.AFE配合)
[8:6] 3 bits TEX[2:0]:内存类型与缓存属性编码
[5] 1 bit APX:访问权限扩展位
[4] 1 bit S:可共享(Shareable)位
[3] 1 bit nG:非全局位(用于ASID匹配)
[2] 1 bit XN:不可执行位(Execute Never)
[1:0] 2 bits 类型标识:固定为0b11
子页权限(Subpage Permissions): 小页和大页支持将页面进一步划分为4个子页(每个子页1KB或16KB)。子页权限由L2描述符中的AP[2:0]和APX位联合编码,通过SCTLR.SPD(Subpage Permissions Disable)位控制启用。当SPD=0时,子页权限生效,允许对同一页内不同区域设置不同的读/写权限。
小页(Small Page)描述符位布局(32位) PFN [31:12] — 物理页帧号(20位) AP[2:0] TEX APX S nG XN SBZ 类型=11 bit 31 bit 12 bit 9 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 SBZ = Should Be Zero(必须为0) 类型=0b11 标识小页描述符

4.3 大页(Large Page)描述符

大页大小为64KB,用于减少TLB压力并提高大块连续内存的映射效率。其描述符格式与小页类似,但物理地址对齐要求不同:

  • PFN位域: [31:16]共16位,物理地址必须64KB对齐(低16位为0)。
  • 子页划分: 64KB大页被划分为4个16KB子页,每个子页拥有独立的访问权限(AP[2:0] + APX)。
  • 类型标识: bit[1:0] = 0b01。
  • 属性位: TEX、S、nG、XN等位域位置与小页相同。
性能权衡: 大页(64KB)在TLB覆盖范围上优于小页(4KB),但内存碎片风险更高。在嵌入式系统中,大页常用于帧缓冲(Frame Buffer)或大块DMA缓冲区映射。虚拟化场景中,大页可减少Stage-2页表的遍历开销。

4.4 极小页(Tiny Page)描述符

极小页大小为1KB,是ARMv7-A中最小的页面粒度。其描述符特点如下:

特性 说明
类型标识 bit[1:0] = 0b10
PFN位域 [31:10]共22位,物理地址1KB对齐
可用条件 必须使能TEX remap(SCTLR.TRE=1)
子页支持 不支持子页权限(SPD位无效)
属性位 AP、TEX、S、nG、XN位域位置与小页一致
兼容性 ARMv7-A可选特性,Cortex-A系列多数实现不支持
弃用建议: 极小页(1KB)在ARMv7-A中属于可选特性,且ARMv8-A AArch64已完全移除该粒度。为了向前兼容和软件可移植性,强烈建议避免使用极小页。如果确实需要细粒度映射,优先考虑小页(4KB)配合子页权限。

4.5 三种数据页描述符对比总结

对比维度 大页(Large Page) 小页(Small Page) 极小页(Tiny Page)
页面大小 64 KB 4 KB 1 KB
类型标识 bit[1:0] 0b01 0b11 0b10
PFN位宽 16 bits [31:16] 20 bits [31:12] 22 bits [31:10]
子页数量 4(每个16KB) 4(每个1KB) 无
子页权限控制 支持 支持 不支持
使能条件 始终可用 始终可用 需SCTLR.TRE=1
TLB覆盖范围 高(64KB/项) 中(4KB/项) 低(1KB/项)
典型用途 帧缓冲、大块DMA 通用内存映射 极少使用
三种L2数据页描述符粒度对比 大页(Large Page) 64 KB 4个子页 × 16KB 小页(Small Page) 4 KB 4个子页 × 1KB 极小页(Tiny Page) 1 KB 无子页支持 相对大小比例(1KB : 4KB : 64KB) 子页权限:大页和小页支持将页面划分为4个子区域,每个子区域可独立设置读/写权限 极小页不支持子页权限,且需要SCTLR.TRE=1才能使用

4.6 L2页表项编程示例

以下示例展示如何构造一个小页描述符,映射虚拟地址到物理地址0x80001000,并设置可读可写、不可执行、普通内存属性:

/* 构造小页描述符示例 */
uint32_t l2_entry = 0;

/* 物理页帧号:物理地址 0x80001000 右移12位 */
uint32_t pfn = (0x80001000 >> 12);  /* 结果: 0x80001 */

/* 填充位域 */
l2_entry |= (pfn << 12);            /* bit[31:12] = PFN */
l2_entry |= (0x3 << 9);             /* AP[2:0] = 0b011: 全权限(读/写) */
l2_entry |= (0x1 << 6);             /* TEX[2:0] = 0b001: 普通内存,外写回内写通 */
l2_entry |= (0x0 << 5);             /* APX = 0 */
l2_entry |= (0x1 << 4);             /* S = 1: 可共享 */
l2_entry |= (0x0 << 3);             /* nG = 0: 全局映射 */
l2_entry |= (0x1 << 2);             /* XN = 1: 不可执行 */
l2_entry |= 0x3;                     /* bit[1:0] = 0b11: 小页描述符 */

/* 写入L2页表基址偏移处 */
*(volatile uint32_t *)(l2_table_base + index) = l2_entry;
调试检查: 在写入L2页表项后,建议使用DSB(Data Synchronization Barrier)和ISB(Instruction Synchronization Barrier)指令确保页表更新对后续指令和观察点可见。在SMP系统中,还需执行TLB失效广播操作(如TLBIALL)。