qemu-kvm, libvirt и проброс видеокарты Nvidia.

11. февраля 2021 Linux 10

Вступление.

В статье рассмотрена виртуализация Win10 посредством qemukvm совместно с libvirt и virt-manager, а так же проброс видеокарты Nvidia.

Выбор ОС и видеокарты обусловлен огромной проблемностью виртуализации, которую можно практически полностью нивелировать правильной настройкой, что создаёт интересный профессиональный вызов. К этому имеется некоторая востребованность для ряда специализированного проприетарного ПО, которое хоть и выходит из оборота, заменяясь на свободные (или не очень) нативные аналоги, но всё ещё эксплуатируется по остаточному принципу в узкоспециализированных нишах.

Несколько слов об Nvidia. Видеокарты данного вендора являются наихудшим вариантом для проброса из-за злонамеренного препятствования, которое подразумевает негласный запрет на проброс «непрофессиональных» моделей видеокарт. Проблема особенно характерна для Win10, в которой проброс без настройки приводит к неработоспособности системы.

В статье описано решение характерной для сочетания Win10 и Nvidia «Ошибки 43» (код 43) и VIDEO_TDR_FAILURE с драйвером nvlddmkm.sys, приводящей к «синему экрану смерти» (BSOD) из-за проблем с MSI (Message Signaled Interrupts). Не смотря на это, GTX 1060 возможно пробросить и она не имеет проблемы со сбросом GPU (reset bug) после выключения виртуальной машины. Проблема со сбросом выражается в том, что после завершения работы виртуальной машины реинициализация видеокарты не произойдёт и она останется в режиме выключения. Чтобы хост-компьютер смог взаимодействовать с таким «подвисшим» устройством, потребуется перезагрузка хоста, что, как правило, очень неудобно.

Примеры в статье отталкиваются от следующего набора оборудования и пакетов:

  • Дистрибутив: Linux Mint 20 (Ubuntu 20.04).
  • Ядро Linux 5.10.9. Вполне подойдёт и LTS.
  • Процессор: Intel i7 6800K 12 потоков.
  • Видеокарта для хоста: AMD RX 480 8 Гб.
  • Видеокарта для проброса: Nvidia GTX 1060 6 Гб.
    • На хосте проприетарный драйвер не применяется. Допустимо использование только свободного (nouveau) в виду специфики технологии проброса.
  • qemu-kvm 4.2 из стандартного репозитория (Ubuntu 20.04).

Вопросы оптимизации виртуализации рассмотрены в отдельной статье: https://noostyche.ru/blog/2021/03/30/optimizaciya-virtualizacii-win10-qemu-kvm/

Базовые требования и рекомендации.

  • В настройках материнской платы (UEFI) необходимо включить поддержку виртуализации.
    • Базовая аппаратная виртуализация.
      • Intel VT.
      • AMD SVM.
    • Поддержка виртуализации ввода-вывода — IOMMU.
      • Intel. Активировать VT-d (Intel Virtualization Technology for Directed I/O).
      • AMD. Активировать AMD-Vi.
  • Две дискретные видеокарты.
    • Видеокарты AMD наиболее предпочтительны для проброса в виду отсутствия искусственного препятствования со стороны вендора, что делает проброс практически беспроблемным.
    • Видеокарта, используемая для проброса, НЕ ДОЛЖНА быть в первом PCI-слоте.
    • Для пробрасываемой видеокарты не должны использоваться проприетарные драйверы, только свободные. В данном случае nouveau. Иначе на этапе захвата видеокарты драйвером vfio_pci хост или видеокарта могут зависнуть.
    • При наличии встроенной в процессор графики можно пробросить дискретную.
  • Видеокарта для проброса должна иметь поддержку EFI (модели от 2012 года).
  • Для вывода изображения с двух видеокарт достаточно одного монитора. Потребуется два кабеля. Первый будет от основной видеокарты, а второй — от пробрасываемой.
    • Переключение между выводом изображения с первой и второй видеокарты будет осуществляться через переключение видеорежима в настройках монитора.
  • Очень желательна материнская плата среднего ценового сегмента и выше, поддерживающая работу PCI в режиме 8x/8/x4 или 16x/8x.
  • Процессор минимум с восемью потоками.
  • В upstream-ядрах могут быть различные улучшения виртуализации, поэтому желательно использовать свежее ядро.

Содержание.

  1. Установка qemu-kvm, libvirt, virt-manager и сопутствующих пакетов.
  2. Базовая настройка libvirt.
  3. Загрузка модулей ядра.
    1. Модуль kvm.
    2. Модули IOMMU.
      1. Группы IOMMU и видеокарта.
    3. Модули vfio.
  4. Завершение подготовки проброса видеокарты GTX 1060.
  5. Создание и настройка виртуальной машины.
    1. Создание виртуальной машины с помощью Virt-manager.
    2. Подробная настройка виртуальной машины.
  6. Нюансы Windows.
  7. Проброс видеокарты Nvidia.
    1. Базовый проброс видеокарты.
    2. Установка драйвера Nvidia.
      1. Подготовка гостя.
      2. Включение MSI для видеокарты Nvidia.
      3. Маскировка виртуализации для решения «ошибки 43».
  8. Заключительная часть.

