3. MMU硬件基础:MMU的组成与工作流程

内存管理单元(MMU)是CPU内部负责虚拟地址到物理地址转换的硬件模块。理解MMU的硬件组成、工作流程及其与CPU的交互机制,是掌握Linux内核页表管理的前提。本章从硬件视角剖析MMU的核心组件与运作原理。

3.1 MMU的硬件组成

现代MMU通常集成在CPU内部,由三个关键硬件单元构成:TLB(转译后备缓冲器)、页表遍历器(Page Table Walker)和控制寄存器组。三者协同完成地址转换与权限检查。

硬件视角提示: MMU不是独立芯片,而是CPU流水线中的一个功能模块。在ARMv8-A中,MMU位于L1 Cache之后、L2 Cache之前;在x86-64中,MMU逻辑集成在内存控制器中。

3.1.1 TLB(转译后备缓冲器)

TLB是MMU内部的高速缓存,用于存储最近使用的虚拟地址到物理地址的映射条目。其目的是避免每次内存访问都遍历页表,从而大幅降低地址转换延迟。

TLB特性 说明 典型值(x86-64)
条目数 存储的页表条目数量 L1 TLB: 64~128条
层级 通常分为L1/L2 TLB L1指令/数据分离,L2统一
关联度 全相联/组相联 L1: 全相联,L2: 4~8路组相联
页大小支持 支持4KB/2MB/1GB大页 4KB基础页 + 大页
命中延迟 TLB命中时的转换时间 1~2个CPU周期
TLB缺失代价: 当TLB未命中时,MMU必须启动页表遍历(硬件遍历),该过程需要多次内存访问(4级页表需4次),每次约10~100ns,总延迟可达数百纳秒,远高于TLB命中的1~2周期。

3.1.2 页表遍历器(Page Table Walker)

页表遍历器是MMU内部的硬件状态机,负责在TLB未命中时自动遍历内存中的页表结构。它从页表基址寄存器(如x86的CR3、ARM的TTBR0_EL1)开始,逐级解析页表条目,直到找到最终的物理地址或触发缺页异常。

// 页表遍历器硬件行为伪代码(4级页表,x86-64)
// 输入:虚拟地址 VA,页表基址 CR3
// 输出:物理地址 PA 或 缺页异常

uint64_t page_table_walk(uint64_t va, uint64_t cr3) {
    uint64_t pml4e = read_memory(cr3 + (va >> 39 & 0x1FF) * 8);
    if (!pml4e & PRESENT)  raise_page_fault(va);
    uint64_t pdpte = read_memory(pml4e & PAGE_MASK + (va >> 30 & 0x1FF) * 8);
    if (!pdpte & PRESENT)  raise_page_fault(va);
    if (pdpte & HUGE_PAGE) return (pdpte & HUGE_MASK) + (va & HUGE_OFFSET);
    uint64_t pde = read_memory(pdpte & PAGE_MASK + (va >> 21 & 0x1FF) * 8);
    if (!pde & PRESENT)    raise_page_fault(va);
    if (pde & HUGE_PAGE)   return (pde & HUGE_MASK) + (va & HUGE_OFFSET);
    uint64_t pte = read_memory(pde & PAGE_MASK + (va >> 12 & 0x1FF) * 8);
    if (!pte & PRESENT)    raise_page_fault(va);
    return (pte & PAGE_MASK) + (va & 0xFFF);
}
硬件遍历 vs 软件遍历: x86/ARM均采用硬件页表遍历器,TLB未命中时由MMU自动完成遍历。而一些早期RISC架构(如MIPS)采用软件遍历,TLB未命中触发异常,由操作系统手动填充TLB。硬件遍历延迟更低,但页表格式固定;软件遍历更灵活,但异常开销大。

3.1.3 控制寄存器组

MMU的行为由一组控制寄存器配置。这些寄存器在系统启动时由内核初始化,并在进程切换时更新。以下是关键控制寄存器及其功能:

寄存器 x86-64名称 ARMv8-A名称 功能描述
页表基址 CR3 TTBR0_EL1 / TTBR1_EL1 指向当前进程的页表物理基地址
MMU使能 CR0.PG SCTLR_EL1.M 开启/关闭MMU地址转换
页大小 CR4.PSE TCR_EL1.TG0/TG1 配置基础页大小(4KB/16KB/64KB)
地址空间 CR3.PCID TTBR0_EL1.ASID 进程地址空间标识,避免TLB刷全
异常级别 — SCR_EL3 / HCR_EL2 控制虚拟化/安全扩展的MMU行为

3.2 MMU的工作流程

MMU的地址转换流程可概括为以下步骤。每次CPU发出内存访问请求(取指令或数据读写),MMU都会执行此流程:

  1. 虚拟地址接收: CPU执行单元将虚拟地址(VA)发送给MMU。
  2. TLB查找: MMU根据VA的页号(VPN)在TLB中并行查找。若命中,直接获取物理页框号(PFN)并拼接偏移量,跳至步骤5。
  3. 页表遍历: TLB未命中时,页表遍历器从控制寄存器读取页表基址,逐级读取页表条目(PTE),检查权限位(读/写/执行)和存在位(Present)。
  4. TLB填充: 遍历成功后,将新映射条目写入TLB(硬件自动完成或触发微码填充),并更新访问位/脏位。
  5. 物理地址生成: 将物理页框号与页内偏移拼接,生成最终物理地址(PA),发送给内存控制器。
  6. 权限检查: 若页表条目权限不足(如写只读页),MMU触发权限异常(Page Fault),由操作系统处理。
