clflush
1是否也刷新相关的TLB条目?我认为不是因为clflush
以缓存行粒度运行,而TLB条目存在于(更大)页面粒度 - 但我准备感到惊讶。
1 ...或clflushopt
虽然可以合理地假设他们的行为是相同的。
我认为没有假设是安全的;将invlpg
烘焙到clflush
听起来像一个疯狂的设计决定,我认为没有人会做。您经常希望使页面中的多行无效。也没有明显的好处;刷新TLB也不会使实现数据缓存刷新变得更容易。
即使只删除最终的TLB条目(不必使任何页面目录缓存无效)也会比invlpg
弱,但仍然没有意义。
所有现代x86都使用具有物理索引/标记的缓存,而不是虚拟。 (VIPT L1d缓存实际上是PIPT,其中包含索引的自由转换,因为它取自地址位,这是位于页面内偏移的一部分。)即使缓存是虚拟的,TLB条目无效也需要无效虚拟缓存,但不能相反。 。
根据IACA,clflush
在HSW-SKL上仅为2 uops,在NHM-IVB上为4 uops(包括微融合)。所以它甚至都没有在英特尔上进行微编码。
IACA没有对invlpg
进行建模,但我认为它更具uops。 (并且它具有特权,因此测试并不是完全无关紧要。)远程可能在HSW之前的那些额外的uops用于TLB失效。
我没有关于AMD的任何信息。
invlpg
享有特权的事实是期望clflush
不成为它的超集的另一个原因。 clflush
没有特权。据推测,仅出于性能原因,invlpg
仅限于响铃0。
但是invlpg
不会出现页面错误,因此用户空间可以使用它来使内核TLB条目无效,延迟实时进程和中断处理程序。 (wbinvd
由于类似的原因而享有特权:它非常缓慢,我认为不会中断。)clflush
在非法地址上做错,因此它不会打开拒绝服务漏洞。不过,你可以clflush
共享的VDSO页面。
除非出于某种原因为什么CPU想要在用户空间中暴露invlpg
(通过将其烘焙到clflush
),我真的不明白为什么任何供应商会这样做。
对于计算未来的非易失性DIMM,任何未来的CPU都不太可能让它在执行clflush
的内存范围内超级缓慢。您期望使用内存映射NV存储的大多数软件都使用clflushopt
,但我希望CPU供应商尽可能快地制作clflush
。
可以使用dTLB-loads-misses:u
性能事件来确定clflush
是否刷新映射指定高速缓存行的TLB条目。当所有TLB级别中的加载未命中并导致页面遍历时,会发生此事件。与dTLB-stores-misses:u
相比,它也得到了更广泛的支持。特别是,英特尔P4及更高版本(Goldmont除外)和AMD K7及更高版本支持dTLB-loads-misses:u
。
你可以在https://godbolt.org/z/97XkkF找到代码。它需要两个参数:
argv[1]
,指定是刷新指定的4KB页面的所有行还是仅刷新一行。argv[2]
,指定是否使用clflush
或clflushopt
。测试很简单。它分配一个4KB的页面,并使用加载指令多次访问同一位置。但是,在每次访问之前,按照argv[1]
和argv[2]
的规定执行缓存刷新操作。如果刷新导致TLB条目被驱逐,那么将发生dTLB-loads-misses:u
事件。如果事件数量接近于负载数量,那么我们可能会怀疑刷新对TLB有影响。
使用以下命令编译并运行代码:
gcc -mclflushopt -O3 main.c
perf stat -e dTLB-loads-misses:u ./a.out wholePage opt
其中wholePage
和opt
可以是0或1.所以有4个案例要测试。
我已经对SNB,IVB,HSW,BDW和CFL进行了测试。在所有处理器和所有情况下,事件的数量可以忽略不计。您可以在其他处理器上运行测试。
我还设法通过在循环中调用WBINVD
来运行ioctl
测试,以便在内核模块中执行指令。我测量过dTLB-loads-misses:u
,iTLB-loads-misses:u
和icache_64b.iftag_miss:u
。所有这些都是非常微不足道的(低于100万载荷指令的0.004%)。这意味着WBINVD
不会刷新DTLB,ITLB或指令缓存。它只刷新数据缓存。