Предварительная настройка.

Установка qemu-kvm, libvirt, virt-manager и сопутствующих пакетов.

Примечание: Набор пакетов характерен именно для Ubuntu 20.04 и деривативов.

sudo apt install qemu-kvm libvirt-daemon libvirt-daemon-system libvirt-daemon-driver-qemu gir1.2-spiceclientgtk-3.0 virt-manager ovmf

qemu-kvm — средство виртуализации qemu с гипервизором kvm.

libvirt-daemon, libvirt-daemon-system и libvirt-daemon-driver-qemu — это основные пакеты, которые подтянут прочие необходимые. В них входит несколько демонов (сервисов) libvirt и утилит для управления виртуальными машинами.

virt-manager — графическая оболочка libvirt для управления виртуальными машинами и редактирования их конфигурации.

gir1.2-spiceclientgtk-3.0 — пакет для поддержки управления виртуальной машиной по протоколу SPICE. Поддерживает шифрование, общий буфер обмена, проброс USB и многое другое. Документация: https://www.linux-kvm.org/page/SPICE

ovmfOpen Virtual Machine Firmware — прошивка с поддержкой эмуляции EFI. Альтернатива seabios. Оптимальный выбор для ОС с поддержкой EFI (все актуальные Linux-дистрибутивы, Win8.1, Win10).

Место хранения прошивок /usr/share/qemu/

qemu-utils — набор утилит. Необязательный пакет для установки.

  • qemu-img — утилита для создания и преобразования образов накопителей. К примеру, позволяет преобразовать образ в формате vdi (Virtualbox) в img.
  • qemu-io — утилита для работы с QEMU I/O.
  • qemu-nbd — экспорт образа накопителя QEMU с помощью протокола NBD.

После установки пакетов требуется перезагрузка.

Базовая настройка libvirt.

После установки пакетов и перезагрузки требуется осуществить подготовку libvirt к использованию.

Пользователь и группа libvirt.

Убедиться, что пользователь был добавлен в группу libvirt:

id $USER | grep libvirt

Это позволит пользователю запускать виртуальные машины без привилегий суперпользователя и получить доступ к расширенным сетевым опциям.

Если пользователь не в группе — добавить вручную. Команда на добавление активного пользователя в дополнительную группу libvirt без удаления из предыдущих групп:

sudo usermod -aG libvirt $USER

$USER — активный пользователь.

После добавление нужно перезапустить сессию, чтобы изменения вступили в силу.

Запуск демона libvirtd.

Запуск libvirtd вручную.

systemctl start libvirtd

Можно добавить сервис в автозагрузку.

systemctl enable libvirtd

Вместе с libvirtd будет запущен virtlogd для ведения журнала событий.

Место хранения журнала событий виртуальных машин: /var/log/libvirt/qemu/

Загрузка модулей ядра.

В данном примере будет рассмотрен вариант передачи параметров для ядра посредством Grub. Для этого потребуется внести изменения /etc/default/grub.

Модули для загрузки и параметры для ядра должны быть перечислены в строке GRUB_CMDLINE_LINUX_DEFAULT=

Итоговый набор параметров для процессоров Intel и видеокарты GTX 1060 будет выглядеть так:

GRUB_CMDLINE_LINUX_DEFAULT="kvm_intel=on intel_iommu=on iommu=pt vfio-pci.ids=10de:1c03,10de:10f1 vfio_iommu_type1.allow_unsafe_interrupts=1 vfio_virqfd=1"

Далее подробно и по порядку.

Модуль kvm.

Основное предназначение — ускорение виртуализации.

Проверить поддержку kvm-ускорения можно утилитой kvm-ok:

sudo kvm-ok

Вывод, указывающий, что ускорение будет использоваться:

INFO: /dev/kvm exists
KVM acceleration can be used

Если модуль kvm не активирован, будет показано предупреждение:

INFO: /dev/kvm does not exist
HINT: sudo modprobe kvm_intel

Если ускорение не поддерживается:

INFO: Your CPU does not support KVM extensions
KVM acceleration can NOT be used

Проверить загружен ли модуль:

lsmod | grep -i kvm

Если вывод пустой, необходимо загрузить модуль.

Модуль kvm_intel зависит от модуля intel_iommu, загрузка которого описана ниже. То есть, чтобы загрузить модуль kvm_intel достаточно загрузить intel_iommu, но можно загрузить и вручную.

