Pull to refresh
0
0
Send message
>> Блок TLB не имеет программного (микропрограммного) управления, как обычный кеш. Из него невозможно удалить запись

> Да неужели?

Вперед и с песней — выполнение этой инструкции из user программы запрещено.
Дополнительно — newsroom.intel.com/wp-content/uploads/sites/11/2018/01/Intel-Analysis-of-Speculative-Execution-Side-Channels.pdf, параграф 2.2.1 Bound Check Bypass:

"… method takes advantage of speculative execution after conditional branch instructions"

Intel рекомендует вставлять LFENCE после условного перехода. Что-то не верится в 1.5%, если после каждого перехода будет LFENCE.

Что касается Branch target injection и предлагаемого патч по имени retpoline для этого в LLVM/gcc, то он убивает execution stack protection — запрет на выполнение кода из стэка. Попросту — открывает новые горизонты для хакеров!
Я не делал.

Однако я уже лет 8 работаю в компаниях занимающихся high performance/high bandwidth и разработкой процессоров. Лет 7 назад я ломал голову, почему пара тривиальных процессов, обменивающихся сигналами или просто перекидывающих друг другу 1 байт на 7i core с 4 процессорами/8 thread-ами работает в 5 (ПЯТЬ, Карл!) раз медленнее, чем когда на машине запустить 8 таких пар. Я нашел — при power-saving ядру надо восстанавливать таблицы страниц, при полной загрузке этого power-saving просто нет.

На AMD этого кстати не было.
> А теперь представьте себе: из L0 одного ядра нужно число переправить в L0 другого ядра. Это сотни тактов, и этот эффект больше, чем то, что мы хотим измерять

Это не совсем верное рассуждение:

1. Это по любому не сотни циклов.
2. Применяют хитрости для сокращения времени.
3. Загрузку всегда делают в pipeline к операции. Тут конечно большая наука намешана, чтобы соблюсти когерентность данных.

Но когеретность времени тут не соблюдается. Просто доступ из локального кэша много короче следующего уровня, вот схема опроса счетчика и работает.
> Процессор не исполняет ничего «на всякий случай». Он не пытается «хватать» инструкции «где-то рядом» с потоком исполнения и рандомно их исполнять — это бессмысленно. На некоторых CRAY системах пытались одновременно спекулятивно исполнять команды на обоих ветвях после перехода… идея себя не оправдала.

На CRAY не оправдала, на MIPS например — оправдала. И вы немного не в курсе, почему часто отрабатывают тщательнЕе код, который внутри loop — просто есть такая штука как instruction parsing (особая головная боль для Интела) и branch-table — код внутри короткой петли уже разобран в процессоре на микроинструкции и все возможные операции уже сделаны. Посему можно сделать speculative операцию довольно легко. Но это для low-end процессоров, для high-end надо смотреть в обе стороны условного перехода.

Кстати, далеко вперед обычно не смотрят, просто парсят и запускают операции загрузки из памяти (ну очень уж они долгие, особенно если учесть возможность подкачки TLB из памяти), и (внимание!) — простейшие операции над адресами в случае индексирования и последующей второй загрузки над результирующим адресом. Вот мне кажется, что AMD не делает либо индексирование либо вторую загрузку, которая зависит от первой. Посему они такие гордые сегодня.

> Если загрузка после проверки «спекулятивно сработала» (а потом не понадобилась) — то это значит, что предсказатель переходов сработал неверно.

Это важно только в случае узкого канала в память. Если у вас хороший кэш, то большинство неверных предсказаний окончится в кэше и чуть потратит рессурсы LFU-или-как-его-там, которых все равно делают в расчете на speculative.

> А вы предлагаете на это событие, случающееся с ничтожной вероятностью, полагаться.

Это как в анекдоте — 50-на-50. Маленьких циклов, которые полностью оседают в процессоре — мало, большая часть циклов просто не обнаруживается процессором. Так что с этой точки зрения выгодно отрабатывать чуть-чуть вперед по обе стороны условного перехода.
Это кранты, это ЕЩЕ ОДИН баг. Поставить внутри guest VM последовательность спекулятивной загрузки карты памяти root-а (!) + чтения слова из этой памяти ==> в TLB будет лежать доступ в память root-а из guest-а.

Если это еще работает (все-таки 7 лет прошло), то весь облачный сервис накрылся медным тазом, сбацать дырокол для тех процессоров — нефиг делать. Ох, заставят всех обновить процессоры, заставят.
Так такой «нехороший код» гораздо чаще в ядре или программе случается! И защититься от него много сложнее через LLVM/gcc.

Но почитав о чем народ талдычит, складывается впечатление, что якобы Интел не делает speculative пока по коду не проползет несколько раз циклом(!) Очень странная мысль, я сидел на одном семинаре где они хвастались, что они просматривают вперед аж на 3 условных перехода длинным pipeline — нахрена тогда им это делать то?

Или это конкретный процессор такой, а народ и не знает?

Это насчет того, сработает нехороший код или нет.
Можно, но потеря производительности будет не 30%, а в разы. Типа возврат обратно к старому доброму 486 или в крайнем случае — старому Atom (до 2013г).
Это для Spectre.
> Но почему-то народное внимание акцентировано на интелах и meltdown, а амд в головах людей «надежны».

Meltdown легко сделать, даже в JS. И он не работает на AMD.

Spectre значительно труднее сделать, по крайней мере Гуглу пришлось воспользоваться eBPF, который по умолчанию выключен.
Есть архитектуры, где проверка доступа происходит ДО запуска чтения. MIPS например (Байкал-T1). И в AMD похоже тоже.
«Чужим процессом» для Spectre может быть само ядро, а функция-читалка — eBFP. Но может быть и другая последовательность в ядре.
Не требует. В цепочку спекулятивных выполнений можно поставить операцию типа address = вытащенный байт * адрес массива. Далее — опредилить, какая строчка массива была вытащена в кэш, например чтением всех строк и измерением времени. Все, значение выдернутого спекулятивно байта известно.
Фиксом в LLVM/gcc можно попробовать решить проблему Spectre, Meltdown же вообще не трогает ядро и качество кода ядра не влияет на него. Кроме как временное отключение kernel maps при выходе в моду пользователя, что и делает вышедший патч.
Вообще-то я не понимаю, почему они сосредоточились только на переходе по регистру. Простой условный переход, условие которого вычисляется в зависимости от неизвестного в данный момент значения может скорее всего вызвать выдергивание кэш строки по известному адресу в команде загрузки сразу за этим переходом.

Я не силен в x86 ассемблере (забыл его), но что-то типа

— вычисление условия А, например по слову из памяти или как последнее в цепочке вычислений
— условный переход по условию А, который всегда выполняется в нормальной ситуации
— загрузка слова по регистру, который известен задолго до и который содержит «нехороший» адрес.

В нормальном выполнении загрузка никогда не срабатывает, так как условный переход идет нафиг всегда. При спекулятивном выполнении есть большой соблазн запустить эту загрузку на всякий случай заранее, хотя в момент запуска еще не известно значение условия А. Приплыли.
> К тому же не всякому хакеру удастся создать эксплоит под эту язвимость.

Достаточно одного, а он точно найдется.
Этот патч по-видимому просто переключает карту памяти ядра каждый раз при входе в ядро и выходе, тогда meltdown не работает.

Но проблема в том, что нужно еще и чистить кэш таблиц страниц, и они должны каждый раз подкачиваться обратно. Вот и греется.
Не, это микроархитектурная ляпа.

Можно сбрасывать кэш (весь!) и тогда ни meltdown, ни spectre, но тут потеря будет В РАЗЫ.
Если биткоин майнить, то потеря будет незначительной.

Если же делать ежедневные операции с диском или локальной сетью, которые и так занимали заметное время, то просадка будет значительна.
Что-то табличка враная — AMD говорит, что Variant 3 (который и есть meltdown) не работает на AMD из-за другой архитектуры:

«Variant Three Rogue Data Cache Load Zero AMD vulnerability due to AMD architecture differences.»

Да и Гуглы не смогли его там запустить.

А в табличке там полно AMD…

Information

Rating
Does not participate
Registered
Activity