内存保护键内存重新排序

时间:2018-07-24 20:44:00

标签: linux performance assembly x86 memory-barriers

阅读有关内存保护密钥(MPK)的英特尔SDM并不建议将wrpkru指令视为序列化或隐式强制执行内存排序。

首先,如果它不执行某种排序是令人惊讶的,因为人们会怀疑程序员不希望乱序执行wrpkru周围的内存访问。

第二,这是否意味着wrpkru需要被lfence包围?

Linuxglibc在写入后不使用任何类型的防护。但这不应该包含在SDM中吗?

1 个答案:

答案 0 :(得分:2)

我假设CPU像往常一样保留了以程序顺序运行单个线程的错觉。那是无序执行的基本规则。使用旧的PKRU完成wrpkru之前的访问,使用新的PKRU完成之后的访问。

就像修改MXCSR如何影响以后的FP指令,而不影响早期的指令一样,或者修改段寄存器如何影响以后的但不更早的加载/存储。

是否要重命名PKRU,MXCSR或段寄存器取决于实现。如果未重命名PKRU,则它必须先完成所有待处理的加载/存储,然后再更改PKRU并允许以后的加载/存储执行。 (也就是说,wrpkru的微代码可以包括lfence的微指令,如果这样做的话。)

所有内存访问都依赖于最后一条wrpkru指令,最后一次写入相关段寄存器,最后一次写入cr3(顶层页表)以及特权级别的最新更改(syscall / iret /其他)。同样,在该位置的最后一家商店,您也不需要围栏就可以看到自己最近的商店。由CPU架构师来构建可以在保持程序顺序错觉的同时快速运行的硬件。

例如至少从Core2起,Intel CPU已重命名了x87 FP控制字,因此通过将x87舍入模式更改为截断然后返回最近的值来实现(int)fp_var的旧二进制文件不会序列化FPU。根据Agner Fog的测试,某些CPU确实重命名了段寄存器,但是我的测试表明Skylake没有:Is a mov to a segmentation register slower than a mov to a general purpose register?


我对MPK并不熟悉,但是为什么只要它们都使用正确的PKRU值,并且不违反x86的任何正常内存顺序,内存访问就会出现乱序的问题规则?

(其他线程只允许对StoreLoad重新排序。在内部,CPU可以比“应有”执行更早的加载,但是请确保在体系结构允许的点之前没有使高速缓存行无效装载。  这就是内存顺序缓冲区的作用。)


在C / C ++ 中,您当然需要某种方式来阻止围绕包装函数的访问在编译时重新排序。通常,非内联函数调用就足够了,例如pthread_mutex_lock()How does a mutex lock and unlock functions prevents CPU reordering?

此答案的较早部分是关于组装中的订购。