Утилита modprobe позволяет загрузить модуль, но только для текущей сессии:

sudo modprobe kvm_intel

Модули IOMMU.

Input Output Memory Management Unit https://ru.wikipedia.org/wiki/IOMMU

Настройка IOMMU является важным этапом для проброса видеокарты.

В настройках материнской платы (UEFI) нужно сделать следующее:

  • Для Intel активировать VT-d (Intel Virtualization Technology for Directed I/O).
  • Для AMD активировать AMD-Vi.

Загрузка с помощью Grub. В файле /etc/default/grub в строку GRUB_CMDLINE_LINUX_DEFAULT добавить intel_iommu=on iommu=pt.

Итоговый вид:

GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt vfio-pci.ids=10de:1c03,10de:10f1 vfio_iommu_type1.allow_unsafe_interrupts=1 vfio_virqfd=1"

intel_iommu=on — включить поддержку транслятора виртуальных адресов в физические. Материнская плата должна иметь блок управления памятью ввода/вывода (IOMMU). По идее, этот блок есть во всех современных не супер бюджетных материнских платах.

iommu=pt — включает режим проброса. Это снижает нагрузку IOMMU для устройств принадлежащих хосту.

После необходимо обновить конфигурацию Grub, чтобы изменения вступили в силу после перезагруки:

sudo update-grub

Перезагрузиться.

Удостовериться, что IOMMU используется:

dmesg | grep -iE "(DMAR|IOMMU)"

i — игнорировать различие регистра.

E — расширенное регулярное выражение.

Если вывод пустой, то IOMMU выключено или отсутствует аппаратная поддержка в материнской плате.

Группы IOMMU и видеокарта.

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

Проверка наличия групп устройств IOMMU:

ls /sys/kernel/iommu_groups

Должен быть подобный вывод (у всех будет разный):

0 1 10 11 12 13 2 3 4 5 6 7 8 9

Если пусто, значит IOMMU не включено.

Видеокарта разделена на два устройства: видео и аудио (звук через HDMI). Нужно проверить в какую IOMMU-группу входит видео и аудио видеокарты. Сначала потребуется узнать их ID. Для Nvidia:

lspci -nn | grep -i nvidia

Для GTX 1060 вывод будет такой:

Искомые ID имеют следующий вид:

  • Видео 02:00.0
  • Аудио 02:00.1

Теперь, зная ID устройств видеокарты, можно провести проверку принадлежности устройств к конкретной группе IOMMU:

find /sys/kernel/iommu_groups/ -type l | grep -iE "(02:00.0|02:00.1)"

Вывод:

Это означает, что устройства видеокарты находятся в группе 27, то есть всё в порядке.

Модули vfio.

Брошюра о vfio: http://www.linux-kvm.org/images/b/b4/2012-forum-VFIO.pdf

Рассмотрим следующий необходимый набор модулей:

GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt vfio-pci.ids=10de:1c03,10de:10f1 vfio_iommu_type1.allow_unsafe_interrupts=1 vfio_virqfd=1"

vfio-pci.ids — обеспечивает мягкий захват видеокарты драйвером vfio на этапе загрузки хост-системы. Это ключевой модуль, обеспечивающий успех проброса.

vfio_iommu_type1.allow_unsafe_interrupts=1 — уменьшает задержки (latency) прерываний. Позволит включить в Win-госте MSISupported для решения проблемы VIDEO_TDR_FAILURE nvlddmkm.sys.

vfio_virqfd=1драйвер для поддержки irqfd — механизма передачи прерываний между хостом и гостем.

Завершение подготовки проброса видеокарты GTX 1060.

Вернёмся к модулю vfio-pci.ids.

Видеокарта состоит из двух устройств: видео и аудио. В целях проброса модулю vfio-pci.ids необходимо передать vendor id и device id устройств видеокарты.

Вывести ID устройств видеокарты:

lspci -nn | grep -i nvidia

Вывод для GTX 1060:

02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] [10de:1c03] (rev a1)
02:00.1 Audio device [0403]: NVIDIA Corporation GP106 High Definition Audio Controller [10de:10f1] (rev a1)

Искомые vendor id и device id имеют такой вид:

  • Видео [10de:1c03]
  • Аудио [10de:10f1]

Итоговый результат для GTX 1060 выглядит так:

GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt vfio-pci.ids=10de:1c03,10de:10f1 vfio_iommu_type1.allow_unsafe_interrupts=1 vfio_virqfd=1"

После перезагрузки vfio захватит видеокарту, что сделает её доступной для проброса.

Проверить успешность захвата по ID видеоустройства:

lspci -nnk -d 10de:1c03

Вывод:

В строке Kernel driver in use должно быть vfio-pci. Это означает, что видеокарта была успешно захвачена драйвером vfio_pci.

На этом непосредственная настройка хоста окончена.

Создание и настройка виртуальной машины.

Процесс будет осуществлён с помощью Virt-manager.

Если при запуске Virt-manager выводится ошибка «Не удалось подключиться к libvirtd», то стоит удостовериться в следующем:

  • Установлены пакеты libvirt-daemon и libvirt-daemon-system.
  • Пользователь находится в группе libvirt.
id $USER | grep libvirt
  • libvirtd на самом деле запущен.
systemctl start libvirtd

Дополнительные варианты решения: https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF#virt-manager_has_permission_issues

Если есть какие-то другие проблемы, то их можно отследить через вывод в системном журнале:

journalctl -xb | grep -i libvirt

Создание виртуальной машины с помощью Virt-manager.

Создание подключения.

Необходимо создать подключение к гипервизору QEMU/KVM.

Предварительная настройка создания виртуальной машины.

В данном примере для установки Win10 в качестве гостевой ОС используется базовая конфигурация. Далее будет проделана дополнительная настройка виртуальной машины, чтобы осуществить проброс видеокарты, успешно установить драйвер и обойти нелепые искусственные ограничения Nvidia («ошибка 43» и BSOD из-за отключенного MSI).

Официальный установочный образ Win10 в формате ISO:

https://www.microsoft.com/ru-ru/software-download/windows10ISO

Образ будет использоваться для установки с использованием эмуляции CD-ROM.

Шаг 0.

Файл / Создать виртуальную машину

Шаг 1.

В методе установки выбрать «Локальный ISO или CDROM»:

Шаг 2.

Выбрать ранее загруженный установочный образ:

В этом же шаге выбрать тип устанавливаемой ОС. Это важно для подтягивания мета-информации, в зависимости от которой предоставляются те или иные настройки в Virt-manager и libvirt. Для отображения полного списка отметить «Include end of life operating systems»:

Шаг 3.

Указать количество ОЗУ и потоков для виртуальной машины.

В данном примере для гостевой ОС будет выделено 16384 Мб из 32768 Мб ОЗУ и 8 из 12 потоков процессора.

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

Шаг 4.

Необходимо указать образ виртуального накопителя, в который будет установлена гостевая (виртуализируемая) ОС.

В libvirt используются специальные хранилища данных, что делает задачу несколько нетривиальной. Ознакомиться можно здесь: https://libvirt.org/storage.html

В примере создаётся хранилище данных с названием pool и типом «Каталог в файловой системе»; в строке Target Path указывается путь до каталога в файловой системе хоста, в котором по итогу расположится хранилище данных.

При выборе места для хранилища стоит учитывать достаточное количество свободного места на физическом накопителе. Для Win10 желательно от 60 Гб.

Хранилище создано. Теперь необходимо создать сам образ виртуального накопителя, в который будет установлена Win10.

Формат: raw. Оптимален для Windows-гостей.

Объём: 60 Гб

Подтвердить создание.

Созданный виртуальный накопитель появится в списке томов. Останется выбрать его.

На этом четвёртый шаг заканчивается.

Шаг 5.

Отметить пункт «Проверить конфигурацию перед установкой»:

Это позволит перейти к непосредственной настройке виртуальной машины.

Подробная настройка виртуальной машины.

Обзор.

Выбрать набор микросхем q35. Он лучше поддерживает проброс.

Выбрать прошивку (firmware) ovmfOVMF_CODE.fd.

Применить изменения.

Информация об ОС.

Убедиться, что выбрано Windows 10, так как это подтягивает мета-информацию, которая влияет на доступные настройки Virt-manager и libvirt.

Процессоры.

В этой вкладке указывается число потоков, конфигурация (модель процессора) и топология процессора. В данном примере копируется конфигурация хоста с разделением на 8 потоков: 4 ядра умножаются на 2 потока, что имитирует гиперпоточность.

Память.

Для гостя выделяется 16384 Мб ОЗУ. Всего в системе 32 Гб.

Параметры загрузки.

Переставить SATA CDROM 1, к которому примонтирован установочный образ, на первое место, тем самым повысив приоритет загрузки:

Иначе процесс установки не сможет начаться. Можно будет лишь наблюдать интерфейс UEFI Interactive Shell, в котором придётся указать путь до загрузочной области вручную:

SATA Диск 1.

Ранее созданный виртуальный накопитель подключается через эмуляцию шины SATA:

В параметрах производительности переключить «Режим кэширования» на «none», а «Режим ввода-вывода» на «native». Это улучшит отзывчивость и позволит избежать потери данных при принудительном выключении виртуальной машины.

Можно подключать несколько виртуальных и даже физических накопителей. Последнее несколько нетривиально и имеет ряд ограничений.

SATA CDROM 1.

