Аморальный патч для Intel DRM
На свете есть не так много вещей, которым под силу меня выбесить до невменяемости. Но кое-что делает это с гарантией: оборзевшая в край машина, возомнившая себя умнее человека.
А значит снова пришло время карать и патчить!
Direct Rendering Manager (DRM)
Развитие современных видеокарт пошло по весьма сюрреалистичному пути:
крупные вендоры страстно хотят чтобы их устройства имели максимально широкую совместимость с открытым ПО и одновременно были закрытыми, неповторяемыми и недоступными для клонирования, плюс защищенными разнообразными патентами.
То что звучит как чистая шизофрения для человека с техническим образованием, будучи спущенным сверху в виде директивы, еще и подкрепленной серьезными бюджетами (с угрозой увольнения в случае провала) — породило на свет такую хтонь как binary blob.
Это когда основная часть управляющей устройством логики реализуется в виде специальной прошивки, с защитой и обфрускацией — того самого «блоба», затем вокруг создается открытая часть, которая линкуется с открытым ядром и окружением.
А все вместе оно задорно и без смущения объявляется как частично беременна открытое, ага.
В современном Linux есть такая штука как Direct Rendering Manager:
The Direct Rendering Manager (DRM) is a subsystem of the Linux kernel responsible for interfacing with GPUs of modern video cards
Если кратко и без мата, то это такая специальная дырка в ядре Linux, для максимально прямой коммуникации между видеокартой и клиентским ПО, создаваемая в первую очередь ради игор.
В угаре оптимизации «ядростроители» дошли до использования 3D-ускорения (GPU) даже для отрисовки консоли (тот самый KMS):
И теперь мы имеем «клевый терминал» в разрешении 1920×1280 и со сглаживанием шрифтов, на котором что-то разобрать можно лишь с лупой.
Угар портирования
Под натиском волн малолетних долбо#бов, желающих «гонять игоры» на серверной ОС, разработчики FreeBSD не выдержали:
подсистема DRM и KMS, вместе с проприетарными блобами была перенесена из Linux и теперь используется в системе по-умолчанию.
С тех лет и до сих пор разработка DRM синхронизируется с апстримом (поскольку это отдельный проект) и ядром Linux.
Заодно были фактически похоронены все альтернативные варианты:
старый текстовый TTY и драйвер Intel для Xorg пока еще существуют, но их связку и настройку, а главное — все сопутствующие баги в клиентском ПО вы ныне будете отлавливать и исправлять самостоятельно.
Поскольку интерес сообщества к таким вещам оказался утрачен.
В качестве вишенки на этом торте из навоза, добавлю что всенародно любимый браузер Chrome откровенно хреново работает без загруженного модуля KMS, так что заводить весь этот цирк с DRM и KMS приходится даже на откровенно винтажных машинах — просто ради сраного браузера.
Оборзевшая машина
Вся эта технологическая «многоножка» из Intel с их блобами и апстрима ядра Linux с их любовью к тотальным переделкам на Rust, на практике приводит к тому, что в FreeBSD постоянно попадают ломающие обновления, ни отследить ни исправить которые в моменте не получается.
«Думали что работает» — говорят в таких случаях разработчики FreeBSD и советуютпройти нах#йобновиться до -CURRENT версии.
Что для обычных людей и рабочего окружения на машине равносильно старому японскому ритуалу сеппуку поскольку упадет и сломается вообще все и с концами.
В какой-то момент обновление пакета drm-kmod, содержащего тот самый порт подсистемы DRM из ядра Linux принесло вот такое:
Ну принесло и принесло, ошибок много разных, исправляются далеко не все и так далее.
Но конкретно эта забивала весь буфер сообщений ядра!
Сообщений генерировалось настолько много, что dmesg — команда для отображения этого самого буфера, показывала только одну эту бесконечно повторяющуюся ошибку.
Ошибка сама по себе известная, страдают как пользователи FreeBSD:
Так и линуксоиды:
Но самое веселое, что баг оказался с рогами и копытами совсем не специфичным и подобное сообщение означает буквально «что-то сломалось».
Ну что, вы все еще любите проприетарные драйвера от уважаемых производителей?
Беглый поиск в репозитории, в котором ведется разработка подсистемы DRM (да, она ведется отдельно от ядра Linux) показал, что сообщений с этой ошибкой откровенно немало:
Положение дел
В итоге получается есть некий баг, с гнездом где-то на уровне прошивки видекарт от Intel. Который (судя по репортам) проявляет себя самым феерическим образом — от спама сообщениями до мигания экрана и полного зависания системы.
Исправить своими силами этот баг нельзя, а все обнаруженные «workaround» в сети по накалу дичи напоминают известное шоу «Битва Экстрасенсов»:
нарисуйте ночью в поле пентаграмму из соли, разложите по углам загрузочные диски FreeBSD с 5й по 10ю и громко читайте файл Changelog задом наперед.
В качестве примера, так выглядит одно из решений:
Хорошие новости
Первая заключается в том, что в свежих прошивках баг вроде бы исправили на стороне Intel, но чтобы эту прошивку поставить — нужна сборка модуля DRM для FreeBSD 15, которая еще не выпущена:
Прямо сейчас идет серьезная работа по перепиливанию DRM как в его основном проекте так и на стороне команды FreeBSD (в -CURRENT), поэтому даже пытаться бекпортировать текущую версию drm-kmod в 14.х ветку не стоит.
Был найден некий бекпорт текущей версии drm-kmod с 15 до 14.1 версии, но во-первых даже он успел устареть практически на год, во-вторых в 14.3 уже не собирается.Еще (к сожалению) не стоит рассматривать переезд на 15ю версию как гарантированное решение, поскольку есть багрепорты уже и оттуда:
Вторая хорошая новость заключается в том, что на двух моих ноутбуках, где проявляется данный баг, все работает без критических сбоев, а само сообщение до недавних пор глушилось настройкой:
compat.linuxkpi.i915_disable_power_well="0"
Так что конкретно в моем случае, проблема заключается лишь в бесконечном засирании буфера сообщений ядра этой дурацкой и бессмысленной ошибкой:
Аморальный патч
Разумеется так делать нельзя — глушить сообщения об ошибках в ваших реальных проектах не стоит.
Хотя если в вашем проекте возникает ситуация, когда сообщение об ошибке генерируется по сотне раз в секунду — ну наверное вопрос уже к вам как к разработчику, допустившему такой п#здец.
Но тут и проект не мой и доступа к разработчикам нет и сам процесс разработки DRM сильно напоминает известный фильм «Human Centipede», так что где искать концы не очень понятно.
Для примера, багрепорты по ошибкам DRM в трекера ядра Linux сразу шлют нахер просят перенаправлять в отдельный проект DRM:
Так что было решено применить военную хитрость и просто заглушить сообщение об ошибке в исходниках, пересобрав DRM из портов.
Так выглядит конечный результат после патча:
Поскольку новая 15я по счету версия FreeBSD еще официально не вышла на момент написания статьи, я все еще использую 14.3 — максимально доступная версия DRM для этой ветки это 6.1.
/usr/ports/graphics/drm-61-kmod
Поиск в исходном коде по тексту сообщения об ошибке показал, что встречается она всего в одном месте, файл i915_irq.c:
drivers/gpu/drm/i915/i915_irq.c
Так выглядит место появления:
.. fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); if (fault_errors) drm_err(&dev_priv->drm, "Fault errors on pipe %c: 0x%08x\n", pipe_name(pipe), fault_errors); ..
Все что нужно сделать — закомментировать этот блок, начиная с условия.
И это проклятое сообщение вы больше не увидите, ура.
Для уменьшения геммороя, я подготовил готовый патч, который достаточно положить в специальный каталог и он автоматически применится при сборке.
Создаете файл patch-i915_irq.c в каталоге /usr/ports/graphics/drm-61-kmod/files, вставляете туда вот такое содержимое:
*** drivers/gpu/drm/i915/i915_irq.c.orig Tue Nov 18 17:17:39 2025
--- drivers/gpu/drm/i915/i915_irq.c Tue Nov 18 17:17:52 2025
***************
*** 2571,2585 ****
if (iir & gen8_de_pipe_underrun_mask(dev_priv))
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
! if (fault_errors)
drm_err(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
! fault_errors);
}
if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
master_ctl & GEN8_DE_PCH_IRQ) {
/*
--- 2571,2585 ----
if (iir & gen8_de_pipe_underrun_mask(dev_priv))
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
! /*if (fault_errors)
drm_err(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
! fault_errors);*/
}
if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
master_ctl & GEN8_DE_PCH_IRQ) {
/*
make clean make
Проверяем что изменения в файле i915_irq.cприменились и запускаем:
make reinstall