clflush是否还会删除TLB条目?

时间:2019-01-15 17:29:53

标签: performance caching x86 cpu-cache

clflush 1 是否还会刷新关联的TLB条目?由于clflush以高速缓存行的粒度运行,而TLB条目以(更大)的页面粒度存在,所以我不做这样的假设,但我准备感到惊讶。


1 ...或clflushopt,尽管人们会合理地假设他们的行为是相同的。

2 个答案:

答案 0 :(得分:3)

我认为不存在是安全的;将invlpg烘焙到clflush中听起来像是一个疯狂的设计决策,我认为没有人会做出。您通常希望使页面中的多行无效。也没有明显的好处。刷新TLB并不会更容易实现数据缓存刷新。

即使只是删除最终的TLB条目(不必使任何页面目录缓存无效)也比invlpg弱,但仍然没有道理。

所有现代x86都使用带有物理索引/标记的缓存,而不是虚拟的。 (VIPT L1d缓存实际上是具有索引的自由转换的PIPT,因为它是从页面内偏移量的一部分地址位中获取的。)即使缓存是虚拟的,使TLB条目无效也需要使虚拟缓存无效,而不是相反。


根据IACA,clflush在HSW-SKL上仅为2 oups,而在NHM-IVB上仅为4 oups(包括微融合)。因此,它甚至都没有在Intel上进行微编码。

IACA不对invlpg进行建模,但是我认为它的作用更大。 (而且它有特权,因此进行测试并非易事。)极有可能在HSW之前的那些额外操作会导致TLB失效。

我没有有关AMD的任何信息。


invlpg享有特权这一事实是另一个期望clflush不是它的超集的原因。 clflush没有特权。大概是出于性能原因,invlpg仅限于环0。

但是invlpg不会出现页面错误,因此用户空间可以使用它来使内核TLB条目无效,从而延迟实时进程和中断处理程序。 (wbinvd获得特权的原因类似:它非常慢,我认为不可中断。)clflush确实在非法地址上出错,因此不会打开该拒绝服务漏洞。不过,您可以clflush共享的VDSO页面。

除非出于某种原因,CPU会想要invlpg暴露在用户空间中(通过将其烘焙到clflush中),否则我真的不明白为什么任何供应商都会这样做。


在未来的计算中使用非易失性DIMM时,将来任何CPU都不可能非常慢地循环执行clflush的一系列内存。您可能希望大多数使用内存映射NV存储的软件都使用clflushopt,但我希望CPU供应商也能使clflush尽可能快。

答案 1 :(得分:2)

可以使用dTLB-loads-misses:u性能事件来确定clflush是否刷新映射指定缓存行的TLB条目。当所有TLB级别的负载均未命中并导致页面遍历时,将发生此事件。与dTLB-stores-misses:u相比,它也得到了更广泛的支持。特别是,dTLB-loads-misses:u在Intel P4和更高版本(Goldmont除外)以及AMD K7和更高版本上受支持。

您可以在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

其中wholePageopt可以为0或1。因此,有4种情况需要测试。

我已经在SNB,IVB,HSW,BDW和CFL上进行了测试。在所有处理器上以及所有情况下,事件的数量都可以忽略不计。您可以在其他处理器上运行测试。


我还设法通过在循环中调用WBINVD到内核模块以在内核模式下执行指令来对ioctl进行测试。我测量了dTLB-loads-misses:uiTLB-loads-misses:uicache_64b.iftag_miss:u。所有这些都可以忽略不计(在100万条装载指令的0.004%以下)。这意味着WBINVD不会刷新DTLB,ITLB或指令缓存。它只会刷新数据缓存。