Эмуляция CD-ROM устройства, подключенного по шине SATA. В него примонтирован установочный образ.

После установки гостевой ОС устройство SATA CDROM 1 можно удалить.

NIC (Настройки сети).

Если используется обычная конфигурация сети, то можно оставить как есть.

Планшет.

Подобные устройства правильнее пробрасывать в виртуальную машину. Поэтому эмулируемое устройство лучше удалить.

Дисплей VNC.

Заменить VNC на «Сервер SPICE» и убрать прослушивание (Listen type), так как виртуализация будет локальной:

Этот протокол более предпочтителен, когда требуется передача звука от гостя к хосту. Так же у него нет проблемы с «залипанием» курсора по краям экрана.

Консоль.

Для Windows-гостей это не требуется, поэтому лучше удалить.

Видео QXL.

Это виртуальный графический адаптер, поддерживающий 2D ускорение. Будет выводить графику, пока не задействована проброшенная физическая видеокарта.

Controller USB 0.

Оставить по умолчанию.

Теперь всё готово для установки ОС, останется нажать кнопку «Начать установку».

После подтверждения будет запущена виртуальная машина с процессом установки:

Курсор из окна виртуальной машины освобождается комбинацией Ctrl + Alt.

С установкой Win10 предлагаю разобраться самостоятельно. Основная сложность в том, что каждое крупное обновление появляются всё новые и новые преграды для отказа от навязываемой учётной записи MS и прочего «ненужно». На момент 2021 года только для отказа от некоторой(!) части телеметрии предлагается снять более десятка галочек, которые, как в головоломке, надёжно спрятаны в графическом интерфейсе и разнесены на несколько окон. Стоит отметить, что без применения спецсредств отключить основную массу телеметрии невозможно.

После установки и завершения работы виртуальной машины можно удалить SATA CDROM 1:

Нюансы Windows.

  • Интерфейс схож с KDE Plasma, но намного менее привлекательный и довольно неудобный, особенно меню запуска («Пуск») и файловый менеджер с его «десятиэтажной» верхней панелью (ужас-ужас). Всё это «приправляет» графический разнобой: мутные шрифты в одном месте и чёткие в другом; в файловом менеджере своё оформление окон, в панели управления другое, в настройках вообще третье. Вся эта «биполярная» картина создаёт удручающее впечатление, но пережить можно.
  • «Из коробки» вас встретит ужасающее количество мусорных программ: от полностью никчёмных, навроде Paint 3D, OneDrive, ознакомительной версии MS Office и так далее, до рекламы в меню запуска («Пуск»). Вся эта «красота», если верить тестам, отбирает до 7% производительности в 3D(!) программах, создаёт невменяемое количество прерываний (interrupts) и очень любит устраивать зашкаливающую пилообразную нагрузку как для процессора, так и для накопителя. Поэтому первым делом вам предстоит избавиться от всего лишнего. Работа непростая, но необходимая.
  • НИ В КОЕМ СЛУЧАЕ недопускайте обновления драйверов на видеокарту через менеджер обновлений Windows. Это может привести к полной неработоспособности Win10.
  • Недопустимо, чтобы хост уходил в гибернацию и сон с запущенной виртуальной машиной. Это может привести к полному зависанию хоста или проброшенной видеокарты.
  • На госте с Windows очень нежелательно применять гибернацию и сон, так как это может привести к зависанию проброшенной видеокарты.
  • Образ виртуального накопителя в формате raw можно примонтировать, как обычный накопитель, что позволит производить чтение и запись хостом. При этом есть ряд важных ограничений, в особенности для файловой системы NTFS:
    • Без крайней необходимости не осуществляйте запись от хоста на виртуальный накопитель. Одновременная запись хоста и гостя может привести к сбою файловой системы на виртуальном накопителе. Запись от хоста должна осуществляться только при выключенном(!) госте.
    • Если работа гостя была завершена переходом в сон, гибернацию, сбоем или принудительным выключением, то запись от хоста даже при выключенном госте может повредить файловую систему.
      • Восстановление файловой системы NTFS возможно Win-утилитой chkdsk, при этом повреждённые записи будут удалены с потерей затронутых файлов.

Проброс видеокарты Nvidia.

Базовый проброс видеокарты.

Осуществялется через Virt-manager.

Перед началом настройки необходимо завершить работу виртуальной машины.

Открыть настройки виртуальной машины и найти кнопку «Добавить оборудование». В списке выбрать видеоустройство видеокарты и аудиоустройство.

Для GTX 1060 результат выглядит так:

Установка драйвера Nvidia.

Подготовка гостя.

После зачистки Win10 и установки нормального браузера предстоит продолжить подготовку проброса для того, чтобы обойти препоны драйвера Nvidia.

Вручную загрузить драйвера для видеокарты с официального сайта: https://www.nvidia.ru/Download/

