ITLB

TLB 功能概述

现代操作系统通常采用虚拟内存管理机制(Virtual Memory Management),在处理器中对应需要内存管理单元(MMU,Memory Management Unit)来进行虚实地址的映射。MMU 负责处理 CPU 的内存访问请求,其功能包括虚实地址的映射、内存保护、CPU 高速缓存控制等。

虚实地址的映射是以页(Page)为单位的。在物理内存管理中,内核会将整个物理内存空间划分为一个一个的页帧(Page Frame),一般情况下页帧大小为 4KB,称为一个物理页帧,内核会将每一个物理页帧进行编号(PFN,Page Frame Number),每个页帧有唯一确定的 PFN。对于一个进程来说,如果它直接使用物理地址构建自己的地址空间,那么作为进程就需要关心每一个变量存放在哪一个物理地址,也就是说程序员需要清楚数据在内存中的具体布局,还需要每次都要考虑内存的分配问题;同时,对于多个进程同时进行的情况,哪些数据是共享的,如何避免地址冲突等等都会成为问题。

进程地址空间

MMU 为每个进程创建自己的虚拟地址空间,存储虚实地址的映射,在进程的视角看来它独享一段确定的(通常是连续的)地址,避免了其它进程的干扰;同时提供了虚实地址转换功能,这使得进程不必关心实际的物理地址在哪里,只需要对自己的地址空间进行操作。同时,对于一个进程来说,每次访问内存时并不是访问整个虚拟内存空间,因此进程实际需要占用的物理内存大小可以小于其虚拟地址空间的大小,由操作系统来决定要把哪一部分留在内存中,将剩余部分保存在磁盘中,在需要时再加载进入内存,极大的扩展了可用内存空间。

程序局部性原理,是计算机科学术语,指程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域。局部性原理又表现为:时间局部性空间局部性

  • 时间局部性是指如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行;如果某数据被访问,则不久之后该数据可能再次被访问。
  • 空间局部性是指一旦程序访问了某个存储单元,则不久之后,其附近的存储单元也将被访问。

虚实页表映射

这样的由 MMU 创建的并负责维护的由虚拟地址指向物理地址的映射也将成为一项存储在一个物理页帧中,MMU 为了访问这样的物理页帧也需要一个根页表,根页表中存储着指向这些物理页帧的页表项(PTE),称为叶子 PTE。一个 PTE 的长度一般为 64 Bit(8 Bytes),而每一个一般物理页帧的大小为 4KB,这也就意味着一个物理页帧最多可以存储 4KB/8B = 2^9 个 PTE,因此根页表可以索引的范围即为 2^9 × 4KB = 2MB。2MB 的页表并不能满足内存日益增大的需要,在香山中实现的 SV48 即采用了四级页表的形式,通过四级的查询最终得到物理地址,每一级页表都能够索引 2^9 个下一级页表,最终找到需要的映射。四级页表下能够索引的地址范围达到了 2^9 × 2^9 × 2^9 × 2MB = 256TB。而页表本身也会比较大,如果存满的话大小会达到 4KB + 2^9 × 4KB + 2^9 × 2^9 × 4KB + 2^9 × 2^9 × 2^9 × 4KB = 537921540KB ≈ 513GB。当然,不是说每一级页表都要填满,页表的四级结构可以理解为一个多叉树形结构,只有需要用到的才会实际使用,很多的分支都不需要使用,因此页表的大小是可变的。

页表一般很大,需要存放在内存中,而处理器每一次访问内存的请求都需要先访问页表查找对应的物理页号然后再去读取所需数据,因此在不发生缺页的情况下,每次访存操作都需要两次访问内存才能得到物理地址,然后再次访问才能得到需要的数据。为了减少多次访存造成的开销,引入了地址转换后援缓存器(TLB,Translation Lookaside Buffer)。MMU 通常借助 TLB 来进行虚实地址的转换。TLB 一般是相连高速缓存(associative cache),相当于页表的 Cache,负责将最可能会用到的页表项对应的映射(虚拟地址与对应的物理地址)存储下来;在查找页表时首先查找 TLB 内存储的映射,如果没有命中再去查找内存中存储的完整页表。

