内存保护密钥内存重新排序



阅读英特尔关于内存保护密钥(MPK(的SDM并不意味着wrpkru指令是串行化的,也不意味着隐含地强制执行内存顺序。

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

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

Linux和glibc在编写之后不使用任何围栏。但这不应该包括在SDM中吗?

我假设CPU一如既往地保留了按程序顺序运行单个线程的幻想。这是无序执行的基本规则wrpkru之前的访问使用旧的PKRU,之后的访问使用新的PKRU。

就像修改MXCSR会影响以后的FP指令但不会影响以前的指令,或者修改段寄存器会影响以后但不会影响前面的加载/存储一样。

这取决于实现是否要重命名PKRU、MXCSR或段寄存器。如果它不重命名PKRU,那么在更改PKRU并允许以后的加载/存储执行之前,它必须完成所有挂起的加载/保存。(即,wrpkru的微码可以包括lfence的uop,如果它是这样实现的话。(

所有存储器访问都依赖于最后一条wrpkru指令,以及对相关段寄存器的最后一次写入、对cr3(顶级页表(的最后一次写入和权限级别的最后更改(syscall/iret/whatever(。同样是在最后一家到那个位置的商店,你永远不需要围栏就能看到你自己最近的商店。这取决于CPU架构师来构建快速运行的硬件,同时保留程序顺序的假象。

例如,Intel CPU,因为至少Core2已经重命名了x87 FP控制字,所以通过将x87舍入模式更改为截断然后返回到最近值来实现(int)fp_var的旧二进制文件不会串行化FPU。根据Agner Fog的测试,一些CPU确实重命名了分段寄存器,但我的测试表明Skylake没有:mov到分段寄存器的速度比mov到通用寄存器的速度慢吗?。


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

(只有StoreLoad重新排序才允许其他线程看到。在内部,CPU可以比"预期"更早地执行加载,但要验证缓存行在架构上允许加载之前是否无效。这就是内存顺序缓冲区的作用。(


在C/C++中,您当然需要一些屏障来防止编译时围绕包装函数重新排序访问。通常,非内联函数调用就足够了,比如pthread_mutex_lock()。互斥锁和解锁函数是如何防止CPU重新排序的?。

这个答案的前一部分是关于组装中的排序。

最新更新