我发现一个x86 CPU有以下内存屏障指令:mfence、lfence和sfence中的一个或多个。x86 CPU只有这三条内存屏障指令,还是还有更多?
mfence
lfence
sfence
ccrfmcuu1#
sfence(SSE 1)与mfence/lfence(SSE 2)是唯一根据其内存栅栏/屏障功能命名的指令。除非使用NT存储与/或WC内存(以及从WC加载NT),否则内存排序只需要mfence。
(Note Intel CPU上的lfence也是乱序执行的障碍,因此它可以串行化rdtsc,并且对于Spectre缓解以防止推测性执行非常有用。(4/周期吞吐量)。该MSR是通过Spectre-mitigation微码更新引入的,通常由更新的内核设置。)
rdtsc
lock艾德指令(如lock add [mem], eax)也是完全内存屏障. Does lock xchg have the same behavior as mfence?。(尽管可能不如mfence在从WC内存排序NT加载时那样强大:xchg [mem], reg有一个隐含的lock前缀,所以它也是一个障碍。
lock
lock add [mem], eax
xchg [mem], reg
在我对Skylake的测试中,lock艾德指令使用代码https://godbolt.org/g/7Q9xgz对NT存储和常规存储进行块重排序。xchg似乎是执行seq-cst存储的好方法,特别是在Skylake等Intel硬件上,mfence还阻止纯ALU指令的乱序执行,如lfence:请参阅此答案的底部。AMD还建议使用xchg或其他锁定指令,而不是mfence。(mfence在AMD手册中被记录为在AMD上进行序列化,因此它总是会受到阻塞OoO exec的惩罚)。对于不带SSE的32位目标上的顺序一致性存储或完全屏障,编译器通常使用**lock or [esp], 0**或其他无操作锁定指令 * 仅 * 用于内存屏障效应。That's what g++7.3 -O3 -m32 -mno-sse does用于std::atomic_thread_fence(std::memory_order_seq_cst);。
xchg
lock or [esp], 0
g++7.3 -O3 -m32 -mno-sse
std::atomic_thread_fence(std::memory_order_seq_cst);
**但无论如何,无论是mfence还是lock艾德insn都没有 * 在架构上 * 定义为在英特尔上进行序列化,**无论在某些CPU上的实现细节如何。完全序列化指令(如cpuid)也是完全内存屏障,不仅会清空存储缓冲区,还会刷新管道。Does lock xchg have the same behavior as mfence?的相关引用摘自英特尔手册。
cpuid
在英特尔处理器上,以下是体系结构上的序列化指令(来自:https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-273.html)的数据:
*特权序列化指令- INVD、INVEPT、INVLPG、INVVPID、LGDT、LIDT、LLDT、LTR、MOV到控制寄存器、MOV(到调试寄存器)、WBINVD和WRMSR。
例外:MOV CR8未序列化。WRMSR至IA32_TSC_DEADLINE MSR(MSR索引6 E0 H)和X2 APIC MSR(MSR索引802 H至83 FH)未序列化。
MOV CR8
WRMSR
*非特权序列化指令- CPUID,IRET 1与RSM
在AMD处理器上,以下是体系结构序列化指令:
*特权序列化指令- INVD,INVLPG,LGDT,LIDT,LLDT,LTR,MOV到控制寄存器,MOV(到调试寄存器),WBINVD,WRMSR与SWAPGS.*非特权序列化指令- MFENCE,CPUID,IRET与RSM
术语“[完全]序列化指令”在Intel处理器上的含义与在AMD处理器上的含义完全相同,但有一点不同:来自CLFLUSH(而不是CLFLUSHOPT)的高速缓存线刷新操作相对于AMD处理器上的较晚指令仅按MFENCE排序。in/out(以及它们的字符串复制版本ins和outs)是完全的内存屏障,也是部分串行化的(像lfence)。文档说它们会将下一条指令的执行延迟到I/O事务的“数据阶段”之后。脚注:(1)根据BJ 137(桑迪布里奇)、HSD 152(哈斯韦尔)、BDM 103(布罗德韦尔):问题:通过从嵌套责任返回而导致责任切换得IRET指令不序列化处理器(与《软件开发人员手册》第3卷中标题为“序列化指令”得部分相反).含义:在任务切换期间依赖于IRET序列化属性的软件可能无法按预期运行。英特尔尚未发现此错误会影响任何商用软件的运行。解决方法:未确定。如果需要序列化,软件可以在IRET指令之前立即执行MFENCE指令。
CLFLUSH
CLFLUSHOPT
MFENCE
in
out
ins
outs
dohp0rv52#
您是对的,x86 CPU上仅有的三个内存屏障函数是:
LFENCE SFENCE MFENCE
2条答案
按热度按时间ccrfmcuu1#
sfence
(SSE 1)与mfence
/lfence
(SSE 2)是唯一根据其内存栅栏/屏障功能命名的指令。除非使用NT存储与/或WC内存(以及从WC加载NT),否则内存排序只需要mfence
。(Note Intel CPU上的
lfence
也是乱序执行的障碍,因此它可以串行化rdtsc
,并且对于Spectre缓解以防止推测性执行非常有用。(4/周期吞吐量)。该MSR是通过Spectre-mitigation微码更新引入的,通常由更新的内核设置。)lock
艾德指令(如lock add [mem], eax
)也是完全内存屏障. Does lock xchg have the same behavior as mfence?。(尽管可能不如mfence
在从WC内存排序NT加载时那样强大:xchg [mem], reg
有一个隐含的lock
前缀,所以它也是一个障碍。在我对Skylake的测试中,
lock
艾德指令使用代码https://godbolt.org/g/7Q9xgz对NT存储和常规存储进行块重排序。xchg
似乎是执行seq-cst存储的好方法,特别是在Skylake等Intel硬件上,mfence
还阻止纯ALU指令的乱序执行,如lfence
:请参阅此答案的底部。AMD还建议使用
xchg
或其他锁定指令,而不是mfence
。(mfence
在AMD手册中被记录为在AMD上进行序列化,因此它总是会受到阻塞OoO exec的惩罚)。对于不带SSE的32位目标上的顺序一致性存储或完全屏障,编译器通常使用**
lock or [esp], 0
**或其他无操作锁定指令 * 仅 * 用于内存屏障效应。That's whatg++7.3 -O3 -m32 -mno-sse
does用于std::atomic_thread_fence(std::memory_order_seq_cst);
。**但无论如何,无论是
mfence
还是lock
艾德insn都没有 * 在架构上 * 定义为在英特尔上进行序列化,**无论在某些CPU上的实现细节如何。完全序列化指令(如
cpuid
)也是完全内存屏障,不仅会清空存储缓冲区,还会刷新管道。Does lock xchg have the same behavior as mfence?的相关引用摘自英特尔手册。在英特尔处理器上,以下是体系结构上的序列化指令(来自:https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-273.html)的数据:
*特权序列化指令- INVD、INVEPT、INVLPG、INVVPID、LGDT、LIDT、LLDT、LTR、MOV到控制寄存器、MOV(到调试寄存器)、WBINVD和WRMSR。
例外:
MOV CR8
未序列化。WRMSR
至IA32_TSC_DEADLINE MSR(MSR索引6 E0 H)和X2 APIC MSR(MSR索引802 H至83 FH)未序列化。*非特权序列化指令- CPUID,IRET 1与RSM
在AMD处理器上,以下是体系结构序列化指令:
*特权序列化指令- INVD,INVLPG,LGDT,LIDT,LLDT,LTR,MOV到控制寄存器,MOV(到调试寄存器),WBINVD,WRMSR与SWAPGS.
*非特权序列化指令- MFENCE,CPUID,IRET与RSM
术语“[完全]序列化指令”在Intel处理器上的含义与在AMD处理器上的含义完全相同,但有一点不同:来自
CLFLUSH
(而不是CLFLUSHOPT
)的高速缓存线刷新操作相对于AMD处理器上的较晚指令仅按MFENCE
排序。in
/out
(以及它们的字符串复制版本ins
和outs
)是完全的内存屏障,也是部分串行化的(像lfence
)。文档说它们会将下一条指令的执行延迟到I/O事务的“数据阶段”之后。脚注:
(1)根据BJ 137(桑迪布里奇)、HSD 152(哈斯韦尔)、BDM 103(布罗德韦尔):
问题:通过从嵌套责任返回而导致责任切换得IRET指令不序列化处理器(与《软件开发人员手册》第3卷中标题为“序列化指令”得部分相反).
含义:在任务切换期间依赖于IRET序列化属性的软件可能无法按预期运行。英特尔尚未发现此错误会影响任何商用软件的运行。
解决方法:未确定。如果需要序列化,软件可以在IRET指令之前立即执行MFENCE指令。
dohp0rv52#
您是对的,x86 CPU上仅有的三个内存屏障函数是: