Выполняется ли сериализация LFENCE на процессорах AMD?

В последних документах Intel ISA инструкция lfence была определена как сериализация потока инструкций (предотвращение выполнения в нем вне очереди). В частности, описание инструкции включает следующую строку:

В частности, LFENCE не выполняется до тех пор, пока все предыдущие инструкции не будут выполнены локально, и никакая последующая инструкция не начнет выполнение, пока не завершится LFENCE.

Обратите внимание, что это относится ко всем инструкциям, а не только инструкциям по загрузке памяти, что делает lfence больше, чем просто ограничение порядка памяти.

Хотя теперь это появляется в документации ISA, неясно, является ли это «архитектурным», то есть должно соблюдаться всеми реализациями x86, или это специфично для Intel. В частности, обрабатывают ли процессоры AMD lfence как сериализацию потока инструкций?


person BeeOnRope    schedule 14.08.2018    source источник
comment
lfence не сериализируется на Intel. Этот термин имеет техническое значение, которое включает полную очистку буфера хранилища. например cpuid и iret сериализуются. lfence сериализует только поток команд / ядро ​​с нарушением порядка, не весь конвейер, включая буфер хранения. Я обычно говорю, что это частичная сериализация или что-то в этом роде.   -  person Peter Cordes    schedule 15.08.2018
comment
@PeterCordes - обратите внимание, что я написал сериализацию потока инструкций при первом использовании этого термина в вопросе. Я не согласен с тем, что Intel последовательно использует сериализацию в своих руководствах. Они действительно используют сериализацию инструкций довольно последовательно для таких вещей, как cpuid, но они также используют только сериализацию для других вещей, включая вещи, которые не являются инструкции по сериализации. В предложении в разделе lfence непосредственно перед тем, что я процитировал, используется термин операция сериализации по отношению к lfence.   -  person BeeOnRope    schedule 15.08.2018
comment
Я предлагаю удалить общий тег isa и добавить тег memory-barriers, который более уместен.   -  person Hadi Brais    schedule 15.08.2018
comment
@HadiBrais: Я удалил [memory-barriers], потому что нас не интересует эффект барьера памяти lfence. Мы знаем, что это так, и это отвлекающий маневр, который отвлекает от вопроса о его другом эффекте. Однако я не настаиваю на его удалении, если вы и @Bee не находите этот аргумент убедительным.   -  person Peter Cordes    schedule 15.08.2018
comment
@PeterCordes - да, но это просто тег. Меня это не отвлекает. Фактически, я нахожу это, по крайней мере, косвенно релевантным: lfence, по крайней мере, представлен как барьер памяти, а - барьер памяти, и этот побочный эффект блокировки OoO на самом деле является результатом дизайна реализации для его первоначальная основная функция. Если вас интересует lfence как барьер, весьма вероятно, что вы заботитесь о производительности, а также, возможно, заботитесь об этом блокирующем поведении OoO. Примите противоположную позицию: вы упоминаете lfence поведение OoO почти каждый раз, когда инструкция появляется в контексте ...   -  person BeeOnRope    schedule 15.08.2018
comment
... реальных барьеров, так почему же обратное так неверно?   -  person BeeOnRope    schedule 15.08.2018
comment
Это честно. Мой единственный контраргумент заключается в том, что сериализация выполнения - текущая основная цель lfence, поэтому имеет смысл упоминать ее всякий раз, когда она возникает в контексте барьера памяти, но, возможно, не наоборот. т.е. я исправляю заблуждение, что lfence полезен как барьер памяти. Но я думаю, вы правы, возможно, люди, выполняющие поиск по тегам на [x86] [memory-barriers], найдут этот вопрос и чему-нибудь научатся. Мне все еще понравилось редактирование моего заголовка, хотя вы убедили меня в тегах, но это ваш вопрос.   -  person Peter Cordes    schedule 15.08.2018
comment
@PeterCordes - да, поэтому я назвал оригинал основным. Я также попытался поместить пугающие кавычки вокруг основного текста, чтобы отразить, что сегодня наиболее интересное использование не имеет ничего общего с упорядочением памяти, но я был на пределе символов для этого комментария. Дело в том, что этот тег заменяет тег isa, который, я думаю, здесь мало используется и бесполезен.   -  person BeeOnRope    schedule 15.08.2018
comment
Насколько мне известно; В рамках попытки найти решения для всех проблем с призраком инструкция LFENCE (которая раньше должна была быть только барьером загрузки) была переопределена как барьер для спекулятивного выполнения в 2018 году.   -  person Brendan    schedule 19.10.2019
comment
@Brendan - это сработало на 100% только для Intel, так как случилось так, что у него было такое поведение на существующих чипах. Для AMD ситуация более сложная, и lfence может или не может быть сериализован в зависимости от значения, установленного в MSR.   -  person BeeOnRope    schedule 19.10.2019
comment
@BeeOnRope: Я предполагаю, что был бы создан набор обновлений прошивки, чтобы бит был установлен по умолчанию (для тех, кто устанавливает обновления и более новые системы).   -  person Brendan    schedule 19.10.2019
comment
@Brendan - наверное. Интересно, как этот большой был создан давным-давно, еще до того, как мы узнали о Spectre и Meltdown - возможно, по другим причинам.   -  person BeeOnRope    schedule 19.10.2019


Ответы (2)


Существует MSR, который настраивает это поведение:

Описание: установите MSR в процессоре так, чтобы LFENCE была инструкцией по сериализации диспетчеризации, а затем используйте LFENCE в потоках кода для сериализации диспетчеризации (LFENCE быстрее, чем RDTSCP, который также выполняет сериализацию диспетчеризации). Этот режим LFENCE можно включить, установив MSR C001_1029 [1] = 1.

