Собираю я свой мини пк для игор.

Dell OptiPlex 9020 SFF, чипсет Q87, Core i3-4150 (i7-4790K в пути).

Ну и по плану закупился дешёвой DDR3 на Али, не брендовой: 4×8 ГБ DDR3-1600 dual-rank. На стоковом Dell BIOS с четырьмя планками система либо вешалась в бесконечный чёрный экран, либо издавала протяжный писк и уходила в перезагрузку. Сначала пошли мысли о том, что мне подсунули явное фуфло, в виде битой банки, ну или таки у меня не работает какой-то слот. Но я быстро потасовал места и планки и понял, что система усмпешно стартует с любыми тремя планкми в любых слотах. Стартует максимум на трех планках по 8gb.

Сверху — китайская с Али, снизу — SK hynix, с которой мне достался комп
Сверху — китайская с Али, снизу — SK hynix, с которой мне достался комп

Думаю ладно, посмотрим ТТХ планок софтом. Вяснилось, что у всех четырёх одинаковый серийник, так что остальным данным в SPD не то чтобы можно доверять. Но от того интерес разобраться, что именно отваливается и почему был только выше.

Пример чтения SPD в Thaiphoon Burner (txt)

Кастомный BIOS

Сначала я узнал о том, что SPD можно перешить, и например попробовать ограничить частоту или тайминги — дать системе возможность стартануть в более щадящем режиме. Все-таки для Haswell 32gb это потолок, а у нас тут не оверклокерская доска. Как ни крути вполне себе офисная рабочая станция, еще и проприетарная, что кстати не дает нам возможности просто поменять частоту памяти в BIOS и уж темболее прошить SPD флешку в RAM.

Чипы памяти и рядом маленькая микросхема SPD — та самая I2C-флешка
Чипы памяти и рядом маленькая микросхема SPD — та самая I2C-флешка

В какой-то момент я подумал о том, что возможно есть какие-то хаки bios, ведь патч для загрузки с NVME дисков есть. Сначала я отбросил мысль. Но когда все-таки поискал, узнал про libreboot. Это опенсорсная замена штатному bios, которая и грузится быстрее, и механизм проверки памяти у нее опенсорсный и еще немного всяких примочек. В том числе отлкючение какой-то проприетарной лабуды от intel. И мой dell в списке поддерживаемых. Собрал прошивку, кинул джампер на включение service mode - прошился. Libreboot 26.01rev1 на базе coreboot с native raminit для Haswell — если это о чем-то скажет.

Перемычка на контактах SERVICE_MODE
Перемычка на контактах SERVICE_MODE

Увы другой механизм проверки памяти не дал эффекта. С тремя планками система грузится без проблем. Стоит поставить четвёртую — raminit падает, машина не стартует. То есть проблема не только в стоковом BIOS: coreboot с более подробным логом показал, где именно приходит отвал. И да. Тут есть логи — их можно читать на встроенном COM порту. Нуженс всего лишь старый советский нульмодемный кабель и второй компьютер с serial портом. Связка USB переходник + mac на m1 вполне подошла. 115200 8N1 -> читаем логи.

Нуль-модемный кабель в COM-порту и USB-переходник
Нуль-модемный кабель в COM-порту и USB-переходник

Что показывает лог

Cannot fast boot: DIMMs have changed raminit failed on step RST_NONT ... C0.R2: Left Right Width Center B5: 336 368 32 352 RcvEn: Width of high region (32) too small RcvEn problems on channel 0, byte 5 raminit failed on step RCVET

Первую ошибку, RST_NONT, можно не читать: coreboot заметил, что планки поменялись, и решил настроить всё с нуля. Это штатное поведение.

А вот RCVET — это и есть поломка.

Как это работает, на пальцах. При каждом включении контроллер памяти заново учится общаться с планками — это называется memory training. Один из шагов — подобрать момент, когда «слушать» ответ планки. Контроллер двигает этот момент маленькими шагами и смотрит, в каком диапазоне сигнал ловится стабильно. Чем шире диапазон, тем больше запас.

Данные планка отдаёт восемью параллельными полосками — байтами, и каждый настраивается отдельно. У нормальных байтов стабильная зона — 56 тиков, а у одного — 32. Coreboot требует строго больше 32 (хвала опенсорсу, это видно прямо в коде), а ищет с шагом 8. То есть не хватило ровно одного шага.

