2. ARMv7/v8 MMU 架构基础:页表层级结构与转换粒度

在 QNX 实时操作系统中,MMU(Memory Management Unit)是虚拟地址到物理地址转换的核心硬件单元。ARMv7(32位)和 ARMv8(64位)架构的 MMU 采用多级页表(Multi-Level Page Table)机制,通过层级化的页表结构实现高效地址翻译与权限控制。本章深入解析 TTB、L1/L2/L3 页表层级、描述符格式以及 4K/16K/64K 转换粒度,为后续 QNX 页表配置与调试奠定基础。

2.1 页表层级结构总览

ARM MMU 使用 翻译表基地址寄存器(TTBR) 指向第一级页表的物理基地址。页表层级从 L1 到 L3,每一级页表包含若干描述符,指向下一级页表或直接映射到物理内存块。层级深度与页面粒度相关,典型配置为 4K 粒度时使用 L1/L2/L3 三级页表。

关键概念: TTB(Translation Table Base)存储于 CP15 寄存器(ARMv7)或系统寄存器 TTBR0_EL1/TTBR1_EL1(ARMv8),是 MMU 遍历页表的入口点。
ARMv7/v8 页表层级结构图 ARMv7/v8 页表层级结构(4K 粒度示例) TTBR0/TTBR1 L1 页表(4096 条目) L2 页表(4096 条目) L3 页表(4096 条目) 物理页(4K) 说明: 每级页表包含 4096 个条目 每个条目 4 字节(ARMv7) 或 8 字节(ARMv8)

2.2 页表描述符格式

每个页表条目(Page Table Entry, PTE)包含物理地址高位、访问权限、内存属性、域标识等控制位。ARMv7 与 ARMv8 的描述符格式存在差异,但核心字段功能一致。

2.2.1 ARMv7 短描述符格式(4 字节)

位域 宽度(位) 功能描述
[31:20] 12 物理地址高位(PA[31:20]),与页内偏移拼接形成 32 位物理地址
[19:12] 8 域标识(Domain),用于权限检查与域访问控制
[11:10] 2 访问权限位(AP[2:1]),控制用户/特权读/写
[9] 1 可共享位(Shareable),多核一致性控制
[8:6] 3 内存属性(TEX[2:0]),缓存策略与内存类型
[5] 1 非安全位(NS),安全世界与非安全世界隔离
[4] 1 可执行位(XN),禁止执行标记
[3:2] 2 页表类型(L1: 0b11 页表, 0b10 段; L2: 0b01 大页, 0b11 小页)
[1:0] 2 条目类型(0b10 表描述符, 0b01 块描述符, 0b11 页描述符)
调试提示: 在 QNX 系统崩溃转储中,检查 L1/L2 描述符的 [1:0] 位可快速判断页表遍历是否中断。若该字段为 0b00,表示无效条目,MMU 将触发 Translation Fault。

2.2.2 ARMv8 长描述符格式(8 字节)

ARMv8 使用 64 位描述符,支持 48 位物理地址空间。L1/L2 描述符为 表描述符 或 块描述符,L3 描述符为 页描述符。

位域 宽度(位) 功能描述
[63:48] 16 物理地址高位(PA[47:32]),扩展物理地址支持
[47:12] 36 物理地址中低位(PA[31:12]),与页内偏移拼接
[11:10] 2 访问权限(AP[2:1]),与 ARMv7 兼容
[9:8] 2 内存属性索引(AttrIndx[1:0]),指向 MAIR 寄存器配置
[7] 1 非安全位(NS)
[6] 1 可执行位(XN)
[5] 1 可执行位(PXN),特权级禁止执行
[4:2] 3 保留位(RES0),必须为 0
[1] 1 非安全访问位(nG),ASID 匹配控制
[0] 1 有效位(Valid),0 表示无效条目
ARMv7 与 ARMv8 描述符格式对比 ARMv7 短描述符(4 字节)与 ARMv8 长描述符(8 字节)对比 ARMv7: 位 [31:20] PA 高位 [19:12] Domain [11:10] AP [9] S [8:6] TEX [5] NS [4] XN [3:2] Type [1:0] Entry ARMv8: 位 [63:48] PA 高位 [47:12] PA 中低位 [11:10] AP [9:8] Attr [7] NS [6] XN [5] PXN [4:2] RES0 [1] nG [0] V 关键差异: ARMv8 描述符长度翻倍,支持 48 位物理地址;ARMv7 使用 Domain 字段,ARMv8 改用 MAIR + AttrIndx 配置内存属性。 ARMv8 增加 PXN 位实现特权级不可执行,增强内核防护能力。

