Материнская плата X79 с XEON E5 2420 V2 2*4 Гб = 8 Гб DDR3 ПАМЯТЬ, комплект combo, NVME MATX сервер

Как втиснуть 16 ГБ памяти на материнскую плату, которая не поддерживает такой объём

Некоторое время назад я поставил на один из своих компьютеров 16 ГБ памяти. На нём стоит материнка Foxconn P55MX с Core i5 750. Можно было бы и заменить этот старый CPU, но он пока нормально работает и делает всё, что мне нужно.

Вот что интересно. Материнская плата официально не поддерживает 16 ГБ RAM. Спецификации на вышеупомянутой странице указывают, что поддерживается максимум 8 ГБ. На плате только два слота, поэтому у меня возникло подозрение, что планки 8 ГБ просто были редкостью в то время, когда вышла материнская плата. Я всё равно решил попробовать. Во многих случаях материнские платы поддерживают больше RAM, чем официально заявляет производитель.

Я убедился, что установлена последняя версия BIOS (версия 946F1P06) и вставил две своих планки по 8 гигабайт. Затем загрузил Ubuntu 16.04, и всё работало отлично. Я решил, что моя теория о том, что плата поддерживает больше памяти, чем заявлено в документации, оказалась правильной, и забыл об этом. Мне нравилось работать с дополнительной RAM и я был счастлив, что игра окупилась.

Но несколько месяцев спустя я попытался загрузить Windows 10. В основном, компьютер работает под Linux. Лишь иногда нужно загрузить Windows, чтобы что-то проверить. Тогда-то и началось самое интересное.

Когда появился GRUB, я выбрал в меню Windows 10 и нажал Enter. Экран загрузки Windows ненадолго появился, а затем меня сразу приветствовал синий экран смерти.

Стоп-код: ACPI_BIOS_ERROR. Я много погуглил и выяснил, что суть в какой-то проблеме с ACPI-таблицами в BIOS. Среди прочего, таблицы ACPI сообщают операционной системе, как настроить оборудование. Попытка загрузки с установочного USB-накопителя Windows привела к той же ошибке. Так что, думаю, Foxconn не врал. Этот компьютер действительно не поддерживает 16 ГБ оперативной памяти. Возврат к 8 ГБ привёл к успешной загрузке. Тесты RAM тоже прошли отлично, так что дело не в плохой планке памяти.

Я попытался связаться с поддержкой Foxconn насчёт исправления BIOS, но не получил ответа. Адрес электронной почты указан на их сайте, но он не работает. Возможно, Foxconn больше не занимается материнскими платами. Похоже, они также не оказывают поддержки.

В этот момент обычный человек просто сдался бы, смирившись с 8 ГБ памяти или купив новый компьютер. Но я не хотел так легко сдаваться. Я знал, что теоретически компьютер может использовать 16 ГБ, потому что он отлично работал в Linux. Поэтому я начал изучать ACPI и экспериментировать с настройками BIOS.

Я нашёл интересный раздел BIOS, где можно играть с некоторыми настройками памяти. Одним из параметров была «функция переназначения памяти» (Memory Remap Feature). Она была включена. В документации по BIOS говорится, что опция позволяет «перекрывать память PCI» для мэппинга выше общей физической памяти. Поиск в интернете указал, что его нужно включить при загрузке в 64-разрядной ОС. Просто ради эксперимента я её отключил, и Windows реально загрузилась! Однако сказала, что может использовать менее 4 ГБ оперативной памяти. Но это было приятно: у меня появился способ попасть в Windows без необходимости физически удалять планку памяти.

В Ubuntu то же самое. С отключённой функцией переназначения памяти она ограничила меня менее чем 4 ГБ RAM. На данный момент я был уверен, что происходит какая-то проблема с отображением памяти. Я решил подробнее изучить ошибку ACPI_BIOS_ERROR и её причины — и наткнулся на этот отличный документ для отладки драйверов Microsoft, который объясняет проверку ошибок ACPI_BIOS_ERROR.

Согласно документу, нужно было найти четыре параметра ошибки, которые раньше отображались на синем экране в старых версиях Windows. Windows 10 по умолчанию скрывает всю информацию, но можно повторно включить отображение дополнительной информации об ошибках, добавив запись в реестр. Вот отличный ответ на superuser.com, который указал мне верное направление.

После соответствующей правки реестра я снова включил функцию переназначения памяти в BIOS и загрузил Windows. BSOD теперь показал четыре дополнительных кода в верхнем левом углу:

Прекрасно! Таким образом, параметр 1 равен 0x0000000000000002. В документации Microsoft написано, что параметр 1, равный 0x02, означает проблему с обработкой списка ресурсов для корневых шин PCI. Поскольку параметры 2, 3 и 4 выглядят как сумасшедшие значения, это, наверное, указатели. И если тут одни указатели, Microsoft говорит, что проблема в том, что область декодирования PCI перекрывается со списком областей памяти, возвращаемых интерфейсом BIOS E820.

Окей. Информации много, но можно с чего-то начать исследование. Я нашёл информацию, как вызов E820 BIOS предоставляет информацию об областях памяти. Затем вернулся в Linux и просмотрел всю информацию о запуске ядра с помощью команды dmesg, уделяя особое внимание E820 и ACPI. Вот что нашлось:

Позже я увидел это:

Ага! Видите предупреждение о конфликте? Я бы его не заметил, но после установки памяти Linux начал выводить это сообщение при каждой загрузке. Я попытался загрузиться в Linux с отключённой функцией переназначения памяти в BIOS. В этом случае пропала последняя область e820 с 0x100000000 до 0x42fffffffff, и, таким образом, сообщение о конфликте также исчезло, а в списке появился ещё один «корневой ресурс шины» с окном главного моста с 0x400000000 до 0xfffffffff.

