一、先看图
flowchart LR
VA[64 位 VA] -->|高 bit 选表| SEL{TTBRn}
SEL -->|高位 1 = 内核| T1[TTBR1_EL1]
SEL -->|高位 0 = 用户| T0[TTBR0_EL1]
T0 --> L0[L0 → L1 → L2 → L3<br/>descriptor chain]
T1 --> L0
L0 --> PA[PA + Attrs]
ASID[ASID 16-bit] -.标签.-> TLB[TLB]
classDef reg fill:#a371f722,stroke:#a371f7,color:#adbac7;
classDef tbl fill:#388bfd22,stroke:#388bfd,color:#adbac7;
class T0,T1,ASID reg
class L0 tbl
二、两套 TTBR
ARMv8 把 VA 空间切成高半和低半:
- TTBR0_EL1:低半(0x0000_…),用户进程
- TTBR1_EL1:高半(0xFFFF_…),内核
好处:切换进程只需换 TTBR0,内核映射(TTBR1)纹丝不动——不需要像 x86 KPTI 那样变戏法。
TCR_EL1 寄存器控制各字段:T0SZ/T1SZ(VA 长度)、TGx(granule)、IPS(物理位数)等。
三、Granule 可选
ARM 支持三档”页大小”:
- 4K granule:最常见,Android/服务器/内核文档默认
- 16K granule:Apple Silicon 默认
- 64K granule:大页场景,曾用于 RHEL7 arm64,后改回 4K
granule 不等于 page size,但最小映射单位就是 granule。不同 granule 下翻译级数不同:
- 4K + 48VA:4 级(L0-L3)
- 16K + 48VA:4 级
- 64K + 48VA:3 级
四、Descriptor 格式
每项 8 字节,低 2 bit 决定类型:
00:invalid01:block(大页,相当于 x86 PSE)11:table(指下一级)11在 L3:page(叶节点)
高位是物理地址,低位若干 attribute bit:
- AP[2:1]:访问权限(RW/RO、EL0/EL1)
- AF:access flag(类似 x86 A)
- SH[1:0]:shareability
- AttrIdx[2:0]:MAIR 表索引,决定 memory type
- XN/UXN/PXN:execute never
- nG:non-global,配合 ASID
- DBM:dirty bit management(ARMv8.1)
五、ASID:原生 TLB 标签
16-bit ASID(小配置 8-bit)标签每个 mm:
- TLB 命中要 (ASID, VA) 都对
- 换进程只换 TTBR0 + ASID,TLB 仍保留
16-bit = 65536 个 ASID。耗尽后内核做 rollover(清 TLB、重分配)。
内核全局映射用 nG=0(忽略 ASID),用户映射 nG=1。
六、VHE(Virtualization Host Extensions)
ARMv8.1 引入 VHE,让 host 内核直接跑 EL2,无须像老 KVM 那样 guest 每次切到 EL2 的”shim”。
配合 E2H、TGE bit 重新解释 EL1 系寄存器。对 Linux 内核意义是 KVM 路径变短、切换更便宜。
dmesg | grep 'VHE' 看是否启用。
七、MTE(Memory Tagging Extension)
ARMv8.5 提出的硬件内存着色:
- 每 16 字节物理内存配 4-bit tag
- 指针的 56-59 位也存 4-bit tag
- 访问时硬件比 tag,不匹配 → 异常
用途:detect UAF、OOB,类似 HWASAN 但是硬件加速(开销 ~1-5%)。
Pixel 8 已在系统框架里实验性开启 “Async MTE”。
八、BTI / PAC
- BTI(Branch Target Identification):间接跳转必须落到 BTI 指令;堵 JOP
- PAC(Pointer Authentication):函数返回地址加签名;每次 ret 验签。Apple M1+、近年 Android 默认开
都靠页表 bit / 指令启用,用户态几乎无感。
九、PAN / UAO
- PAN(Privileged Access Never):EL1 态默认不能直接访问 EL0 地址;等价 x86 SMAP
- UAO(User Access Override):打补丁用;ARMv8.2
十、Linux arm64 实际布局
默认 4K granule + 48 位 VA:
0x0000_0000_0000_0000 .. 0x0000_ffff_ffff_ffff 用户(TTBR0)
0xffff_0000_0000_0000 .. 0xffff_ffff_ffff_ffff 内核(TTBR1)
内核空间再切成:
- VMALLOC 区
- 线性映射(PAGE_OFFSET 以上)
- modules 区
- fixmap
- kimage(KASLR 随机)
十一、观察 arm64 页表
cat /proc/cpuinfo | grep -E 'CPU architecture|Features'
# Features : asimd mte bti pauth ...
# 看 granule
cat /proc/config.gz | zgrep ARM64_PAGE_SHIFT # 12=4K, 14=16K, 16=64K
# MTE / BTI 运行时
grep -E 'mte|bti|pauth' /proc/cpuinfokernel
代码:arch/arm64/include/asm/pgtable-hwdef.h
定义各 bit;arch/arm64/kernel/setup.c 处理
feature 发现。
十二、x86 vs ARM 翻译对比
| 维度 | x86_64 | ARMv8-A |
|---|---|---|
| VA 分段 | 一条空间 + 非规范空洞 | TTBR0/1 硬件切两套 |
| 页大小 | 4K/2M/1G 固定 | granule 可选 4K/16K/64K |
| TLB 标签 | PCID(4.14+ 软件启用) | ASID(原生) |
| Accessed/Dirty | 硬件自动维护 | AF 硬件;DBM 可选 |
| 内存着色 | PKU(粗粒度) | MTE(16 字节粒度) |
| 控制执行 | NX + SMEP | XN/UXN/PXN + BTI |
| 级数 | 4 or 5 | 3 / 4 / 5(按 granule) |
十三、小结
- TTBR0/1 分家是 ARM 最有辨识度的设计
- granule 选择深刻影响页表结构
- ASID + nG 是”免费 PCID”
- MTE/BTI/PAC 让硬件承担一部分内存安全
参考文献
- ARM Architecture Reference Manual (ARM DDI 0487),VMSA 章节
Documentation/arch/arm64/memory.rst- Will Deacon 在 LPC 系列 arm64 MMU talks
- “Memory Tagging Extension for ARMv8-A.” ARM whitepaper 2019
- Mark Rutland, “Pointer Authentication on ARMv8.” 2017
工具
arch/arm64/tools/*perf stat -e dTLB-load-misses,iTLB-load-missestrace-cmd+arm_smmuevents- SCUDO / GWP-ASan(搭配 MTE)
上一篇:x86_64 多级页表 下一篇:TLB 工程
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【操作系统百科】特权级与硬件隔离:ring0、EL、SMEP/SMAP/PKU/CET
OS 的隔离能力在哪里落地?CPU 提供了特权级、MMU、MPU、enclave、VMX 等一串原语,OS 把它们组合成进程/用户/内核/hypervisor 等隔离层级。本文从 x86 ring 0-3、SMM、ARMv8 EL0-3 起步,梳理 SMEP/SMAP/PAN、KPTI、CET、MTE、PKU、IBRS 等缓解机制,说清楚每一项挡的是哪一类攻击。
【操作系统百科】系统调用 ABI:x86_64 / arm64 / riscv / Windows NT 对照
系统调用是 OS 最稳定的接口。本文拆解 Linux syscall 的参数寄存器约定、返回值规范(负 errno 与 2-value ABI)、x86_64 SYSCALL、arm64 SVC、RISC-V ECALL、Windows NT 的 int 2e/syscall/SYSENTER 历史;说明为什么 Linux 承诺 \"don't break userspace\"、什么东西算 syscall ABI、vDSO 如何用共享内存加速、Go/musl/glibc 各自怎么实现 syscall stub。
【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
【操作系统百科】交换
swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。