clflush
1 是否还会刷新关联的TLB条目?由于clflush
以高速缓存行的粒度运行,而TLB条目以(更大)的页面粒度存在,所以我不做这样的假设,但我准备感到惊讶。
1 ...或clflushopt
,尽管人们会合理地假设他们的行为是相同的。
答案 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
其中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或指令缓存。它只会刷新数据缓存。