同 Cache 一样,TLB 中页表项的组织方式一般有直接映射、全相联映射、组相连映射三种方式。直接映射一般通过模运算匹配,例如对昆明湖 48 行的 TLB 来说,其第 1 块只能对应内存的第 1/49/97/…/(n×48+1) 块,硬件结构简单、成本低、转换速度快,但是 TLB 表项利用率低,TLB miss 频繁,只适用于 TLB 大小与页表大小较接近的情况。全相联映射则不同,内存中的所有表项可以存放在 TLB 中的任意一项中,可以充分利用 TLB 的空间,冲突概率更低,但因此查找开销较高,适用于小容量 TLB。组相联映射是一种折中,可以二路组相联、四路组相联等。在香山的 TLB 模块中提供了丰富的参数配置,其中即包括采取哪一种相连方式,可以通过传入参数自行配置。本次验证的 ITLB 即采用 48 项全相联的结构。

二路组相联示意图 四路组相联示意图

香山的 MMU 模块由 TLB、Repeator、L2TLB、PMP&PMA 组成,其中 L2TLB 又包含了 Page Cache、Page Table Walker、Last Level Page Table Walker、Miss Queue 和 Prefetcher。在核内每次进行内存的操作(读写)时都需要通过 MMU 模块进行虚实地址的翻译,而 TLB 将被实例化为 ITLB(前端取指)和 DTLB(后端访存)。以 ITLB 为例,每当 ICache 或 IFU 需要进行取指操作,会先向 ITLB 发送一个地址转换请求,把需要转换的虚拟地址发给 ITLB;ITLB 接收到请求后就要查找自己存储的表项里有没有这个虚拟地址对应的映射,如果有的话就输出对应物理地址(paddr),之后由 PMP&PMA 模块检查对该物理地址的访问是否有效(包括地址是否有效、访问者是否有访问权限、页表属性等,其中对 ITLB 来说由于取出来的物理地址是待执行的指令,需要检查是否可以执行),检查通过后就可以把物理地址返回给前端。如果 ITLB 发现自己没有存储这样的表项,那么立即回应 miss,并同时发起 PTW 请求。前端接收到 miss 信号后会通过一些调度策略重新发起访问,在香山中体现为 miss 后不断重新给 TLB 发请求直到 hit。PTW 请求将交由 Page Table Walker 来执行,通过一些策略访问 L2TLB、Page Cache、内存中的完整页表,之后把访问到的 PTE(页表项)发回给 TLB(如果 PTW 都找不到那么会发生 Page Fault,同样返回给 TLB,TLB 收到 Page Fault 后会上报并由操作系统等从磁盘中加载页面)。TLB 接收到 PTE 的同时将 PTE 填充进自己的缓存中并向前端返回物理地址,前端才能通过该物理地址找到对应的指令。

TLB功能示意图

香山实现了二级 TLB,包括 TLB 与 L2TLB。同样类似于 Cache 与 L2Cache,TLB(一级 TLB)通常是小容量、高速缓存,直接与处理器核心连接,用于加速最近访问过的虚拟地址到物理地址的转换;L2TLB(二级 TLB)容量较大,速度稍慢,但比直接访问内存要快。L2TLB 用来缓存更多的页表项,减少一级 TLB 未命中(TLB Miss)时对内存的频繁访问,香山目前有 1 个 ITLB 和 3 个 DTLB,都与同一个 L2TLB 连接。在这种二级结构下,TLB 未命中时将会首先查找 L2TLB,之后如果再次未命中才去访问内存,可以有效提高地址转换的命中率和性能。由于在 TLB 与 L2TLB 之间有着一定的物理距离,因此在 TLB 向 L2TLB 发出读取请求的时候需要进行加拍,这项工作交给了 MMU 中的 repeater 进行,是 TLB 与 L2TLB 之间的一个请求缓冲。同时,repeator 还需要负责对 TLB 向 L2TLB 发送的请求进行过滤(即 Filter 的功能),把重复的请求过滤掉,以减少 L2TLB 性能损失。

昆明湖架构支持 RISC-V 手册中定义的 Hypervisor 扩展,即 H 扩展。H 扩展为处理器提供了虚拟化的支持,即允许虚拟机运行在主机上,此时虚拟机将与主机共享 TLB,那么在 MMU 中也需要进行相应的调整与支持。TLB 需要能够同时容纳多个虚拟机的条目并做到隔离,同时需要引入 Hypervisor Page Table Walker(HPTW)用于遍历虚拟机的页表。

在 MMU 模块中还需要实现 PMP(Physical Memory Protection)与 PMA(Physical Memory Access)检查,不过这与 TLB 无关,在实现中无论请求是否有效或有足够权限,都会通过 TLB 先进行地址转换,之后再把转换的结果(物理地址)送到 PMP&PMA 模块进行权限检查。

最后修改 February 22, 2025: ifu top rtl build scripts modify (#76) (5520758)