Для установки потребуется перейти в безопасный режим, иначе установка будет прервана BSOD («синим экраном смерти») и не завершится корректно. После такого сбоя потребуется удалять то, что успело установиться, специальной утилитой (DDU или подобной).

Переход в безопасный режим можно осуществить следующим образом:

  • Нажать комбинацию клавиш META + R. В появившейся строке ввести msconfig и подтвердить.
  • В открывшемся окне перейти на вкладку «Загрузка» и отметить «Безопасный режим»:

Перезагрузиться.

Визуально безопасный режим будет выглядеть подобным образом:

Теперь можно установить драйвер, не опасаясь BSOD.

Для этого запустить ранее загруженный установочный файл.

В установочнике отметить «Выборочную установку», чтобы установить только драйвер без дополнительного софта:

Ни в коем случае не устанавливать предлагаемый GeForce Experience. Это очень проблемный софт, который становится ещё проблемнее на виртуальной машине.

Перезагрузиться, всё ещё оставаясь в безопасном режиме.

Теперь предстоит настроить MSI (Message Signaled Interrupts). Без этого в обычном режиме запуска будет происходить зацикленный BSOD с ошибкой VIDEO_TDR_FAILURE в драйвере nvlddmkm.sys.

Включение MSI для видеокарты Nvidia.

Оптимально включить вручную через реестр, создав специальный параметр.

Сначала необходимо узнать ID видеокарты, по которому её можно найти в реестре.

META + R и в появившейся строке ввести devmgmt.msc, а затем подтвердить.

Это откроет окно «Диспетчера устройств»:

Развернуть свиток «Видеоадаптеры», нажать на видеокарте ПКМ и выбрать «Свойства».

В «Свойствах» перейти во вкладку «Сведения». В списке найти «ИД оборудования». Первым в списке будет искомый ID видеокарты. Для GTX 1060: VEN_10DE&DEV_1C03&SUBSYS_1C0310DE&REV_A1

Теперь можно редактировать реестр. Это осуществляется стандартной утилитой regedit.

META + R и в появившейся строке ввести regedit. Откроется окно редактора реестра:

Необходимо проследовать в самые дебри:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\

И вот здесь должен быть раздел с тем самым ID видеокарты. В данном примере это VEN_10DE&DEV_1C03&SUBSYS_1C0310DE&REV_A1

Развернуть раздел с ID видеокарты, нажать ПКМ на разделе Device Parameters и создать раздел Interrupt Management:

Нажать ПКМ на разделе Interrupt Management и создать раздел с именем MessageSignaledInterruptProperties:

Нажать ПКМ на созданном разделе и создать параметр DWORD (32 бита) с именем MSISupported:

Сделать двойной клик по параметру MSISupported и в появившемся окне присвоить значение равное 1 в шестнадцатеричной системе счисления:

Готово. Теперь можно закрыть редактор реестра.

Примечание: MSI может сбрасываться после обновления Win и драйвера для видеокарты. Поэтому придётся проделывать процедуру снова, но будет достаточно добавить параметр MSISupported, остальное должно остаться.

В msconfig включить обычный запуск:

Перезагрузиться.

Казалось бы, проделан такой большой путь и теперь уж точно всё должно работать, но не тут-то было. Nvidia так просто не сдаётся. Видеокарта всё ещё не будет работать из-за «ошибки 43»: «Система Windows остановила это устройство, так как оно сообщило что Nvidia в край обнаглела о возникновении неполадок».

Эта проблема решается маскировкой факта виртуализации для гостя.

Маскировка виртуализации для решения «ошибки 43».

Маскировка осуществляется в настройках виртуальной машины. Необходимо, чтобы гость был выключен.

Конфигурация виртуальной машины хранится в специальном файле в формате xml. Их можно редактировать с помощью утилиты virsh, но в данной статье ограничимся Virt-manager.

Редактирование конфига можно осуществить непосредственно через Virt-manager во вкладке XML (Edit libvrit XML). Пример настроенной конфигурации:

Маскировка разнесена на три блока:

  • domain / features / hyperv
  • domain / features / kvm
  • domain / cpu

hyperv.

В этот блок нужно добавить следующую строку:

<vendor_id state="on" value="FckYouNVIDIA/>

Целиком будет выглядеть так:

<hyperv>
  <relaxed state="on"/>
  <vapic state="on"/>
  <spinlocks state="on" retries="8191"/>
  <vendor_id state="on" value="FckYouNVIDIA"/>
</hyperv>

Строка vendor_id доступна для чтения из гостевой ОС. Драйвер Nvidia проверяет её наличие. Если она отсутствует, то это является одиним из поводов показать «ошибку 43».

Cтроке value может быть присвоен любой набор из 12 символов. В «классическом» варианте можно указать следующее: FckYouNVIDIA

