我正在编写一些涉及 L1/2/3 缓存驱逐和 TLB 条目失效的代码。我尝试使用指令INVLPG
使 TLB 条目失效并验证 实现的一些结果mprotect()
,但我对INVLPG
和mprotect()
对缓存层次结构的影响都表示怀疑,因为这对我来说很重要。
具体来说:当使给定地址的INVLPG
TLB 条目无效(或mprotect()
降低对 TLB 条目具有类似效果的权限)时,是否会对给定地址的 CPU 缓存造成任何副作用?它是否可能导致创建缓存条目或影响缓存条目?
我找不到有关它们的缓存交互的具体细节。
至少在过去几十年的主流 x86 CPU 上,包括 L1i 和 L1d 在内的缓存都是物理寻址的(L1 缓存的 VIPT,但避免了混叠)。(英特尔酷睿 i7 处理器中使用了哪种缓存映射技术?)。因此,当虚拟页面不再引用同一物理页面时,它们不需要失效;任何有效条目只需继续缓存其物理页面的行即可。
一些微架构具有更大的低关联 L1 缓存(例如Zen 1的 64K 4 路 L1i 和 K10/Bulldozer 的 64K 2 路 L1i),需要一些技巧来避免混叠问题。我认为它们可能仍然像纯物理寻址一样工作,因为不需要无效
invlpg
。过去对此类缓存的一些讨论包括:invlpg
不能使 L1i 条目无效。(并且共享 L1i 的两个核心可以共享条目,而不需要像 TLB 条目那样将它们标记为属于一个核心或另一个核心。)Sandybridge 系列中的 uop 缓存 (DSB) 是虚拟寻址的,因此需要通过 使其无效
invlpg
。(我假设它标有 PCID(进程上下文 ID),因此不一定必须在每次更改 CR3 时使其无效。它至少需要一些 SMT(超线程)的上下文标记。我对 AMD Zen 的 uop 缓存了解不多。虚拟寻址确实可能缩短英特尔的命中延迟,而强大的解码器使重新填充变得便宜,因此如果 AMD 做出同样的选择,那将是有意义的。
不,它不应该。
invlpg
不加载或存储任何东西;它永远不会导致页面漫游(会通过缓存),因为它只是访问 TLB 本身来检测与给定的虚拟地址匹配的条目。x86 寻址模式不包括内存间接,因此地址计算仅涉及读取寄存器。即使是 AMD
invlpgb
(向其他 CPU 广播无效消息,Zen 3 中的新功能)可能也不应该触及内存。如果没有它,操作系统需要发送 IPI(处理器间中断)来关闭其他核心上的 TLB 条目,以用于多线程进程。操作系统代码在这些 CPU(中断处理程序)上运行,当然会涉及加载和存储。