ARMv8-A MMU 架构:页表层级、转换粒度与地址空间划分

ARMv8-A 架构的 MMU(Memory Management Unit)是整个内存映射与虚拟化机制的核心。理解其页表层级、转换粒度以及地址空间划分,是进行 MMU 配置与 DMA 缓冲区验证的理论基础。本节将深入剖析这三项关键参数,并通过图表与表格进行对比说明。

2.1 页表层级结构:4级 vs 3级

ARMv8-A 支持基于页表的虚拟地址到物理地址转换。根据配置,页表层级可以是 4 级或 3 级。层级越多,页表树的深度越大,但能支持更大的地址空间和更细粒度的内存管理。

  • 4级页表(4-Level Page Table): 支持 48 位虚拟地址空间(VA),是默认且最常用的配置。层级包括:PGD(Page Global Directory)、PUD(Page Upper Directory)、PMD(Page Middle Directory)、PTE(Page Table Entry)。
  • 3级页表(3-Level Page Table): 支持 39 位虚拟地址空间,层级包括:PGD、PMD、PTE。适用于地址空间需求较小的场景,可减少页表遍历开销。
关键点: 在 4 级页表配置下,如果使用 64KB 转换粒度,PUD 层级会被跳过,实际退化为 3 级页表。这是 ARM 架构的硬件优化特性。

下表对比了两种页表层级的关键差异:

特性 4级页表 3级页表
虚拟地址宽度 48 位 39 位
最大虚拟地址空间 256 TB 512 GB
页表层级 PGD → PUD → PMD → PTE PGD → PMD → PTE
典型应用场景 通用 Linux 内核、大型系统 嵌入式系统、地址空间受限场景

下图展示了 4 级页表的遍历流程:

ARMv8-A 4级页表遍历流程 4级页表遍历流程(48位VA) TTBR0_EL1 PGD PUD PMD PTE 说明:TTBR0_EL1 指向 PGD 基地址,MMU 硬件自动遍历各级页表, 最终从 PTE 中提取物理地址(PA)和内存属性。

2.2 转换粒度:4K / 16K / 64K

转换粒度(Translation Granule)决定了页表中最底层页(Page)的大小。ARMv8-A 支持三种粒度:4KB、16KB 和 64KB。粒度选择直接影响页表大小、TLB 覆盖范围和内存碎片化程度。

  • 4KB 粒度: 最细粒度,页表层级最多(4级),内存利用率高,但页表占用内存较大。适用于通用操作系统。
  • 16KB 粒度: 折中方案,页表层级减少(3级),TLB 覆盖范围增大。适用于需要平衡性能与内存占用的场景。
  • 64KB 粒度: 最粗粒度,页表层级最少(3级或2级),TLB 覆盖范围最大,但内存碎片化风险增加。适用于高性能计算或大页需求场景。
注意: 粒度选择必须在系统启动时通过 TCR(Translation Control Register)配置,且不能动态更改。DMA 缓冲区分配时,必须确保缓冲区大小与粒度对齐,否则可能导致映射失败或性能下降。

下表对比了三种粒度的关键参数:

参数 4KB 粒度 16KB 粒度 64KB 粒度
页大小 4 KB 16 KB 64 KB
页表层级(48位VA) 4 级(PGD/PUD/PMD/PTE) 3 级(PGD/PMD/PTE) 3 级(PGD/PMD/PTE)
单页表项覆盖范围 4 KB 16 KB 64 KB
TLB 覆盖范围(相同条目数) 小 中 大
页表内存占用 高 中 低
典型应用 Linux 内核默认 Android / 嵌入式 高性能计算 / 服务器

下图展示了不同粒度下的页表层级差异:

不同粒度下的页表层级对比 不同粒度下的页表层级对比 4KB 粒度:4级页表 PGD → PUD → PMD → PTE 16KB 粒度:3级页表 PGD → PMD → PTE 64KB 粒度:3级页表 PGD → PMD → PTE 说明:4KB 粒度需要 4 级页表来覆盖 48 位虚拟地址空间; 16KB 和 64KB 粒度由于每级页表覆盖范围更大,仅需 3 级即可。 64KB 粒度在特定配置下可进一步降为 2 级页表。

2.3 地址空间划分:内核空间与用户空间

ARMv8-A 支持两个独立的虚拟地址空间:用户空间(User Space) 和 内核空间(Kernel Space)。通过 TTBR0_EL1 和 TTBR1_EL1 两个页表基地址寄存器来区分。这种划分是操作系统内存保护的基础。

  • 用户空间(TTBR0_EL1): 低地址区域,每个进程拥有独立的页表,进程间隔离。地址范围取决于 VA 宽度(如 48 位时为 0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF)。
  • 内核空间(TTBR1_EL1): 高地址区域,所有进程共享同一个内核页表,用于内核代码、数据结构和设备映射。地址范围(48 位时为 0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF)。
实践要点: 在 DMA 缓冲区验证中,驱动程序通常将缓冲区映射到内核空间(通过 dma_alloc_coherent 或 ioremap),并可选地映射到用户空间(通过 mmap)。理解地址空间划分有助于正确配置页表属性(如缓存策略、权限位)。

下表总结了用户空间与内核空间的关键区别:

特性 用户空间 内核空间
页表基地址寄存器 TTBR0_EL1 TTBR1_EL1
地址范围(48位VA) 0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF 0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF
页表独立性 每个进程独立 所有进程共享
访问权限 EL0(非特权) EL1(特权)
典型内容 应用程序代码、堆、栈 内核代码、设备驱动、页表自身

下图展示了 ARMv8-A 的地址空间划分:

ARMv8-A 地址空间划分 ARMv8-A 地址空间划分(48位VA) 用户空间(TTBR0_EL1) 0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF 内核空间(TTBR1_EL1) 0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF 说明:用户空间和内核空间通过 TTBR0/TTBR1 寄存器切换, MMU 根据虚拟地址的最高位(bit 47)自动选择对应的页表。

2.4 页表配置与 DMA 缓冲区验证的关联

在 DMA 缓冲区验证中,页表配置直接影响缓冲区的映射属性和访问性能。以下是几个关键关联点:

  • 缓存属性: 页表项中的 AttrIndx 字段控制内存类型(Normal、Device、Strongly Ordered)。DMA 缓冲区通常配置为 Normal Non-Cacheable 或 Device 类型,以避免缓存一致性问题。
  • 权限位: AP(Access Permission)和 PXN/UXN(Privileged/User Execute Never)位控制访问权限。DMA 缓冲区通常需要同时具有读写权限。
  • 粒度对齐: 缓冲区起始地址和大小必须与转换粒度对齐。例如,使用 4KB 粒度时,缓冲区地址必须 4KB 对齐,否则 MMU 无法正确映射。
验证技巧: 在驱动测试中,可以通过读取 /proc/self/pagemap 或使用 ioctl 查询页表项,验证 DMA 缓冲区的物理地址、缓存属性和权限位是否与预期一致。

下表总结了 DMA 缓冲区验证中常见的页表配置项:

配置项 页表字段 推荐值(DMA缓冲区) 说明
内存类型 AttrIndx[2:0] Normal Non-Cacheable (0b010) 避免 CPU 缓存与 DMA 数据不一致
访问权限 AP[2:1] EL0/EL1 读写 (0b00) 允许内核和用户空间访问
执行权限 PXN, UXN 禁止执行 (1) 防止缓冲区被用于代码执行
共享属性 SH[1:0] Inner Shareable (0b11) 确保多核一致性

通过深入理解 ARMv8-A MMU 的页表层级、转换粒度和地址空间划分,开发者能够更精确地配置页表,从而为 DMA 缓冲区验证提供可靠的内存映射基础。下一节将介绍 MMU 初始化与页表构建的具体实现。