什么?时间太慢?加缓存!

利用时空局部性 (temporal and spatial locality),MMU 中的转译后备缓冲 (Translation Lookaside Butter, TLB) 通过缓存高频访问的 PTE 来加速地址翻译过程。

TLB

一个 TLB 项包括 VPN,PFN 和其他位如有效位,保护位等。

TLB 是全相联映射 (fully associative) 的:对于给定 VPN 的搜索是并行 (in parallel) 的,速度相当快。

Paging address translation with TLB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
while (!Success) {  // retry instruction
VPN = (VirtualAddress & VPN_MASK) >> SHIFT
(Success, TlbEntry) = TLB_Lookup(VPN)

if (Success == True) // TLB Hit
if (CanAccess(TlbEntry.ProtectBits) == True)
Offset = VirtualAddress & OFFSET_MASK
PhysAddr = (TlbEntry.PFN << SHIFT) | Offset
Register = AccessMemory(PhysAddr)
else
RaiseException(PROTECTION_FAULT)
else // TLB Miss
PTEAddr = PTBR + (VPN * sizeof(PTE))
PTE = AccessMemory(PTEAddr)
if (PTE.Valid == False)
RaiseException(SEGMENTATION_FAULT)
else if (CanAccess(PTE.ProtectBits) == False)
RaiseException(PROTECTION_FAULT)
else
TLB_Insert(VPN, PTE.PFN, PTE.ProtectBits)
}

TLB 未命中的处理

硬件处理:硬件通过 PTBR 查找页表,找到对应的 PTE,更新 TLB 中后重试指令。

OS 处理:硬件触发异常,OS 切入并运行陷阱处理器,搜索页表,使用特权指令更新 TLB 后从陷阱返回 (return from trap),硬件重试指令。

  • 系统调用后的从陷阱返回是从引发陷阱的指令之后继续执行的
  • TLB 未命中后的从陷阱返回是从引发陷阱的指令之前继续执行的,因此是重试指令

OS 处理可以使用自定义的算法与数据结构,更为灵活简单。

线程共享

上下文切换后,TLB 能在不同线程间共享吗?

  • 不能:将 TLB 中的所有项的有效位置 0,从而清空 (flush) TLB。
    • 每次线程切换后都将产生大量的 TLB 未命中
  • 能:在 TLB 中添加额外的地址空间标识符 (address space identifier, ASID) 对不同线程的 TLB 缓存进行标记。MMU 每次需要查找 VPN 与 ASID 两个字段。

替换策略

TLB 满后增加新条目,应当遵循怎样的替换策略?=> 最近最少使用 (least recently used, LRU)