B05 — How the MMU Translates Virtual Addresses to Physical Addresses
Key Insight: Behind every virtual address is a complex translation process. And you never perceive it.
What is an MMU
The MMU is a hardware unit on the CPU chip. It translates Virtual Addresses (VA) to Physical Addresses (PA).
MMU 在系统中的位置:
CPU Core Memory Controller
│ │
执行单元 ──→ VA ──→ MMU ──→ PA ──→ Cache/DRAM
│
Translation:
VA → PA
MMU 的职责:
1. 虚拟地址到物理地址的翻译(Address Translation)
2. 访问权限检查(读/写/执行权限)
3. 内存保护(防止用户进程访问内核空间)
4. TLB 缓存(加速翻译)
为什么需要 MMU:
- 让每个进程有独立的地址空间(隔离)
- 支持虚拟内存(内存可以比实际物理内存大)
- 防止恶意程序访问其他进程或内核的内存Virtual Address to Physical Address Translation
x86-64 virtual address translation:
x86-64 虚拟地址(48-bit)的结构:
63~48(符号扩展)| 47~39 | 38~30 | 29~21 | 20~12 | 11~0
[31 bits] | PML4 | PDPT | PD | PT | Offset
每个索引 = 9 bits(512 个条目)
页大小 = 4KB(Offset = 12 bits)
总虚拟地址空间 = 2^48 = 256TB
线性地址解析:
VA[47:39] → PML4 索引(512 条目)
VA[38:30] → PDPT 索引(512 条目)
VA[29:21] → PD 索引(512 条目)
VA[20:12] → PT 索引(512 条目)
VA[11:00] → 页内偏移(4KB)Translation Process (4-Level Page Table):
VA = 0xFFFF880000001000(48-bit)的翻译过程:
Step 1:读取 CR3(页目录基址寄存器)
CR3 = 0x100000(假设)
Step 2:PML4[VA[47:39]]
Index = VA[47:39] = 0x1FF(511)
PML4[511] = 0x1010000000000863
→ 这是 PDPT 的物理地址(高 52 bits 有效)
→ 权限:User + RW + Present
Step 3:PDPT[VA[38:30]]
PDPT 物理地址 = 0x1010000000000863 & 页对齐 = 0x1010000000000000
Index = VA[38:30] = 0x000
PDPT[0] = 0x1020000000000867
→ 这是 PD 的物理地址
Step 4:PD[VA[29:21]]
PD 物理地址 = 0x1020000000000000
Index = VA[29:21] = 0x000
PD[0] = 0x1030000000000867
→ 这是 PT 的物理地址
Step 5:PT[VA[20:12]]
PT 物理地址 = 0x1030000000000000
Index = VA[20:12] = 0x001
PT[1] = 0x0000000000000863
→ 这是 4KB 页的物理基址
Step 6:生成物理地址
PA = 0x0000000000000863 + Offset(VA[11:0] = 0x000)
PA = 0x0000000000000863
最终:VA 0xFFFF880000001000 → PA 0x0000000000000863Structure of a Page Table Entry (PTE)
x86-64 PTE(Page Table Entry,8 bytes):
63 62 60 59 58 57 56 55 52 51 50 49 48 47 40 39 32
P RSVD XD RSVD U RW PS G PAT AVL [ Physical Address 52:48 ]
31 12 11 9 8 7 6 5 4 3 2 1 0
[ Physical Address 47:12 ] | PAT | G |D| A| PCD| PWT| U| W| P|
字段解释:
P(Present):页是否在内存中(0=不存在,换出到磁盘)
RW(Read/Write):读写权限
U(User/Supervisor):用户/内核访问权限
PS(Page Size):0=4KB, 1=2MB/1GB(大页)
G(Global):全局页(TLB 不刷新)
A(Accessed):访问过(用于页面换出判断)
D(Dirty):脏页(被写过,用于写回)
XD(Execute Disable):禁止执行(安全)
PCD/PWT:缓存控制TLB(Translation Lookaside Buffer)
Every MMU address translation needs to access page tables, but page tables are in DRAM, so access latency is high (~60ns). TLB is the MMU’s built-in cache, caching recently used address translations.
TLB 的工作原理:
CPU 请求 VA = 0xFFFF880000001000
→ TLB 查询(并行检查所有 TLB 条目)
→ TLB Hit!(PTE 已在 TLB 中)
→ 直接使用 TLB 中的 PA
→ 延迟 ≈ 1 cycle(~0.3ns)
如果 TLB Miss:
→ MMU 查四级页表(60ns 延迟)
→ 发现 PA,构建 PTE
→ 把 PTE 存入 TLB(缓存)
→ 返回 PA
→ 后续访问同一页,TLB Hit
TLB 的命中率(典型):
- L1 TLB:~90%+ 命中率(128 条目)
- L2 TLB:~95%+ 命中率(1K~2K 条目)
- 每次 TLB Miss 约 60ns 额外延迟
Linux TLB 刷新:
- 当页表改变时,内核需要刷新 TLB(INVLPG/INVPCID)
- 进程切换时(CR3 改变),自动 flush TLBMemory Overhead of Multi-Level Page Tables
Why does x86-64 use 4-level page tables instead of a single-level page table?
一级页表的问题(2^48 个条目):
假设用一级页表(48-bit 索引):
- 需要 2^48 个条目 × 8 bytes = 2^48 × 8 = 256 TB 的页表!
- 完全不可行
多级页表的优势:
假设每个进程只用 128TB 虚拟地址空间中的 128MB:
PML4:1 个条目(1 页)
PDPT:1 个条目(1 页)
PD:32 个条目(32 页)
PT:32 × 128 个条目(32 × 128 × 8 = 32KB)
总计:4 页 = 16KB(而不是 256TB!)
稀疏虚拟地址只需要稀疏的页表项。
多级页表的内存节省:
- 进程只需要实际使用的虚拟地址区域对应的页表
- 不使用的 VMA 不需要页表
- 节省了大量内存Huge Pages (Large Pages)
To reduce TLB misses, modern CPUs support huge pages:
x86-64 支持的大页:
2MB 大页:PDE.PS=1,页内偏移 21 bits
1GB 大页:PDPTE.PS=1,页内偏移 30 bits
2MB 大页的 TLB 优势:
- 一个 TLB 条目覆盖 2MB(而不是 4KB)
- 大型数据(数据库、机器学习)用大页可以显著减少 TLB Miss
Linux 配置大页:
# 预留 16 个 2MB 大页(总共 32MB)
$ echo 16 > /proc/sys/vm/nr_hugepages
# 挂载 hugepage filesystem
$ mount -t hugetlbfs nodev /mnt/hugepages
程序使用:
mmap(NULL, 32MB, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0);
或者使用 SHM:
shmget(IPC_PRIVATE, 32MB, SHM_HUGETLB|IPC_CREAT|0600);Summary
- MMU: Memory Management Unit; hardware on the CPU chip responsible for VA to PA translation
- 4-Level Page Table: PML4 → PDPT → PD → PT; each level has 9-bit index, 512 entries
- Virtual Address Structure: x86-64 uses 48-bit VA; split into five 9-bit indices + 12-bit offset
- PTE Structure: 8 bytes; contains physical base address + permission bits (RW/U/P/XD/G/A/D)
- TLB: MMU’s built-in cache; ~60ns latency without → ~0.3ns with cache hit; 90%+ hit rate
- Multi-Level Page Tables: Sparse VMA only needs sparse page tables; saves significant memory (single level 256TB vs 4-level 16KB)
- Huge Pages: 2MB/1GB pages reduce TLB misses; suitable for large data applications
Next (B06): How does Linux’s buddy system manage physical memory? Physical page allocation and deallocation, and why buddy system instead of simple bitmap management.
Comments