Как физический адрес отображается в строках и банках DRAM

в 10:23, , рубрики: dimm, Ivy Bridge, ram, rowhammer, Sandy Bridge, адресное пространство, информационная безопасность, Компьютерное железо, ОЗУ, отображение адресов, Процессоры

В прошлой статье мы обсуждали, как процессоры Intel Sandy Bridge отображают физические адреса в кэше L3.

Теперь я расскажу, как контроллеры памяти этих процессоров сопоставляют физические адреса с местоположением в DRAM — в частности, с номерами строк, банков и столбцов в модулях DRAM. Назовём это отображением адресов DRAM. Я использую одну тестовую машину в качестве примера.

Мотивация: баг Rowhammer

Меня интересует отображение адресов DRAM, поскольку оно относится к багу Rowhammer.

Rowhammer — проблема с некоторыми модулями DRAM, когда определённые самые плохие модели доступа к памяти могут привести к повреждению памяти. В этих DRAM многократная активация строки памяти («забивание строки») вызывает электрические помехи, меняющие биты в уязвимых ячейках соседних строк.

Эти повторяющиеся активации строк могут быть вызваны многократным доступом к паре адресов DRAM, которые находятся в разных строках одного банка DRAM. Знание отображения адресов DRAM полезно, поскольку оно указывает, какие пары адресов удовлетворяют этому свойству «один банк, разные строки» (same bank, different row; SBDR).

Угадывание и проверка отображения адресов

Для теста у меня есть машина с модулями DRAM, уязвимыми к багу Rowhammer. Запуск rowhammer_test на этой машине демонстрирует смену битов.

Я хотел бы знать схему отображения адресов DRAM для этой машины, но она не задокументирована публично: здесь процессор Sandy Bridge, но Intel не документирует отображение адресов, используемое контроллерами памяти этих процессоров.

На самом деле тесту rowhammer_test не нужно знать пары адресов SBDR. Он просто несколько раз пытается забивать случайно выбранные пары адресов. Обычно 1/8 или 1/16 из них оказываются парами SBDR, потому что в нашей машине 8 банков в каждом DIMM (и 16 банков в итоге). Таким образом, нам не нужно знать отображение адресов DRAM, чтобы вызвать смену битов в памяти, но такое знание поможет проводить тест более целенаправленно.

Хотя отображение адресов не задокументировано, я обнаружил, что могу сделать обоснованное предположение о нём на основе геометрии DRAM, а затем проверить предположение на основе физических адресов, о которых сообщает rowhammer_test. Тест сообщает физические адреса, где происходят смены битов («жертвы») и пары физических адресов, которые производят эти смены («агрессоры»). Поскольку эти пары должны быть парами SBDR, мы можем проверить гипотетическое сопоставление адресов с этими эмпирическими данными.

Геометрия памяти

Первый шаг: проверить, сколько DIMM установлено в машине и как они внутренне организованы.

Я могу запросить информацию о DIMM с помощью инструмента decode-dimms в Linux (в Ubuntu он находится в пакете I2C-tools). Этот инструмент декодирует метаданные SPD (Serial Presence Detect) в DIMM.

На моей тестовой машине два четырёхгигабайтных SO-DIMM, что даёт 8 ГБ памяти.

Инструмент decode-dimms сообщает следующую информацию для каждого из модулей:

Size                                            4096 MB
Banks x Rows x Columns x Bits                   8 x 15 x 10 x 64
Ranks                                           2

Это означает, что у обоих DIMM:

  • В каждом банке 2^15 строк (32768 строк).
  • Каждая строка содержит 2^10 * 64 бит = 2^16 бит = 2^13 байт = 8 Кбайт.

У каждого DIMM есть 2 ранга и 8 банков. Перекрёстная проверка ёмкости модуля DIMM даёт тот размер, какой и ожидалось:

8 Кбайт в строке * 32768 строк * 2 ранга * 8 банков = 4096 МБ = 4 ГБ

Отображение адресов DRAM

На моём тестовом компьютере биты физических адресов используются следующим образом:

  • Биты 0-5: это младшие 6 битов байтового индекса в строке (т.е. 6-битный индекс для 64-байтовой кэш-линии).
  • Бит 6: это 1-битный номер канала, который выбирает между двумя DIMM.
  • Биты 7-13: верхние 7 битов индекса в строке (т.е. верхние биты номера столбца).
  • Биты 14-16: XOR с нижними 3 битами номера строки, что выдаёт 3-битный номер банка.
  • Бит 17: 1-битный номер ранга, который выбирает между двумя рангами DIMM (которые обычно являются двумя сторонами микросхемы DIMM).
  • Биты 18-32: 15-битный номер строки.
  • Биты 33+: их можно установить, потому что физическая память начинается с физических адресов больше 0.

Почему такое отображение?

Данное отображение сходится с результатами rowhammer_test (см. ниже), но мы также можем объяснить, что адресные биты сопоставляются таким образом, чтобы обеспечить хорошую производительность для типичных шаблонов доступа к памяти, таких как последовательный доступ (sequential access) и ступенчатый или шаговый доступ (strided access):

  • Параллелизм каналов. Размещение номера канала в бите 6 означает, что кэш-линии станут чередоваться между двумя каналами (т.е. двумя модулями DIMM), к которым можно получить доступ параллельно. Это означает, что если мы обращаемся к адресам последовательно, нагрузка будет распределена по двум каналам.

    Кстати, Ivy Bridge (преемник Sandy Bridge), по-видимому, усложняет отображение номера канала. В презентации Intel упоминается «хэширование каналов» и говорится, что это «позволяет выбирать канал на основе нескольких адресных битов. Исторически оно равнялось “A[6]”. Так обеспечивается более равномерное распределение доступа к памяти по каналам».

  • Буксование банка: в целом, расположение номеров колонок, банков и строк должно минимизировать частую смену активных строк банка (bank thrashing).

    Небольшое введение: модули DRAM организованы в банки, которые, в свою очередь, организованы в строки. У каждого банка есть «текущая активированная строка»: её содержимое копируется в буфер строк, который действует как кэш, к которому можно быстро получить доступ. Доступ к другой строке занимает больше времени, потому что её сначала нужно активировать. Итак, при отображении адресов DRAM пары SBDR разносятся как можно дальше в физическом адресном пространстве.

    Чеканка строк (row hammering) — частный случай буксования банка, когда попеременно активируются две конкретные строки (возможно, специально).

  • Параллелизм банков: доступ к банкам может осуществляться параллельно (хотя и в меньшей степени, чем к каналам), поэтому номер банка изменяется перед номером строки по мере увеличения адреса.
  • Схема XOR: XOR'инг младших бит номера строки в номер банка — это трюк, чтобы избежать буксования банка при доступе к массивам большими шагами. Например, в приведённом выше отображении XOR'инг заставляет адреса X и X+256k разместиться в разных банках, не образуя пару SBDR.

    Схемы XOR'инга для банка/строки описаны в различной литературе, например:

Cверка c выдачей rowhammer_test

Работа rowhammer_test_ext (расширенная версия rowhammer_test) на тестовой машине в течение 6 часов выявила повторяемую смену битов в 22 местах. (см. исходные данные и код анализа).

Тест чеканки строк генерирует наборы из трёх адресов (A1, A2, V):

  • V — адрес жертвы, где мы видим смену бита.
  • А1 и А2 — адреса агрессора, которые мы чеканим.
  • Сортируем A1 и A2 так, чтобы A1 был ближе к V, чем A2. Мы предварительно предполагаем, что более близкий адрес, A1 фактически вызывает смену бита (хотя это не обязательно было бы верно, если бы использовалось более сложное отображение адресов DRAM).

Для всех этих результатов мы ожидаем выполнения трёх свойств:

  • Строка: номера строк A1 и V должны отличаться на 1, т.е. они должны быть в соседних строках. (у A2 может быть любой номер строки).

    Это свойство позволяет легко определить, где в физическом адресе находятся нижние биты номера строки.

    Тест показал, что это свойство выполняется для всех результатов, кроме двух. В этих двух результатах номера строк отличаются на 3, а не на 1.

  • Банк: V, A1 и A2 должны иметь одинаковый номер банка. Действительно, это свойство проявилось во всех 22 результатах. Оно сохраняетися только при применении схемы XOR'инга строк/банков.
  • Канал: V, A1 и A2 должны иметь одинаковый номер канала. Это справедливо для всех результатов. Бывает, что у всех результатов channel=0, потому что rowhammer_test выбирает только адреса, выровненные по 4k, и поэтому тестирует только один канал (возможно, это можно считать багом).

Возможные дальнейшие тесты

В будущем можно запустить ещё два эксперимента для проверки, правильно ли отображение адресов DRAM оценивает свойство SBDR:

  • Замер времени: многократный доступ к парам адресов SBDR должен быть медленнее, чем многократный доступ к парам без SBDR, потому что первый вызывает активацию строк, а второй — нет.
  • Исчерпывающее тестирование Rowhammer: как только мы нашли адрес агрессора A1, который вызывает повторяемую смену бита, мы можем проверить это на многих значениях A2. Эффект чеканки (A1, A2) произведёт смену битов только в том случае, если это пара SBDR.

Кроме того, изъятие одного модуля DIMM из системного блока должно изъять бит канала из отображения адресов DRAM и соответственно изменить адреса агрессора и жертвы. Это тоже можно проверить.

Автор: m1rko

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js