MMU地址转换工作流程 CPU发出VA请求 MMU接收虚拟地址 TLB查找(VPN匹配) 命中? TLB命中→取PFN TLB未命中→遍历 页表遍历器逐级解析 填充TLB + 更新PTE 生成物理地址PA 发送PA到内存控制器 是 否

3.3 MMU与CPU的交互

MMU并非独立工作,它与CPU流水线、Cache、中断控制器紧密耦合。以下是关键的交互机制:

3.3.1 流水线集成

在CPU流水线中,MMU位于取指阶段(IF)和访存阶段(MEM)之间。具体交互如下:

  • 取指阶段: 指令指针(PC)输出的虚拟地址先经过MMU转换为物理地址,再发送给L1指令缓存(L1 I-Cache)。
  • 访存阶段: 加载/存储指令的虚拟地址同样经过MMU转换,然后访问L1数据缓存(L1 D-Cache)。
  • 乱序执行: 现代CPU支持推测执行,MMU必须处理推测性地址转换,并在推测错误时回滚TLB状态。

3.3.2 异常与中断交互

当MMU检测到异常情况时,通过CPU的异常处理机制通知操作系统:

MMU异常类型 触发条件 CPU响应 Linux处理
缺页异常 页表条目Present位为0 保存上下文,跳转到缺页异常向量 do_page_fault()分配物理页
权限异常 写只读页/执行不可执行页 触发保护异常(#GP/Segfault) 发送SIGSEGV信号
TLB冲突异常 TLB中同VPN多条目(罕见) 硬件自动清除冲突条目 无需软件干预
访问位更新 PTE的Accessed位为0 MMU设置Accessed位,可能触发写回 页面回收算法使用

3.3.3 TLB刷新与上下文切换

进程切换时,新进程的页表基址写入控制寄存器,但TLB中可能残留旧进程的映射。MMU与CPU通过以下机制保证正确性:

  • ASID(地址空间标识符): 每个TLB条目携带ASID标签,不同进程使用不同ASID。切换时仅需更新控制寄存器中的ASID,无需刷TLB。
  • TLB刷指令: 当页表修改(如解除映射)时,内核执行特权指令(x86: INVLPG,ARM: TLBI VAE1IS)使特定条目失效。
  • 全局页(Global Page): 内核空间映射通常标记为Global,TLB条目不携带ASID,切换进程时保留,减少TLB缺失。
性能关键点: 在大型多核系统中,TLB shootdown(跨核TLB刷新)是重要的性能开销。当CPU A修改页表时,必须通过IPI中断通知所有其他CPU刷新相关TLB条目。Linux使用flush_tlb_mm_range()等函数管理此过程。

3.4 多级页表与MMU硬件适配

MMU的页表遍历器设计为支持固定级数的页表结构。以x86-64的4级页表和ARMv8-A的3级/4级页表为例,MMU硬件直接硬编码了各级索引的位域划分:

架构 页表级数 索引位域 页大小 最大地址空间
x86-64 4级(PML4→PDPT→PD→PT) 9+9+9+9+12 4KB 48位(256TB)
ARMv8-A(4KB页) 4级(PGD→PUD→PMD→PTE) 9+9+9+9+12 4KB 48位(256TB)
ARMv8-A(64KB页) 3级(PGD→PMD→PTE) 13+13+13+16 64KB 48位(256TB)
RISC-V Sv39 3级 9+9+9+12 4KB 39位(512GB)
MMU与CPU流水线集成示意图 取指 IF MMU转换 L1 I-Cache 译码 ID 执行 EX 访存 MEM MMU转换 L1 D-Cache 写回 WB 说明: • 取指阶段和访存阶段各有一个MMU转换单元,分别处理指令地址和数据地址。 • MMU转换单元内部包含TLB和页表遍历器,转换结果直接驱动Cache访问。 • 异常处理:MMU检测到缺页或权限错误时,通过异常信号中断流水线。

3.5 关键硬件特性总结

MMU硬件设计对操作系统内存管理有深远影响。以下是需要重点记忆的硬件特性:

  • TLB是性能关键: TLB命中率直接影响内存访问延迟。大页(Huge Pages)通过减少页表级数和TLB条目占用,显著提升TLB命中率。
  • 页表遍历器固定格式: 硬件遍历器要求页表格式严格遵循架构规范。Linux通过pgtable_t类型和pte_t等抽象层适配不同架构。
  • 控制寄存器切换开销: 写控制寄存器(如CR3)通常需要数十周期,且可能触发TLB刷全。Linux通过PCID/ASID技术减少切换开销。
  • 硬件一致性: 多核系统中,MMU必须保证页表修改的全局可见性。通常需要内存屏障指令(如sfence/dsb)配合TLB刷新。
学习建议: 在阅读Linux内核源码时,重点关注arch/x86/mm/和arch/arm64/mm/目录下的文件。其中tlb.c处理TLB刷新,fault.c处理缺页异常,pgtable.c管理页表分配。结合本章的硬件知识,可以更深入理解内核为何如此设计。