Итак, что получается. Linux работает с 16 ГБ, потому что замечает конфликт и игнорирует конфликтующий диапазон PCI, который предоставляет ACPI, в то время как Windows с отвращением поднимает руки и выблёвывает синий экран: «У вашего BIOS проблема!» Не могу винить Windows. Действительно, существует перекрытие, поэтому можно понять, что она путается.

В этот момент я не был уверен, стоит ли продолжать. Последние 768 МБ памяти с 0x400000000 до 0x42fffffffff сопоставлены с началом огромной области пространства памяти, которую материнская плата использует для PCI. Ясно, что если материнская плата ожидает там PCI, может произойти что-то действительно плохое. Таким образом, материнская плата поддерживает только 15,25 ГБ RAM, правильно?

Но… в Linux всё работает просто отлично, без поддержки этой дополнительной области сопоставления PCI! Что, если как-то изменить таблицы ACPI, чтобы большой диапазон PCI начинался с 0x430000000 вместо 0x400000000, то есть сразу после окончания физической RAM. Тогда конфликт бы исчез, а большая часть окна сопоставления PCI по-прежнему осталась доступной.

Я начал копаться в таблицах ACPI. К счастью, Linux позволяет очень легко делать дампы. Есть специальные инструменты для этого, но таблицы можно легко найти в sysfs:

Вот они все. Меня также обрадовало, что в GRUB есть возможность заменить ваши таблицы ACPI новыми версиями. Поэтому если выяснить, какая таблица задействована, можно установить новую версию этой таблицы с помощью GRUB. Теоретически, Windows будет счастлива этим.

Среди других инструментов, я использовал iasl, чтобы разобрать различные таблицы ACPI и найти значение 0x400000000 для замены. Скорее всего, это значение с обратным порядком байтов (little-endian) и размером 64 бита, так что я запустил binwalk для поиска по всем файлам таблиц:

Я сделал копию таблицы OEMB, заменив байт 0x00 непосредственно перед байтом 0x04 на 0x30, чтобы изменить значение на 0x430000000 (помните, что это обратный порядок). Эту изменённую копию я поместил в файл /boot/oemb.dat. Затем использовал GRUB для замены таблицы OEMB моей копией, временно вставив следующую команду в список команд загрузки (ввод буквы ‘e’ в GRUB после выбора Ubuntu):

Идея в том, что она говорит GRUB загрузить все таблицы ACPI, кроме таблицы OEMB, а затем загрузить содержимое /boot/oemb.dat и добавить его в качестве дополнительной таблицы. Это эффективно заменит старую таблицу OEMB новой таблицей OEMB.

Хорошо, я загрузил Linux и…

Проклятая ошибка никуда не делась. WTF? Я предположил, что диапазон PCI фактически определён где-то ещё, но я нигде не видел, чтобы определялось конкретное значение. Я убедился, что исправленная таблица OEMB действительно загрузилась, и вернулся к исследованию.

На этот раз я решил использовать iasl для декомпиляции таблицы DSDT. Отслеживание показало, что таблица DSDT должна содержать метод под названием _CRS , который отвечает за создание этой таблицы.

В файле .dsl я действительно нашёл метод _CRS, связанный с шиной PCI, и он выглядел довольно сложным. Таблица DSDT содержит фактический код, поэтому значения таблицы искать непросто. В моем случае метод _CRS оказался довольно сложным. Я интерпретировал код насколько смог и понял, что метод _CRS загружает информацию из другой таблицы в памяти, начиная с 0xCF78E064. Я снова посмотрел лог загрузки Linux в dmesg и нашёл это:

Ага! Он загружает информацию из таблицы OEMB. Моя догадка была верна с самого начала. Так почему же не сработала замена таблицы OEMB?

Первым порывом было изменить DSDT, чтобы перевести её на новое расположение таблицы OEMB, но я чувствовал, что в перспективе это плохая идея, потому что новые версии GRUB могут изменить местоположение в памяти, где хранится пользовательская таблица OEMB.

Я остановился на другой идее. В GRUB есть эквиваленты команд write_byte , write_word , write_dword и read_ . Что если GRUB на лету будет изменять исходную таблицу OEMB? В наше время BIOS’ы сжатые. Вероятно, таблицы загружаются в RAM, поэтому теоретически можно изменять значения.

Так я и сделал. В качестве временного теста я добавил следующую команду в последовательность загрузки GRUB:

Я перезагрузился в Linux и с тревогой проверил лог dmesg для PCI.

Успех! Окно 0x430000000-0xfffffffffff появилось как новое допустимое окно в списке, и предупреждение о конфликте исчезло. После проверки, что Linux всё ещё работает нормально, я попытался загрузиться в Windows с тем же хаком.

Сработало! Теперь я могу загрузиться в Windows с 16 ГБ RAM, если использовать GRUB в качестве загрузчика с вышеупомянутой командой write_byte. Загрузчик Windows 10, очевидно, не будет работать. И если я когда-нибудь переустановлю Windows, вероятно, придётся временно вытащить одну планку RAM, чтобы загрузился установщик. Но это работает!

Чтобы навсегда добавить исправление в GRUB, я создал файл /etc/grub.d/00_patchbios следующего содержания:

Затем сделал скрипт исполняемым и запустил sudo update-grub . Теперь патч автоматически применяется при запуске GRUB.

Думаю, это был весёлый опыт, чтобы поделиться с миром! Надеюсь, вы что-то узнали из этого поста. Конечно, я и сам многому научился в процессе.

Добавить комментарий