MMU内存管理单元之TLB快表
1. TLB快表
页表以数据结构的方式存放在DDR中,假如cpu每做一次地址访问,都要去DDR里去取出1级描述符,然后解析1级描述符,再去查找2级描述符,解析2级描述符,加上偏移得到物理地址,那真是太慢了
1.1 MMU的cache ——TLB
TLB的全称是Translation Lookaside Buffer,我们知道,处理器在取指或者执行访问memory指令的时候都需要进行地址翻译,即把虚拟地址翻译成物理地址。而地址翻译是一个漫长的过程,需要遍历几个level的Translation table,从而产生严重的开销。为了提高性能,我们会在MMU中增加一个TLB的单元,把地址翻译关系保存在这个高速缓存中,从而省略了对内存中页表的访问
TLB也是一种cache,有cache也就意味着数据有多个copy,因此存在一致性(coherence)问题。和数据、指令cache或者unified cache不同的是,硬件并不维护TLB的coherence,一旦软件修改了page table,那么软件也需要进行TLB invalidate操作,从而维护了TLB一致性。
1.2 快速上下文切换FSCE
对于MMU如何识别进程的切换,几乎所有的参考资料上(包括ARM体系结构)均讲解的是快速上下文切换的方法,但其实操作系统并没有使用
快速上下文切换扩展FCSE(Fast Context Switch Extension),是MMU中的一个附加硬件,用于提高ARM嵌入式系统的系统性能。FCSE使得多个独立的任务可以运行在一个固定的重叠存储空间中,而上下文切换时又不需要清理或清除cache,或TLB。如果没有FCSE,则从一个任务切换到另一个任务需要改变虚拟存储映射。如果涉及两个有重叠地址的任务,则保存在cache和TLB中的信息将变为无效,这样系统就必须清除cache和TLB中的无效数据。清除这些模块的过程使任务切换增加了很多时间,因为内核不仅要清除cache和TLB中的无效数据,还要从主存中装载新的数据到cache和TLB。使用FCSE,虚拟存储管理增加了一次地址转换。FCSE在虚拟地址到达cache和TLB前,使用一个特殊的,包含进程ID值的重定位寄存器来修改虚拟地址。把修改之前的虚存地址称为VA(Virtual Address),把第一次转换之后的地址称为修改后虚地址MVA(Modified Virtual Address)。这样,任务间的切换就不用涉及到改变页表,只需简单的将新任务的进程ID写到位于CP15的FCSE进程ID寄存器。为了利用FCSE,编译链接所有的任务,使他们都运行在虚存的第一个32MB块空间,为每个任务分配一个进程ID;然后通过下边的公式,将每个任务放置在修改后虚存的不同32MB分区中:MVA = VA +(0x2000000 * 进程ID)
FSCE的一个主要限制是您最多有128个进程,并且每个进程的大小被限制为2^25或32MB才能利用它。它还消耗大量的虚拟地址空间。这就是为什么它从未被引入Linux主线的原因。尽管许多嵌入式Linux设备可能受益,但它不像ASID那样通用,ASID支持256个进程,没有大小限制,也不消耗虚拟地址空间。
1.3 Global TLB和non-global
现代OS都将地址空间分为内核空间和用户空间。内核空间特权态访问,用户空间用户态访问。内核空间内容基本各个进程(包括内核线程)都差不多,内核地址空间是一样的,因此对于这部分地址翻译,无论进程如何切换,内核地址空间转换到物理地址的关系是永远不变的,在进程的时候,不需要清掉。对于用户空间,各个进程的内容都不太一样,保留只会造成混乱,需要清掉。在这种思路引导下,CPU在切换进程的时候,只会清掉不带Global标志的用户空间页表TLB,而不会动带有global标志的内核页表项。一个新的进程会开始一个半新的TLB,效能提高不少。