kvm.

По умолчанию блок kvm отсутствует. Его необходимо самостоятельно добавить в блок features.

<kvm>
  <hidden state="on"/>
</kvm>

Строка отвечает за опцию маскировки использования гипервизора kvm от обнаружения гостем. Драйвер Nvidia проверяет этот момент и при обнаружении признаков использования kvm покажет «ошибку 43».

cpu и host-passthrough.

Основной задачей является пробросить информацию о процессоре хоста, предоставить гостю возможность напрямую использовать процессорный кэш и отключить оптимизации гипервизора, которые явно указывают на то, что гостевая ОС запущена на виртуальной машине. Этот факт будет легко обнаружен драйвером Nvidia, что вновь приведёт к «ошибке 43».

По умолчанию этот блок будет выглядеть схожим образом:

<cpu mode="host-model" check="partial">
  <topology sockets="1" cores="4" threads="2"/>
</cpu>

Гостевой ОС будет предоставлено только название процессора без проброса детаельной информации и кэша. Это необходимо исправить.

Конечный результат будет выглядеть так:

<cpu mode="host-passthrough" check="none">
  <topology sockets="1" cores="4" threads="2"/>
  <cache mode="passthrough"/>
  <feature policy="require" name="invtsc"/>
  <feature policy="disable" name="hypervisor"/>
</cpu>

Режим проброса указывается следующей строкой:

<cpu mode="host-passthrough" check="none">

Далее указывается топология ядер процессора. В данном случае это 8 потоков (4 ядра умножаются на 2 потока, что имитирует гиперпоточность):

<topology sockets="1" cores="4" threads="2"/>

Проброс процессорного кэша:

<cache mode="passthrough"/>

Это значительно улучшает производительность гостевой ОС.

Опция invtsc улучшает обработку прерываний для Win-гостя, что позитивно сказывается на производительности:

<feature policy="require" name="invtsc"/>

Она не критична для маскировки, но очень желательна для улучшения работоспособности.

Отключение оптимизаций гипервизора:

<feature policy="disable" name="hypervisor"/>

Гостевая ОС не будет видеть, что запущена на виртуальной машине. Драйвер Nvidia тоже не сможет определить факт виртуализации, что наконец избавит от «ошибки 43».

Применить изменения.

Заключительная часть.

Наконец всё готово и видеокарта сможет свободно работать в гостевой ОС!

Ключевым признаком работы проброшенной видеокарты будет «зависание» картинки в окне просмотра Virt-manager. Если используется один монитор, то потребуется переключить видеорежим, чтобы увидеть графику гостевой ОС.

Рабочий стол будет отображаться в полноэкранном режиме:

Останется испытать производительность.

Рекомендую следующие программы для тестирования производительности:

  • LatencyMon — предназначена для измерения задержек прерываний. Чем выше задержки, тем сильнее проявляются «заикания».
  • Cinebench — тестирование производительности процессора.
  • Unigine Superposition Benchmark — общее тестирование производительности.

Набор незамысловат, но позволяет ясно увидеть уровень производительности. Забегая вперёд скажу, что производительность будет заметно меньше, чем при нативном запуске, но это можно исправить, сократив накладные расходы до минимума.

Варианты оптимизации рассмотрены в отдельной статье: https://noostyche.ru/blog/2021/03/30/optimizaciya-virtualizacii-win10-qemu-kvm/

Проблема с отсутствием звука в виртуальной машине.

Как правило, при использовании протокола SPICE со звуком проблем нет, но бывают исключения.

Звук может отсутствовать из-за блокировки apparmor. Проверка наличия предупреждений о блокировке:

cat /var/log/syslog | grep -i 'apparmor="DENIED"'

Если блокировка отсутствует, то вывод будет пустой.

При наличии предупреждений, самым простым способом является отключение защиты через конфигурационный файл /etc/libvirt/qemu.conf. Защита будет отключена только для виртуальных машин, запускаемых с использованием libvirt.

За использование защиты отвечает следующая строка:

security_driver = [ "selinux", "apparmor" ]

Для отключения необходимо добавить строку со значением «none»:

security_driver = "none"

Для применения изменений перезапустить libvirtd:

sudo service libvirtd restart


