AMD 一直在其手册中将 LFENCE 的实现描述为加载序列化指令
充当强制强内存排序(序列化)的障碍
在 LFENCE 之前的加载指令和加载指令之间
跟随 LFENCE。
LFENCE 的原始用例是订购 WC 内存类型加载。然而,在推测执行漏洞被发现后,AMD 于 2018 年 1 月发布了一份题为“管理 AMD 处理器推测的软件技术”的文件。这是第一个也是唯一一个提到 MSR C001_1029[1] 的文档(在一些 AMD 文档中讨论了 C001_1029 的其他位,但不是第 1 位)。当 C001_1029[1] 设置为 1 时,LFENCE 表现为分派序列化指令(比仅仅加载序列化更昂贵)。由于此 MSR 在大多数较旧的 AMD 处理器上都可用,因此似乎几乎总是支持它。可能是因为他们认为他们将来可能需要在 LFENCE 的行为方面保持与英特尔处理器的兼容性。
栅栏指令和序列化指令以及具有序列化属性的指令的排序规则有例外。这些例外在 Intel 和 AMD 处理器之间略有不同。我现在能想到的一个例子是CLFLUSH 指令。因此,当 AMD 和 Intel 谈论具有序列化属性的指令时,他们的意思略有不同。
我不清楚的一点是 harlod 的回答中引用的以下部分:
AMD 系列 0Fh/11h 处理器始终支持 LFENCE 序列化,但
不支持此 MSR。
此声明含糊不清,因为它没有明确说明 AMD 系列 0Fh 和 11h 上的 LFENCE 是完全序列化(在 AMD 术语中)还是分派序列化(在 AMD 术语中)。但它很可能只是调度序列化。 AMD 系列特定的手册未提及 LFENCE 或 MSR C001_1029。
从 Linux 内核 v4.15-rc8 开始,使用 AMD 处理器上LFENCE 的序列化属性。更改包括两个提交 1 和 2。定义了以下宏:
+#define MSR_F10H_DECFG 0xc0011029
+#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT 1
第一个宏指定 MSR 地址,第二个指定偏移量。在init_amd中添加了以下代码(一些cmets是我的):
/* LFENCE always requires SSE2 */
if (cpu_has(c, X86_FEATURE_XMM2)) {
unsigned long long val;
int ret;
/* The AMD CPU supports LFENCE, but there are three cases to be considered:
* 1- MSR C001_1029[1] must be set to enable the dispatch
* serializing behavior of LFENCE. This can only be done
* if and only if the MSR is supported.
* 2- The MSR is not supported (AMD 0Fh/11h). LFENCE is by
* default at least dispatch serializing. Nothing needs to
* be done.
* 3- The MSR is supported, but we are running under a hypervisor
* that does not support writing that MSR (because perhaps
* the hypervisor has not been updated yet). In this case, resort
* to the slower MFENCE for serializing RDTSC and use a Spectre
* mitigation that does not require LFENCE (i.e., generic retpoline).
/*
* A serializing LFENCE has less overhead than MFENCE, so
* use it for execution serialization. On families which
* don't have that MSR, LFENCE is already serializing.
* msr_set_bit() uses the safe accessors, too, even if the MSR
* is not present.
*/
msr_set_bit(MSR_F10H_DECFG,
MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
/*
* Verify that the MSR write was successful (could be running
* under a hypervisor) and only then assume that LFENCE is
* serializing.
*/
ret = rdmsrl_safe(MSR_F10H_DECFG, &val);
if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) {
/* A serializing LFENCE stops RDTSC speculation */
set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
/* X86_FEATURE_LFENCE_RDTSC is used later to choose a Spectre
mitigation */
} else {
/* MFENCE stops RDTSC speculation */
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
}
}
从v5.4-rc1开始,MSR写入验证码被移除。于是代码变成了:
msr_set_bit(MSR_F10H_DECFG,
MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
commit message 中讨论了此更改背后的原因。 (总而言之,它大多是不需要的,它可能不起作用。)
该文件还说:
所有 AMD 系列 10h/12h/14h/15h/16h/17h 处理器都支持此 MSR。
LFENCE 支持由 CPUID 函数 1 EDX 位 26,SSE2 指示。 AMD
系列 0Fh/11h 处理器始终支持 LFENCE 序列化,但确实如此
不支持这个 MSR。
但似乎尚未更新任何 AMD 手册以提及对 C001_1029[1] 的支持。
AMD 在该文件中表示:
AMD 计划支持此 MSR 并为所有未来访问此位
处理器。
这意味着 C001_1029[1] 应被视为未来 AMD 处理器上的架构(相对于 2018 年 1 月)。