Байт Запас (тики)
B0, B1, B2, B4 56 нормально
B3 48–56 нормально
B5 32 впритык → отказ

Лог: 9020-4dimm-FAIL-RCVET.txt

C0.R2.B5 — это адрес: канал 0, ранг 2, байт 5. Ранг — половинка dual-rank планки, для контроллера она выглядит как отдельная маленькая планка. Ранг 2 — это вторая планка в канале 0, та самая четвёртая. В рабочем варианте на трёх планках её слот пустует.

При этом две планки в одном канале — не проблема сама по себе: в канале 1 они прекрасно уживаются. Не работает именно канал 0 со второй планкой.

Эксперименты и воспроизводимость

Дальше я переставлял всё подряд: менял планки местами, гонял между слотами 4-гигабайтную single-rank (она попроще для контроллера), перезагружался по многу раз. Результат всегда один:

Что делал Запас B5 Лог
4 × 8 ГБ 32 txt
заменил одну 8 ГБ на 4 ГБ в другом канале 32 txt
поставил 4 ГБ в соседний слот того же канала 32 txt
то же, ещё раз 32 там же, вторая загрузка

Остальные байты от раза к разу гуляют на ±8 тиков. А B5 каждый раз одинаковый, до тика. Слишком стабильно для случайности.

Слоты памяти на плате
Слоты памяти на плате

Значит, дело не в конкретной планке, не в окислившемся слоте и не в перегрузке канала — соседа облегчал, второй канал менял, а B5 всё равно. Остаются подозреваемые:

  • контроллер памяти в процессоре (конкретный экземпляр);
  • контакт в сокете процессора;
  • сама материнская плата.

Точнее разделить без запасных планок не получилось.

Железо тут пограничное само по себе — штатный BIOS тоже капризничал. Coreboot просто строже: одна попытка — и сдаётся (в коде прямо написано TODO: Try more than once), а порог в 32 — не более чем эвристика.

Подводные камни

Одинаковые серийники аукнулись отдельно: fast boot в coreboot сравнивает SPD по слотам, и раз у всех планок SPD совпадает вплоть до серийника, перестановку одинаковых модулей coreboot не замечает и применяет тренировку от другой физической планки. Сбросить кэш можно только сменой набора занятых слотов.

Похожая история со сменой CPU: у i3-4150 и i7 того же поколения одинаковый CPUID (306C3), а сброс кэша по сигналу ME «CPU replaced» в коде закомментирован. С той же памятью новый процессор загрузится на тренировке от старого. Чтобы форсировать новую тренировку — нужна одна загрузка на двух планках, и только потом вернуть третью.

Обходной путь

Рабочий вариант на сейчас — просто не занимать проблемный слот: три планки, слот C0S1 пустой. 24 ГБ, из них 16 в dual-channel. Работает стабильно. Но хочется все 32 :)

Дальнейшие шаги

  1. Заменить CPU — хоть и контроллер памяти и в i3 и в i7 одинаковый, но разводка внутри корпуса у i7 своя, плюс заново сядет контакт в сокете. Другой экземпляр IMC может иметь больше запаса и пройти training с четырьмя DIMM на DDR3-1600. В теории для лучшей серии процессоров и голый кремний и готовый процессор проходят более строгие тесты.
  2. Снизить частоту до DDR3-1333, если замена CPU не поможет. То, что я хотел сделать прошивкой SPD. В Libreboot нет прямой настройки частоты памяти — она берётся по самой медленной планке из SPD, поэтому нужен патч в init_mpll.c, ограничивающий tCK значением TCK_666MHZ, если в каком-то канале две планки. Ну или найти планку с низкой частотой.
  3. Ослабить порог до width < 32 — как крайний диагностический эксперимент. Не решение как таковое: понадобится долгий прогон memtest86+ на прогретой машине, потому что искажённый DQS на non-ECC памяти даёт не отказ загрузки, а тихие битые биты.

Для более глубокой диагностики стоит собрать прошивку с CONFIG_DEBUG_RAM_SETUP=y — тогда в логе появится декод SPD и посэмпловый график RcvEn по каждому байту.