10 отзывов к статье “qemu-kvm, libvirt и проброс видеокарты Nvidia.”

  • 1
    Иван в 02.06.2021 Ответить

    Спасибо.

  • 2
    Андрей в 17.12.2021 Ответить

    Привет. Спасибо за статью.
    Все сдела по инструкции, но получаю ошибку видео карты:

    «Недостаточно свободных ресурсов для работы данного устройства. (Код 12)
    Если вы хотите использовать это устройство, отключите одно из других устройств в системе.»

    Видео карта — GeForce GTS 450
    Гостевая ОС — Windows 10

    • 3
      Igor в 22.12.2021 Ответить

      Привет. На здоровье.

      Вроде бы, сталкивался с подобным. Перезагрузка хоста не помогла? Устройство точно не используется хостом? Проприетарный драйвер должен быть удалён, иначе драйвер vfio не сможет нормально подхватить видеокарту.
      «Магия» против обнаружения виртуализации применена?
      Так же стоит проверить IOMMU-группу. Она есть для устройства?

  • 4
    Сергей в 24.06.2022 Ответить

    Igor, благодарю за эту статью с подробной инструкцией и объяснениями.
    Я решил попробовать этот вариант (QEMU-KVM GPU passthrough), поскольку меня не устроила потеря производительности при запуске Windows 10 guest в VirtualBox на Linux host — производительность 3D по сравнению с нативной упала аж в 11 раз: я использовал для замеров производительности Furmark GPU stress test, на нативной результат 77 FPS, на VirtualBox — 7 FPS.
    В интернете я нашёл обещания, что QEMU-KVM GPU passthrough вариант может дать производительность «почти без потерь», вот я и решил попробовать.
    В итоге проброс видеокарты по вашей инструкции сделать получилось. Единственное, был такой нюанс: у меня видеокарта Nvidia Quadro M4000M, и, видимо, поэтому «ошибка 43» не возникла до маскировки виртуализации, а, наоборот, появилась сразу после маскировки (в инетах пишут, что карты Quadro лояльны к виртуализации). Чтобы оставить маскировку, но убрать «ошибку 43», я удалил в XML настройках в блоке строку «», и это сработало. Таким образом, судя по моему опыту, карточки Quadro обижаются, когда их «посылают»).
    Но что в итоге с производительностью 3D? А вот что: в варианте с пробросом видеокарты на QEMU-KVM производительность оказалась ещё в разы хуже, чем на VirtualBox, а именно 1 FPS (!!!), что в 7 раз ниже, чем на VirtualBox, и в 77 (!!!) раз ниже, чем на нативной винде.
    Печально, но из-за необходимости работы в 3D приложениях, придётся мне вернуться к винде.

    Или, может быть, я что-то не так сделал? Может, это только у меня такое падение производительности? У вас как? В чём причина? Есть идеи? Стоит ли пробовать добавить Looking Glass, может ли это принципиально изменить картину в лучшую сторону?

    • 5
      Igor в 10.07.2022 Ответить

      Нужно убедиться, что драйвер был установлен и работает. Это можно проверить через Диспетчер устройств. Так же нужно проверить нагрузку на процессор. При виртуализации Windows может проявиться очень неприятная проблема, когда система отказывается видеть виртуальные ядра, кроме одного, что приводит к его загруженности на 100%. Именно из-за этого производительность будет драматически низкой. Решается пробросом процессора и конкретных потоков.

      Печально, но из-за необходимости работы в 3D приложениях, придётся мне вернуться к винде.

      Все основные 3D приложения работают на Linux. От Blender и Maya до Mari и набора Substance.

    • 6
      Igor в 10.07.2022 Ответить

      Варианты решения проблемы с ядрами и увеличения производительности в целом описаны в этой статье: https://noostyche.ru/blog/2021/03/30/optimizaciya-virtualizacii-win10-qemu-kvm/

  • 7
    Сергей в 24.06.2022 Ответить

    Единственное, был такой нюанс: у меня видеокарта Nvidia Quadro M4000M, и, видимо, поэтому «ошибка 43» не возникла до маскировки виртуализации, а, наоборот, появилась сразу после маскировки (в инетах пишут, что карты Quadro лояльны к виртуализации). Чтобы оставить маскировку, но убрать «ошибку 43», я удалил в XML настройках в блоке «» строку «», и это сработало. Таким образом, судя по моему опыту, карточки Quadro обижаются, когда их «посылают»).

    • 8
      Igor в 10.07.2022 Ответить

      Да, должны пробрасываться без дополнительных манипуляций.

  • 9
    ILYA POGORYANSKIY в 21.05.2023 Ответить

    Добрый, подскажите, правильно ли я понял, что для проброса нужна вторая физическая видеокарта не задействованная в выводе на монитор изображения в самом линуксе? Ну т.е. к первой подключены физически провода для вывода изображения на монитор, а пробрасываем вторую, не задействованную?

    • 10
      Igor в 15.06.2023 Ответить

      Привет. В теории можно с одной. Необходимо переключить отрисовку графики для хоста на программную (LLVMpipe или Lavapipe), а видеокарту дать захватить драйверу vfio. Я использовал вариант с двумя видеокартами, где видеовыводы от видеокарт подключены к одному монитору, а переключение между ними осуществлялось через переключение видеовыводов в меню монитора.

Добавить комментарий для Igor Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *