TLB管理¶
基础知识¶
处理器在访问内存时都需要经过地址翻译,将虚拟地址翻译成物理地址。地址翻译是一个漫长的过程,ARMv8支持四级页表也就是说要经过四次翻译才能找到对应的物理地址。为了提高性能,硬件设计师在MMU中新增了一个叫TLB的单元,把翻译好的地址保存在这个缓存中,从而跳过繁杂的地址翻译过程。
CPU在查询地址时,会先在TLB中查询。如果找到,称为TLB命中。如果没有找到,才会执行地址翻译,并把结果缓存到TLB中,以便下次查询,这个叫做TLB未命中。
一个TLB项可以包括以下内容:
- VPN:虚拟地址页帧号
- PFN:物理地址页帧号
- V:有效位
- nG:表明是否是全局TLB或进程独有TLB
- D:脏位
- AP:访问权限
- ASID:进程地址空间ID
同名问题¶
现代操作系统允许进程拥有独立的地址空间,但是这容易引发同名问题。所谓同名问题就是进程A与进程B拥有相同的虚拟地址,但是对应的物理地址不同,在进行进程切换时,新的进程去TLB中查询时,可能会返回旧进程的物理地址,从而导致错误。
一种解决方案是每次进程切换时就刷新TLB使得TLB失效,但是这会对性能造成严重的影响。因为在发生进程切换之后,新进程面对的是一个空白的TLB,相当于冷启动,以前建立的TLB全都不能用了,而重建TLB需要花费大量的时间。
为了提高TLB的性能,几十年来芯片设计人员和操作系统设计人员付出了巨大的努力。从内核角度看,地址空间可以分为两种:内核空间和用户空间,因此TLB对应地也可以分为两种:
- 全局TLB:缓存了内核空间的映射,这部分内容不会变化。
- 进程独有TLB:缓存了每个进程的用户空间映射,这部分内容会随着进程切换而变化。
为了支持进程独有TLB,ARM体系结构提供了硬件上的支持:进程地址空间ID(ASID),每个进程的ASID都不同。TLB命中的查询过程需要包含对ASID的检查,只有当ASID匹配时,才允许TLB命中。而TLB项的nG位则用来标识该TLB是进程独有还是全局的。
管理指令¶
ARMv8体系结构提供了TLB管理指令来帮助刷新TLB,有些场景需要我们手动使用TLB管理指令来维护TLB一致性。
ARMv8体系结构提供的指令有:
- 使所有TLB项失效
- 使ASID对应的某个TLB项失效
- 使ASID对应的所有TLB项失效
- 使虚拟地址对应的所有TLB项失效
TLBI指令用于管理TLB,格式如:TLBI <type><level>{IS} {<Xt>}
。
注意,如果想要保证TLB管理指令的执行次序,我们还需要使用内存屏障指令。
ARM64体系结构编程与实践一书中P278页 ~ P286页对于TLB案例的分析非常精彩,推荐阅读。