Итог

Жду i7. Он уже в стране. Если не поможет — ставлю патч на 1333, а затем при необходимости ослабляю порог и прогоняю memtest. Если будет совсем грустно — куплю еще один 9020, сниму с него плану 4gb — чтобы уж двухканал был :D А второй комп кому-нибудь подарю :)

UPD:

В ожидании процессора я таки решил прошить BIOS прошивкой опускающией частоту памяти на 1333. Собрал, прошил — получилось завести 28gb, на 32 проходит тренинг, но дальше все равно падает. Пока не знаю, искать пару плашек брендированной памяти, или взять еще 4gb и успокоиться с конфиуграцией 4+4+8+8. Так что и ослабление порога теперь тоже не выглядит особо осмысленным: на 1333 MHz полные 32 ГБ уже способны пройти весь memory training, а проблема вылезает дальше по загрузке.

Что показали прогоны на DDR3-1333

Патч с ограничением частоты сработал как задумано: coreboot выбирает 666 MHz, то есть DDR3-1333, обычно с CL9. Но результат оказался не в духе «снизил частоту — всё починилось». Картина стала сложнее.

На одной из первых попыток с тремя планками raminit снова упал на Receive Enable Training: тот же byte 5 канала 0 получил окно шириной 32 тика. То есть само по себе снижение частоты не убрало маргинальность. При этом в дальнейших прогонах те же и более тяжёлые конфигурации уже проходили memory training полностью.

Самое интересное — 32 ГБ. На DDR3-1600 четыре 8-гигабайтные dual-rank планки стабильно умирали прямо в RCVET на C0.R2.B5. На DDR3-1333 все четыре планки уже могут полностью пройти raminit: контроллер видит по 16 ГБ на каждом канале, mc_init_done приходит успешно. Но дальше машина всё равно нестабильна — в одной раскладке перезагружается на переходе из romstage в postcar, в другой доходит заметно дальше и виснет уже при старте дополнительных ядер CPU.

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

Конфигурация Объём Примерное число ranks Что получилось на 1333 Логи
2×8 ГБ, по одной планке на канал 16 ГБ 4 Есть полный успешный старт; в другом прогоне memory init прошёл, но позже был крах на clear_memory/init_pae_pagetables OK, крах
3×8 ГБ 24 ГБ 6 Были повторяющиеся поздние перезапуски, но та же конфигурация позже полностью загрузилась до payload перезапуски, OK
3×8 ГБ + 1×4 ГБ single-rank 28 ГБ 7 Полный успешный старт дважды, причём в двух разных раскладках слотов раскладка 1, раскладка 2
4×8 ГБ dual-rank 32 ГБ 8 Memory training проходит полностью, но дальше система зависает/перезагружается: либо на postcar, либо при AP init postcar, AP init

Отдельно хорошо видно, как поменялась именно максимальная конфигурация:

4×8 ГБ DDR3-1600 DDR3-1333
Частота контроллера 800 MHz 666 MHz
Основные тайминги CL11, 2T CL9, 2T
Receive Enable Training Стабильный fail на C0.R2.B5, width = 32 Может пройти полностью по всем ranks
До какой стадии доходит загрузка Не выходит из raminit Доходит до postcar/ramstage и даже до AP init
Итог Не стартует Всё ещё нестабильно, но проходит заметно дальше
Лог txt postcar, AP init

Есть ещё одна странность: поздние падения встречались и на более лёгких конфигурациях, причём одна и та же раскладка могла несколько раз подряд перезагрузиться, а потом нормально пройти до payload. Поэтому я пока не считаю 28 ГБ каким-то жёстким «лимитом платформы». Скорее видно, что 7 ranks уже работают достаточно надёжно, а 8 ranks делают систему совсем пограничной. Плюс где-то рядом существует ещё одна плавающая проблема — контакт, конкретный IMC, материнская плата или особенности native raminit.

Практический результат на сейчас такой: 28 ГБ в виде трёх dual-rank 8 ГБ и одной single-rank 4 ГБ — первая конфигурация с четырьмя занятыми слотами, которую удалось дважды полностью загрузить в разных перестановках. Полные 32 ГБ на 1333 уже проходят тренировку памяти, но стабильного старта пока нет.