【问题标题】:Memory Protection Keys Memory Reordering内存保护键 内存重新排序
【发布时间】:2019-01-01 14:02:32
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您可能想查看pkey_mprotect() 的源代码,看看他们是否采取了任何措施来保护它。
  • @Barmar pkey_mprotect 不使用 wrpkru,它修改 pte 以设置 pkey 编号,然后在缓存时使 TLB 条目无效/关闭。
  • 我误读了this page。它说pkey_set()wrpkru 的包装器。
  • @RossRidge:我假设 OP 建议 LFENCE 阻止 CPU 管道中的乱序执行,这是lfence 的保证(仅限英特尔)效果:(Are loads and stores the only instructions that gets reordered? ),而不是因为它的(不存在的)内存排序效果。 (即仅与来自 WC 内存的 MOVNTDQA 负载与其他负载重新排序相关,没人关心。)
  • @PeterCordes 好吧,这个问题确实提到了内存排序几次。正如您的回答所解释的那样,这里的问题是内存排序是一条红鲱鱼。

标签: linux performance assembly x86 memory-barriers


【解决方案1】:

我假设 CPU 会像往常一样保留按程序顺序运行单个线程的错觉。这是乱序执行的基本规则。wrpkru 之前的访问是用旧的 PKRU 完成的,之后的访问是用新的 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?.

这个答案的前面部分是关于在装配中订购。

【讨论】:

  • 英特尔以防止数据加载和存储围绕它重新排序的方式实现了WRPKRU(如MFENCE)。然而,由于 Spectre 1.1 的漏洞(推测缓冲区溢出),WRPKRU 必须执行LFENCE,而不仅仅是MFENCE。但是 AFAIK,英特尔尚未发布补丁。所以 OP 是正确的,它需要具有与LFENCE 相同的序列化属性。但不幸的是,它在当前的处理器上不能这样工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 2021-12-02
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
相关资源
最近更新 更多