- PVSM.RU - https://www.pvsm.ru -
В модульных Linux дистрибутивах, таких как Puppy/Slax/Porteus, корневая файловая система собирается из многих слоев с помощью aufs либо overlayfs. Слои представляют из себя squashfs файлы, смонтированные через loopback.
Проприетарные драйвера NVIDIA для Linux по умолчанию не предполагают возможности соседства нескольких версий в одной файловой системе в классических дистрибутивах. Но эта проблема может быть легко решена в модульных дистрибутивах путем создания отдельных squashfs модулей с разными версиями NVIDIA драйверов.
PocketHandyBox [1] компактный портативный Linux дистрибутив на базе Debian (и Devuan) с поддержкой NVIDIA "из коробки", предназначенный для тестирования, обслуживания ПК, ноутбуков.
В PocketHandyBox squashfs модули с драйверами NVIDIA находятся в папке live/nvidia. При этом модули для ядра Linux выделены в отдельные squashfs файлы. Файлы с расширением .kmodsfs содержат в названии uname -r (kernel release) ядра для которого они собраны.
Определение видеокарты по PCI ID и загрузка модуля с соответствующей версией драйвера реализована в initrd в скрипте linuxrc [2]. Используются только команды из состава busybox.
# Detect nvidia video cards on pcie bus
if [ "$NVIDIA" = detect ]; then
echo "${i}detecting nvidia GPU"
nvlist=`lspci | grep -i "030.: 10de:" | cut -d":" -f4`
if [ -n "$nvlist" ]; then
for nv in $nvlist
do
echo "${i}$nv chip found, checking which nvidia driver supports it"
if grep -sqi 10de$nv /usr/share/nvidia/nvidia.ids; then NVIDIA=nvidia; break
elif grep -sqi 10de$nv /usr/share/nvidia/nvopen.ids; then NVIDIA=nvopen; break
elif grep -sqi 10de$nv /usr/share/nvidia/nvidia-tesla-470.ids; then NVIDIA=nv470; break
elif grep -sqi 10de$nv /usr/share/nvidia/nvidia-legacy-390xx.ids; then NVIDIA=nv390; break
elif grep -sqi 10de$nv /usr/share/nvidia/nvidia-legacy-340xx.ids; then NVIDIA=nv340; break
else echo "${i}$nv chip is not supported by nvidia driver"
fi
done
else echo "${i}could not find any nVidia GPU on this PC"
fi
fi
# Find nvidia modules
if [ "$NVIDIA" ] && [ "$NVIDIA" != detect ]; then
echo "${i}$NVIDIA NVIDIA driver will be activated"
find $DATADIR/nvidia -name "$NVIDIA*.kmodsfs" 2>/dev/null | grep $KERNEL >>/tmp/modules
find $DATADIR/nvidia -name "$NVIDIA*.squashfs" 2>/dev/null | grep -v gsp | egrep -ve "$NOLOAD" >>/tmp/modules
[ "$NVIDIA" = nvopen ] && find $DATADIR/nvidia -name "nvidia*.squashfs" 2>/dev/null | egrep -ve "$NOLOAD" >>/tmp/modules
NOLOAD="$NOLOAD|mesa-vulkan-drivers"
fi
В системе установлен пакет nvidia-detect который в /usr/share/nvidia/ содержит текстовые файлы .ids со списками PCI ID видеокарт, поддерживаемых определенной версией драйвера. При создании initrd1.xz для каждого ядра Linux скрипт mkinitrd [3] копирует их внутрь cpio архива.
В загрузчиках по умолчанию прописан cmdline nvidia=detect. При загрузке если в выводе lspci есть видеокарты NVIDIA - последовательно производится поиск найденных PCI ID в файлах .ids из /usr/share/nvidia/. Если совпадение найдено то переменной NVIDIA присваивается значение с префиксом для поиска модулей соответствующей версии драйвера.
Имена найденных файлов модулей .squashfs и .kmodsfs добавляются в файл /tmp/modules. Далее при вызове функции IncludeModules [4] они будут смонтированы в /memory/images/ и затем в overlayfs.
В конце, когда новый корень собран - linuxrc передает управление /usr/sbin/init либо systemd. Происходит штатный запуск сервисов, в том числе udev. При этом подхватываются настройки из /etc/modprobe.d и /etc/modules-load.d (в том числе blacklist nouveau) которые содержатся в подключенных squashfs модулях.
Таким образом получаем рабочий драйвер NVIDIA сразу после запуска и без дополнительных манипуляций.
Дополнительная сложность добавилась с выходом NVIDIA драйвера для RTX 5000 серии. Дело в том что Blackwell не поддерживается [5] классическими закрытыми модулями ядра. При этом перейти полностью на открытые модули тоже нельзя так как они не поддерживают Maxwell и Pascal.
Поэтому в PocketHandyBox собраны оба варианта модулей ядра. Во избежание дублирования squashfs модули с userspace библиотеками и утилитами у них общие. А также сформированы два списка nvidia.ids [6] (все начиная с Maxwell и не включая Blackwell) и nvopen.ids [7] (все начиная с Turing, включая Blackwell). Доработана логика в linuxrc. При выборе nvopen - загружаются и nvidia*.squashfs модули, в том числе squashfs с файлами GSP прошивок.
Спасибо за внимание!
Если интересно то в следующих статьях могу рассказать как в PocketHandyBox реализовано переключение на дискретную NVIDIA карту для современных драйверов, которые поддерживают PRIME render offload [8] и для legacy версий 340.xx и 390.xx, в которых эта поддержка отсутствует.
Автор: gumanzoy
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/435110
Ссылки в тексте:
[1] PocketHandyBox: https://habr.com/ru/news/935640/
[2] linuxrc: https://github.com/PocketHandyBox/phb-base/blob/main/bookworm/rootcopy/opt/initramfs/linuxrc
[3] mkinitrd: https://github.com/PocketHandyBox/phb-base/blob/main/bookworm/rootcopy/usr/local/sbin/mkinitrd
[4] IncludeModules: https://github.com/PocketHandyBox/phb-base/blob/main/bookworm/rootcopy/opt/initramfs/finit#L236
[5] не поддерживается: https://download.nvidia.com/XFree86/Linux-x86_64/580.76.05/README/kernel_open.html
[6] nvidia.ids: https://github.com/PocketHandyBox/phb-base/blob/main/bookworm/xfceconf/usr/share/nvidia/nvidia.ids
[7] nvopen.ids: https://github.com/PocketHandyBox/phb-base/blob/main/bookworm/xfceconf/usr/share/nvidia/nvopen.ids
[8] PRIME render offload: https://download.nvidia.com/XFree86/Linux-x86_64/580.76.05/README/primerenderoffload.html
[9] Источник: https://habr.com/ru/articles/961400/?utm_campaign=961400&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.