Результат: при обнаружении LFENCE, когда установлен бит MSR, отправка будет остановлена ​​до тех пор, пока инструкция LFENCE не станет самой старой инструкцией в машине.

Применимость: все процессоры семейства AMD 10h / 12h / 14h / 15h / 16h / 17h поддерживают этот MSR. Поддержка LFENCE обозначается битом 26 EDX функции1 CPUID, SSE2. Процессоры AMD семейства 0Fh / 11h всегда поддерживают LFENCE как сериализацию, но не поддерживают этот MSR. AMD планирует поддержку этого MSR и доступ к нему для всех будущих процессоров.

(исходный код)

person Community    schedule 14.08.2018
comment
Этот регистр - недавнее изобретение или он существует и на более старых моделях AMD? Было бы странно, если бы это была старая вещь, поскольку она предположительно была добавлена ​​для смягчения последствий Spectre. - person BeeOnRope; 14.08.2018
comment
@BeeOnRope Семейство AMD 10h - это K10, 0Fh (не имеет MSR, но имеет сериализацию LFENCE) - это K8, AFAIK что-то более старое даже не имело SSE2, поэтому вообще нет LFENCE - person harold; 14.08.2018
comment
А Windows / Linux / * BSD все установили этот MSR с включенной защитой от Spectre? Так что теперь в большинстве случаев безопасно использовать lfence; rdtsc с переносом, если мы можем предположить, что ядра обновлены? - person Peter Cordes; 15.08.2018
comment
(Обратите внимание, что руководство Intel не обещает, что rdtscp останавливает выполнение последующих инструкций, оно только обещает что время не будет измеряться до тех пор, пока не будут выполнены все предыдущие. Так что это бесполезно в начале временного интервала. См. также этот случай, когда lfence;rdtsc;lfence давал более согласованные результаты в нижней части временного интервала. интервал: clflush для недействительности строки кеша с помощью функции C - person Peter Cordes; 15.08.2018

AMD всегда в своем руководстве описывала реализацию LFENCE как инструкцию по сериализации загрузки.

Действует как барьер для принудительного упорядочивания памяти (сериализации) между инструкциями загрузки, предшествующими LFENCE, и инструкциями загрузки, которые следуют за LFENCE.

Первоначальный вариант использования LFENCE заключался в том, чтобы упорядочивать загрузки типа памяти WC. Однако после того, как были обнаружены уязвимости спекулятивного исполнения, AMD в январе 2018 года выпустила документ, озаглавленный «Программные методы управления спекуляциями на процессорах AMD». Это первый и единственный документ, в котором упоминается MSR C001_1029 [1] (другие биты C001_1029 обсуждаются в некоторых документах AMD, но не бит 1). Когда C001_1029 [1] установлен в 1, LFENCE ведет себя как инструкция диспетчеризации сериализации (что дороже, чем просто сериализация загрузки). Поскольку этот MSR доступен на большинстве старых процессоров AMD, кажется, что он почти всегда поддерживался. Может быть, потому что они думали, что в будущем им может понадобиться поддерживать совместимость с процессорами Intel в отношении поведения LFENCE.

Существуют исключения из правил упорядочивания инструкций ограждения и инструкций и инструкций сериализации, которые имеют свойства сериализации. Эти исключения слегка различаются между процессорами Intel и AMD. Примером, о котором я могу думать прямо сейчас, является инструкция CLFLUSH. Итак, AMD и Intel имеют в виду несколько разные вещи, когда говорят об инструкциях со свойствами сериализации.

Одна вещь, которая мне не ясна, - это следующая часть цитаты из ответа Харлода:

Процессоры AMD семейства 0Fh / 11h всегда поддерживают LFENCE как сериализацию, но не поддерживают этот MSR.

Это заявление расплывчато, потому что в нем четко не говорится, является ли LFENCE в семействах AMD 0Fh и 11h полностью сериализоваться (в терминологии AMD) или сериализоваться с отправкой (в терминологии AMD). Но, скорее всего, это только сериализация отправки. В руководствах AMD для конкретных семейств не упоминается LFENCE или MSR C001_1029.


Начиная с ядра Linux v4.15-rc8, используются свойства сериализации LFENCE на процессорах AMD. Изменение состоит из двух коммитов 1 и 2. Были определены следующие макросы:

+#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);
    }
}

Начиная с v5.4-rc1, код проверки записи MSR был удален. Итак, код стал:

    msr_set_bit(MSR_F10H_DECFG,
            MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
    set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);

Причина этого изменения обсуждается в сообщении о фиксации. (Таким образом, в большинстве случаев это не нужно и может не работать.)

В этом документе также говорится:

Все процессоры семейства AMD 10h / 12h / 14h / 15h / 16h / 17h поддерживают этот MSR. Поддержка LFENCE обозначается битом 26 EDX функции1 CPUID, SSE2. Процессоры AMD семейства 0Fh / 11h всегда поддерживают LFENCE как сериализацию, но не поддерживают этот MSR.

Но похоже, что ни одно из руководств AMD еще не обновлено, чтобы упомянуть поддержку C001_1029 [1].

AMD сообщила в этом документе следующее:

AMD планирует поддержку этого MSR и доступ к нему для всех будущих процессоров.

Это означает, что C001_1029 [1] следует рассматривать как архитектурный для будущих процессоров AMD (относительно января 2018 г.).

person Hadi Brais    schedule 14.08.2018