ARM TLB
时间轴
2025-10-26
init
参考文档:
TLB基础知识
ARMv8.6 芯片手册与TLB相关内容
D5.9章 Translation Lookaside Buffers(TLBs)
D5.10章 TLB maintenance requirements and the TLB maintenance instructions
TLB背景知识

- TLB是cache的一种
- TLB的表项:记录了最新使用的VA到PA的转换结果
- TLB基地址在映射基础寄存器(TTBR0_EL1)和(TTBR1_EL1)中指定。当 VA 的上面几位都是 0 时,TTBR0
所指向的映射表被选中,当 VA 的上面几位都被设置为 1 时,TTBR1 被选中。 - EL2 和 EL3 有一个 TTBR0,但没有 TTBR1。这意味着:
- 如果 EL2 使用的是 AArch64,它只能使用范围在 0x0 到 0x0000FFFF_FFFFFFFF。
- 如果 EL3 使用的是 AArch64,它只能使用范围在 0x0 到 0x0000FFFF_FFFFFFFF。

- TLB也支持全相连,支持直接映射,组相连等三种映射方式。
- Cortex-A72采用两级TLB设计。类似2级cache的设计思路。
- L1 instruction and data TLBs(全相连)
- 48-entry fully-assocaitive L1 1-TLB
- 32-entry fully-associative L1 D-TLB
- L2 unified TLB.4-way set-associative of 1024-entry L2 TLB(组相连)
- L1 instruction and data TLBs(全相连)

每个 TLB 条目通常不仅包含物理地址和虚拟地址,还包含诸如内存类型、缓存策略、访问权限、地址空间 ID
(ASID)和虚拟机 ID(VMID)等属性

TLB的重名(别名)问题

虽然VP1和VP2在TLB里缓存了两个不同的TLB entry,但是TLB entry里的PFN都是指向Phys Page,所以,不会产生别名问题
TLB的同名问题

进程A切换到进程B,旧进程使用的TLB对新进程来说是无用数据,并且可能产生同名问题。如果直接在进程切换时invalidate TLB,那么性能上会有较大损失。解决方法就是使用ASID(Address Space Identifier)技术
ASID(Address Space Identifier)
- 全局类型的TLB:内核空间是所有进程共享的空间
- 进程独有类型的TLB:用户地址空间是每个进程独立的地址空间
- ASID机制用来实现进程独有类型的TLB
- ARMv8的ASID是存储在TTBR0_EL1或者TTBR1_EL1中。其中TCR寄存器的A1域可以做选择
- ASID支持8位或者16位
- 8位宽的ASID,最多支持256个ID
- 16位宽的ASID,支持65536个ID


TCR_EL1 中定义:

TLB可以识别哪个TLB entry属于哪个进程,这个是解决TLB同名问题的核心思想。这样进程切换时只需要刷掉被切换的进程的TLB entry
操作系统常使用位图的方式管理ASID,一般不会用进程的PID

此外,ARMv8-A 架构提供线程 ID 寄存器供操作系统软件使用。这些寄存器没有硬件意义,通常由线程库作
为每个线程数据的基本指针使用。这通常被称为线程本地存储(TLS)。例如,pthreads 库使用这一功能,包
括以下寄存器:
- 用户读写线程 ID 寄存器(TPIDR_EL0)。
- 用户只读线程 ID 寄存器(TPIDRRO_EL0)。
- 线程 ID 寄存器,仅限特权访问(TPIDR_EL1)
Linux内核里的ASID
Linux内核里为每个进程分配两个ASID,即奇,偶数组成一对
- 当进程运行在用户态时,使用奇数ASID来查询TLB
- 当程序陷入内核态运行时,使用偶数ASID来查询TLB
为每个进程分配两个ASID主要是解决熔断漏洞问题
硬件的ASID的分配通过位图来分配和管理
进程切换的时候,需要把进程持有的硬件ASID写入到TTBR1_EL1寄存器里
当系统中所有的硬件ASID加起来超过硬件最大值时会发生溢出,需要刷新全部TLB,然后重新分配硬件ASID

页表项中的nG属性

第11位nG:
1:表示这个页面对应的TLB页表项是进程特有的
0:表示是使用全局的TLB
TLB缓存一个块
ARMv8-A 架构提供了一个称为连续块条目的功能,以有效地使用 TLB 空间。
映射表块条目每个都包含一个连续的位。当设置时,该位向 TLB 发出信号,它可以缓存一个涵盖多个块的映射的单一条目。一个查找可以索引到一个连续块所覆盖的地址范围的任何地方。因此,TLB 可以为定义的地址范围缓存一个条目,使得在 TLB 中存储更大范围的虚拟地址成为可能。
要使用一个连续的位,连续的块必须是相邻的,也就是说它们必须对应于一个连续的虚拟地址范围。它们必须从一个对齐的边界开始,具有一致的属性,并指向同一级别转换的连续输出地址范围。
TLBI指令
如果操作系统修改了可能已缓存在 TLB 中的映射条目,那么操作系统就有责任使这些陈旧的 TLB 条目失效,需要使用TLBI指令
- ARMv8提供了TLBI指令
- 指令格式:
1 | TLBI <type><level>{IS} {,Xt} |
- Type:
- ALL 整个TLB
- VMALL 所有的TLB entry(stage 1, for current guest OS)
- VMALLS12 所有的TLB entry(stage 1&2 for current guest OS)
- ASID 和ASID匹配的TLB entry,xt指定虚拟地址以及ASID
- VA 虚拟地址指定的TLB entry,xt指定虚拟地址以及ASID
- VAA 虚拟地址指定的TLB entry,xt制定了虚拟地址但是不包括ASID
- Level:En=异常等级(n可以是3,2,or 1)
- IS:表示inner share
- Xt:由虚拟地址和ASID组成的参数
- Bit[63:48]:ASID
- Bit[47:44]:TTL,用于指明使哪一级的页表保存的地址无效。若为0,表示需要使所有级别的页表无效(一般都设置为0)
- Bit[43:0] :虚拟地址的Bit[55:12]

例子:修改页表后对TLB进行刷新
1 | // Writes to Translation Tables |
执行场景:你修改了页表映射(如修改虚拟地址到物理地址的映射),CPU 仍可能用旧 TLB 翻译缓存,所以:
- 必须先确保页表写入完成 →
DSB ISHST - 使旧 TLB 失效 →
TLBI ALLE1 - 确保失效动作真正完成 →
DSB ISH - 刷新 CPU 指令执行上下文 →
ISB
相关寄存器
TCR_EL1
TCR_EL1 控制 EL1 和 EL0 的其他内存管理功能。



| 字段 | 位范围 | 含义 | 用于 |
|---|---|---|---|
| T0SZ | [5:0] |
控制 TTBR0 的虚拟地址空间大小 | 用户空间或低地址映射 |
| TG0 | [15:14] |
TTBR0 页大小(Granule Size) | 4KB/16KB/64KB 页 |
| T1SZ | [21:16] |
控制 TTBR1 的虚拟地址空间大小 | 内核空间或高地址映射 |
| TG1 | [31:30] |
TTBR1 页大小(Granule Size) | 4KB/16KB/64KB 页 |
| IPA size | [34:32] |
控制中间物理地址宽度 (Intermediate Physical Address Size) | 用于虚拟化或物理地址上限设置 |




