【问题标题】:How to use CPUID as a serializing instruction?如何使用 CPUID 作为序列化指令?
【发布时间】:2018-07-08 05:25:10
【问题描述】:

CPUID 可以用作序列化指令,如herehere 所述。在 C++ 中以这种方式使用它的最小/最简单的 asm 语法是什么?

// Is that enough?
// What to do with registers and memory?
// Is volatile necessary?
asm volatile("CPUID":::);

【问题讨论】:

  • 从技术上讲,您根本不能这样做,因为内联汇编是标准 C++ 中不存在的编译器特定的东西。虽然我们可以猜测您最有可能使用哪个编译器,但在询问有关内联汇编的问题时始终包含该信息。还提到目标 ISA 通常是个好主意,即使在这种情况下也可以猜到。
  • 使用内置而不是 asm。 cpuid 覆盖寄存器,至少您需要将 eax,ebx,ecxedx 列为 clobbers。是的,volatile 是必需的。
  • #include <intrin.h> 并使用__cpuid() 函数。
  • 你需要它做什么?
  • 如果需要序列化rdtsc,使用lfence。英特尔保证它可以工作(至少在英特尔 CPU 上)。见stackoverflow.com/questions/38994549/…。 (不过,on AMD it seems you need mfence instead of lfence,所以cpuid 显然更便携)

标签: c++ assembly cpuid


【解决方案1】:

您不使用栅栏操作是否有原因?如果目标是序列化一段代码,你可以这样做

    asm __volatile__ (
" mfence \n"
" lfence \n"
);
Your code
asm __volatile__ (
" mfence \n"
" lfence \n"
);

【讨论】:

  • intel 手册说:“MFENCE 不序列化指令流。”
  • "对在此指令之前发出的所有从内存加载和存储到内存指令执行序列化操作。保证在程序顺序之前的每个内存访问,内存栅栏指令在程序顺序中跟随栅栏的任何内存指令之前是全局可见的。” software.intel.com/sites/landingpage/IntrinsicsGuide/…
  • 是的,但这仅涉及内存操作。 “非特权序列化指令——CPUID、IRET 和 RSM。”和 “以下指令是内存排序指令,而不是序列化指令。这些会耗尽数据内存子系统。它们确实不序列化指令执行流。非特权内存排序指令 -- SFENCE、LFENCE 和 MFENCE。"
  • @Jester: lfence 现在(或将要)正式记录为序列化,多年来这是一个实现细节,但仍然看到一些英特尔文档推荐或至少使用lfence; rdtsc。至少 some 好来自 Spectre...(不过,我不能 100% 确定它的序列化程度与 cpuid 一样强)。但无论如何,mfence 没有在指令流、纸上或实践中序列化是对的。背靠背同时使用lfencemfence 似乎没有用。
  • 更正:lfence 正在序列化指令流,而不刷新存储缓冲区。 lfence; rdtsc 就足够了。这不是像cpuidiret 这样的完整技术意义上的“序列化指令”。 mfence 根据文档在 AMD 上进行序列化,实际上也在 Skylake 等一些 Intel CPU 上进行序列化,可能是修复错误的微码更新增强了它比 Intel 手动保证强得多:Are loads and stores the only instructions that gets reordered?
猜你喜欢
  • 2012-08-26
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
  • 2012-08-17
  • 2021-02-28
  • 2021-07-16
  • 1970-01-01
相关资源
最近更新 更多