LFENCE是否在AMD处理器上序列化?

时间:2018-08-14 15:26:00

标签: x86 intel cpu-architecture amd memory-barriers

在最近的Intel ISA文档中,lfence指令已被定义为序列化指令流(以防止在指令流中无序执行)。特别是,指令的description包含以下行:

  

具体来说,只有在本地完成所有先前的指令后,才会执行LFENCE,直到LFENCE完成为止,之后的指令才开始执行。

请注意,这不仅适用于 all 指令,而且不仅适用于内存加载指令,还使lfence 更多,而不仅仅是内存排序规则。

尽管这现在出现在ISA文档中,但尚不清楚它是否是“体系结构”的,即所有x86实现是否都遵循它,或者它是否特定于Intel。特别是, AMD处理器还将lfence视为序列化指令流吗?

2 个答案:

答案 0 :(得分:4)

有一个MSR可以配置该行为:

  

描述:在处理器中设置一个MSR,以便LFENCE是一个调度序列化指令,然后   在代码流中使用LFENCE来序列化分派(LFENCE比RDTSCP快,后者也是分派的   序列化)。可以通过设置MSR C001_1029 [1] = 1来启用这种LFENCE模式。

     

效果:当MSR位置1时遇到LFENCE时,分派将停止,直到LFENCE   指令成为机器中最早的指令。

     

适用性:所有AMD系列10h / 12h / 14h / 15h / 16h / 17h处理器均支持此MSR。 LFENCE支持是   由CPUID function1 EDX位26 SSE2指示。 AMD系列0Fh / 11h处理器支持LFENCE序列化   始终但不支持此MSR。 AMD计划支持此MSR,并在将来使用此位   处理器。

source

答案 1 :(得分:3)

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的行为保持与英特尔处理器的兼容性。

fence指令和序列化指令以及具有序列化属性的指令的订购规则有例外。这些例外在Intel和AMD处理器之间略有不同。我现在可以想到的一个示例是CLFLUSH指令。因此,当AMD和Intel谈论具有序列化属性的指令时,它们的意思稍有不同。

我不清楚的一件事是harlod的答案的引言的以下部分:

  

AMD系列0Fh / 11h处理器始终支持LFENCE,但始终进行序列化   不支持此MSR。

该语句含糊不清,因为它没有明确说明在AMD系列0Fh和11h上的LFENCE是完全序列化(在AMD术语中)还是调度序列化(在AMD术语中)。为了安全起见,应将其解释为仅调度序列化。特定于AMD系列的手册没有提到LFENCE或MSR C001_1029。


Linux内核已更改为在2018年1月8日(AMD文档发布前16天)使用AMD处理器上的LFENCE的序列化属性。更改包括两个提交12。定义了以下宏:

+#define MSR_F10H_DECFG         0xc0011029
+#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT    1

第一个宏指定MSR地址,第二个宏指定偏移量。 init_amd中添加了以下代码(有些注释是我的):

/* 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);
    }
}

AMD在该文档中说了以下内容:

  

AMD计划为此MSR提供支持,并在将来为所有用户提供对该位的访问   处理器。

这意味着MSR在AMD处理器上是建筑