2.3 转换粒度与页表层级关系

ARMv7/v8 支持三种页面粒度:4K、16K、64K。粒度决定了页表层级深度和每级页表的索引位数。QNX 默认使用 4K 粒度,兼顾灵活性与内存利用率。

粒度 页内偏移位数 L1 索引位数 L2 索引位数 L3 索引位数 页表层级数 典型应用
4K 12 12 12 8 3 QNX 标准配置,细粒度内存保护
16K 14 11 11 8 3 减少 TLB 缺失,适合大内存系统
64K 16 10 10 8 3 硬件加速场景,减少页表占用
工程注意: 在 QNX 系统中切换页面粒度需要重新初始化 MMU 并刷新 TLB。4K 粒度下 L3 页表条目数最多(256 个),页表总大小约为 4 MB(L1: 16KB + L2: 16KB + L3: 每进程 1MB)。16K/64K 粒度可减少页表层级深度,但可能造成内部碎片。

2.4 地址翻译流程示例(4K 粒度)

以 ARMv8 4K 粒度为例,虚拟地址 VA[47:0] 被拆分为:

  • VA[47:39]:9 位 L1 索引(512 条目)
  • VA[38:30]:9 位 L2 索引(512 条目)
  • VA[29:21]:9 位 L3 索引(512 条目)
  • VA[20:12]:9 位 L3 索引(ARMv8 4K 实际使用 9 位 L3 索引,共 512 条目)
  • VA[11:0]:12 位页内偏移

MMU 遍历流程:

  1. 从 TTBR0_EL1 读取 L1 页表基地址。
  2. 使用 VA[47:39] 作为索引,在 L1 页表中获取表描述符,指向 L2 页表。
  3. 使用 VA[38:30] 作为索引,在 L2 页表中获取表描述符,指向 L3 页表。
  4. 使用 VA[29:21] 作为索引,在 L3 页表中获取页描述符,得到物理页基地址。
  5. 物理页基地址 + VA[11:0] 偏移 = 最终物理地址。
ARMv8 4K 粒度地址翻译流程 ARMv8 4K 粒度地址翻译流程 VA[47:39] L1 索引 VA[38:30] L2 索引 VA[29:21] L3 索引 VA[20:12] L3 索引(扩展) VA[11:0] 页内偏移 TTBR0_EL1 L1 页表 L2 页表 L3 页表 物理地址 物理页基地址 + 页内偏移 每级页表使用虚拟地址 对应位段作为索引

2.5 QNX 中的页表配置实践

QNX 系统启动时,内核通过 mmu_init() 函数初始化页表。关键配置参数包括:

  • 页面粒度:通过内核构建选项 ARM_PAGE_SIZE 设置,可选 4K/16K/64K。
  • TTBR 选择:QNX 使用 TTBR0 映射用户空间,TTBR1 映射内核空间,实现地址空间隔离。
  • 域访问控制:通过 DACR 寄存器(ARMv7)或 MAIR 寄存器(ARMv8)配置内存类型与缓存策略。
调试命令: 在 QNX 中,使用 pidin -p <pid> -v 查看进程页表信息;使用 asinfo 工具转储当前 MMU 配置与页表层级。

2.6 常见页表错误与调试要点

错误类型 MMU 异常 典型原因 调试方法
Translation Fault Data/Instruction Abort 页表条目无效(Valid=0)或未映射 检查 TTBR 地址与 L1/L2/L3 描述符有效位
Permission Fault Prefetch/Data Abort AP 位禁止当前特权级访问 对比访问模式与 AP 字段配置
Domain Fault Data Abort 域访问控制寄存器(DACR)禁止访问 检查 DACR 值与页表 Domain 字段
Alignment Fault Data Abort 访问地址未对齐到粒度边界 检查虚拟地址低 12 位(4K 粒度)
调试陷阱: ARMv8 中 L3 页表条目数可能为 512(9 位索引)或 256(8 位索引),取决于粒度配置。QNX 默认 4K 粒度使用 9 位 L3 索引,共 512 条目。若手动修改页表,务必确认索引位数与页表大小匹配,否则会导致 Translation Fault。