2. MMU核心硬件结构:TLB、页表遍历与PTE格式
内存管理单元(MMU)是CPU内部负责虚拟地址到物理地址转换的硬件模块。其核心由TLB(转译后备缓冲器)、页表遍历器(Page Table Walker)以及页表项(PTE)格式三部分构成。理解这三者的协同机制,是配置MMU和设计DMA缓冲区的基石。
核心要点:TLB是地址转换的“缓存”,页表遍历器是“慢速路径”,PTE是“转换规则”。性能与灵活性在此三者间权衡。
2.1 TLB:地址转换的快速缓存
TLB是一个位于CPU流水线关键路径上的全相联或组相联高速缓存,用于存储最近使用的虚拟地址到物理地址的映射关系。其访问延迟通常为1-2个CPU周期,远低于内存访问。
- 功能:缓存页表项(PTE),避免每次内存访问都去内存查页表。
- 结构:通常分为指令TLB(ITLB)和数据TLB(DTLB),部分架构还包含统一TLB(UTLB)或二级TLB(L2 TLB)。
- 关键指标:条目数(如32/64/512条)、相联度(全相联/4路组相联)、页面大小支持(4KB/2MB/1GB)。
- 失效处理:TLB Miss后,硬件页表遍历器自动填充,或触发软件异常由操作系统处理。
嵌入式实战提示:在实时系统中,TLB Miss会导致不确定的延迟抖动。关键任务代码和DMA缓冲区应尽量使用大页(如2MB)映射,以增加TLB覆盖范围,减少Miss概率。
2.2 页表遍历:硬件自动化的慢速路径
当TLB Miss发生时,硬件页表遍历器(Hardware Page Table Walker)自动接管,根据虚拟地址和页表基址寄存器(如ARM的TTBR0/TTBR1)在内存中查找页表。这个过程对软件透明,但消耗多个内存访问周期。
| 遍历层级 | 页表级别 | 描述 | 典型延迟(周期) |
|---|---|---|---|
| L0 | PGD(页全局目录) | 512GB地址范围映射 | ~4(L1缓存命中) |
| L1 | PUD(页上级目录) | 1GB地址范围映射 | ~4(L1缓存命中) |
| L2 | PMD(页中间目录) | 2MB地址范围映射 | ~4(L1缓存命中) |
| L3 | PTE(页表项) | 4KB物理页帧 | ~4(L1缓存命中) |
性能警告:一次完整的4级页表遍历在最坏情况下(各级页表均不在缓存中)需要访问4次内存,每次约100ns(DDR延迟),总计400ns。在此期间CPU流水线可能停顿数十到数百个周期。对于DMA缓冲区,建议使用块映射(Section Mapping)或大页(Huge Pages)来减少遍历层级。
2.3 页表项(PTE)格式:转换规则的原子单元
页表项是页表中的最小数据单元,通常为8字节(64位架构)。它包含了物理地址的高位(物理页帧号PFN)以及一系列属性位,这些属性位决定了访问权限、缓存策略和内存类型。
2.3.1 典型PTE字段解析(以ARMv8-A为例)
| 位域 | 名称 | 功能描述 | DMA设计影响 |
|---|---|---|---|
| [47:12] | Output Address | 物理页帧号(PFN),指向4KB对齐的物理页 | DMA缓冲区必须物理连续 |
| [11] | nG(非全局) | 0=全局映射(所有进程共享),1=进程私有 | DMA缓冲区建议设为全局 |
| [10] | AF(访问标志) | 0=未访问(触发缺页),1=已访问 | 预置AF=1避免首次访问异常 |
| [7:6] | AttrIndx | 指向MAIR(内存属性间接寄存器)的索引 | 决定DMA缓冲区的缓存策略 |
| [5] | NS(非安全) | 安全世界/非安全世界隔离 | DMA需在非安全世界访问 |
| [4] | AP[2](访问权限) | 与AP[1]组合:读/写/只读/不可访问 | DMA缓冲区需可读可写 |
| [2] | SH(可共享性) | 00=非共享,10=外部共享,11=内部共享 | 多核DMA必须设为共享 |
| [1] | XN(不可执行) | 1=禁止在该页执行指令 | DMA缓冲区应置XN=1 |
| [0] | Valid | 1=有效映射,0=无效(触发缺页) | 映射必须有效 |
关键配置组合:对于DMA缓冲区,典型的PTE属性应为:Valid=1, AF=1, XN=1, AP=读/写, SH=外部共享, AttrIndx指向非缓存(Device-nGnRnE)或写回(Normal Write-Back)的MAIR条目,具体取决于DMA是否需要CPU缓存一致性。
2.3.2 PTE与缓存策略的关联
PTE中的AttrIndx字段指向MAIR寄存器组(通常有8个条目),每个MAIR条目定义了该内存区域的类型(Normal/Device)和属性(缓存策略)。这是MMU配置中与DMA设计最直接相关的部分。
/* Linux内核中设置MAIR的示例(ARM64)*/
#define MAIR_DEVICE_nGnRnE 0x00
#define MAIR_NORMAL_NC 0x44 /* Normal, Non-cacheable */
#define MAIR_NORMAL_WB 0xFF /* Normal, Write-Back, Read-Allocate, Write-Allocate */
/* 设置MAIR寄存器 */
asm volatile("msr mair_el1, %0" : : "r" (MAIR_DEVICE_nGnRnE |
(MAIR_NORMAL_NC << 8) |
(MAIR_NORMAL_WB << 16)));
2.4 TLB与页表遍历的协同工作流
一次完整的内存访问地址转换流程如下:
- CPU发出虚拟地址,MMU并行查询ITLB/DTLB。
- TLB Hit:直接返回物理地址,访问L1/L2缓存或内存,耗时1-2周期。
- TLB Miss:硬件页表遍历器启动,根据TTBRx寄存器中的页表基址,逐级遍历页表。
- 页表遍历完成:找到有效的PTE,将其填充到TLB中,并返回物理地址。
- TLB填充策略:通常采用随机替换或轮转替换算法,部分架构支持锁死TLB条目(用于关键代码)。
- 属性检查:MMU同时检查PTE中的权限位(AP、XN、SH等),若违反则触发异常(Data Abort / Page Fault)。
DMA缓冲区设计要点:在配置DMA缓冲区的页表时,务必在PTE中设置AF=1(避免首次访问触发遍历)、SH=外部共享(多核一致性)、XN=1(防止指令预取污染)。对于高性能场景,使用2MB块映射可减少TLB压力。
2.5 本章小结
- TLB是地址转换的性能关键,其命中率直接影响系统实时性。大页映射是提升TLB覆盖范围的有效手段。
- 页表遍历器是硬件自动化的慢速路径,其延迟由页表层级和缓存命中率决定。DMA缓冲区应尽量减少遍历层级。
- PTE格式中的属性位(尤其是AttrIndx、SH、AP、XN)直接决定了DMA缓冲区的访问权限、缓存一致性和安全性。配置错误将导致DMA传输失败或数据损坏。
- 在嵌入式系统中,提前分配并锁定TLB条目(如使用TLB锁定或大页)是保证DMA实时性的关键优化手段。