Я сижу под Linux, но иногда нужна винда. До недавнего времени у меня был обычный dual boot, но сейчас я реализовал свой идеальный сетап:

  • основная система - Linux

  • Windows - на выделенной SSD

  • на нее можно загрузиться как из груба, так и из виртуалки

  • с пробросом второго GPU (дисплей на отдельный физический выход)

  • с качественным удаленным подключением (как RDP, но быстрое) - можно играть в игры

Ниже опишу что и как сделал.

Не является руководством к действию, я в процессе этих игр одну инсталляцию загубил - накосячил с драйверами видеокарт. Все действия - на свой страх и риск.

Тема уже поднималась на Хабре, вот например хорошая статья.

Что нам потребуется

Нам потребуется:

  1. выделенный SSD NVMe для установки Windows.

  2. вторая видеокарта (вообще можно одну, но я пока не заморачивался со скриптами автоматического отключения/подключения GPU на лету; вот этот тип сделал нормально)

  3. подходящая аппаратная конфигурация:

    1. нужно чтобы IOMMU-группы совпали. Подробности ниже

    2. не все аппаратные средства поддерживают такую конфигурацию. Подробностей к сожалению нет, только мой опыт. Например, TeamGroup отказался пробрасываться, а Samsung согласился (не реклама!).

  4. немного настроек

IOMMU-группы

Если вкратце, то все оборудование на аппаратном уровне сгруппировано по каким-то неведомым нам критериям в IOMMU-группы. Программно перегруппировать оборудование нельзя, но можно переключить в другой разъем.

Все пишут, что их нужно в явном виде включать, но у меня они завелись сразу после установки хостовой ОС.
Посмотреть группы можно командой:

sudo dmesg |grep iommu

У меня получилось вот так:

Мои IOMMU группы и ID устройств. Если кому важно, Aorus Elite B550
Мои IOMMU группы и ID устройств. Если кому важно, Aorus Elite B550

Чтобы понять, что это за устройства, нужно выполнить команду:

lspci
lspci|grep NVMe
lspci|grep VGA
lspci|grep NVMe - да, у меня две NVMe одного вендора
lspci|grep NVMe - да, у меня две NVMe одного вендора

В моем вариант это две NVMe (на одной работает Linux, вторую отдаю под Винду) и две видеокарты.

Давайте посмотрим, что там по группам для интересующих нас устройств, id которых мы узнали выше:

sudo dmesg |grep iommu| grep "01:00.0" -A1 -B1
IOMMU группы для интересующих нас NVMe и GPU
IOMMU группы для интересующих нас NVMe и GPU

Получается, что NVMe 0000:01:00.0 одна в своей группе iommu group 14, а вот Radeon RX и вторая NVMe - нет, они в группе 15 вместе с кучей других устройств. Их передать абсолютно нереально. Однако, с картой NVIDIA нам тоже повезло: она тоже в отдельной группе №16; пусть вас не смущает еще одно устройство рядом, это всего лишь Audio device: NVIDIA Corporation GP104 High Definition Audio Controller (rev a1). То есть звук через HDMI с той же видеокарты.

Все сошлось, можем начинать настройку.

Пробросить SSD

Итак, мы определились, какую NVMe мы будем прокидывать в виртуалку, и по счастливой случайности основная система стоит не на ней. На самом деле нет, и мне изначально пришлось менять местами NVMe, но это не важно для наших целей. Это устройство с id 01:00.0.

Создаем виртуалку через обычный virt-manager. А чтобы он не спрашивал пароль sudo каждый раз при подключении, можно добавить себя в правильную группу:

sudo usermod -a -G libvirt $(whoami)

Windows будем ставить сразу на виртуалку:

Создаем виртуалку, готовимся ставить Windows из iso
Создаем виртуалку, готовимся ставить Windows из iso

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

Диск не согздаем, вместо него будет SSD NVMe
Диск не согздаем, вместо него будет SSD NVMe

Обязательно нажимаем "Проверить конфигурацию перед установкой". Нам нужно еще кое-что поменять, прежде чем запускать виртуалку и ставить Windows.

Обязательно проверить конфигурацию перед установкой
Обязательно проверить конфигурацию перед установкой

ВАЖНО!!! Переходим в первый пункт "Обзор" и выбираем BIOS/UEFI. Надо выбрать то же самое, на чем у вас работает основная система. Чтобы GRUB ее мог увидеть.

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

Сверь BIOS/UEFI с хостом чтобы работал dual boot
Сверь BIOS/UEFI с хостом чтобы работал dual boot

Далее выбираем "Добавить оборудование" - "PCI-устройство узла" и наше NVMe устройство.

Проброс PCI-устройства NVMe
Проброс PCI-устройства NVMe

Остальное можно на первых порах оставить без изменений. Все, виртуалка готова.

Если все прошло как надо, виртуалка успешно увидела NVMe, установила Windows и загрузилась. Вот только видео через virt-manager оставляет желать лучшего... Хотя уже сейчас можно нормально подключаться по RDP и работать с документами. А вот играя даже в простую пошаговую Heroes3 я все глаза себе сломал.

Дисплей QXL, на гостевой машине виден Базовый видеоадаптер. GPU нет.
Дисплей QXL, на гостевой машине виден Базовый видеоадаптер. GPU нет.

Можем проверить состояние устройств командой:

$ lspci -nnk|grep NVMe -A3
01:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller 980 (DRAM-less) [144d:a809]
	Subsystem: Samsung Electronics Co Ltd Device [144d:a801]
	Kernel driver in use: vfio-pci
	Kernel modules: nvme
0c:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller 980 (DRAM-less) [144d:a809]
	Subsystem: Samsung Electronics Co Ltd Device [144d:a801]
	Kernel driver in use: nvme
	Kernel modules: nvme
vfio-pci для NVMe появился; NVMe недоступна с хоста, но видимо как устройство
vfio-pci для NVMe появился; NVMe недоступна с хоста, но видимо как устройство

Откуда взялось вот это, я если честно сам не понял. Само собой появилось: Kernel driver in use: vfio-pci. После отключения виртуалки драйвера вернулись в норму, vfio ушел.

vfio-pci для NVMe ушел, виртуалка выключена; NVMe можно примонтировать к хосту и пользоваться
vfio-pci для NVMe ушел, виртуалка выключена; NVMe можно примонтировать к хосту и пользоваться

GRUB

Ну а теперь обновляем конфигурацию GRUB. Только ОБЯЗАТЕЛЬНО нужно выключить виртуалку, а то он не видит отданную ей NVMe.

sudo grub2-mkconfig -o /etc/grub2-efi.cfg
Хоба! Винда с виртуалки нашлась!
Хоба! Винда с виртуалки нашлась!

Можем перезагрузиться и проверить (хотя и не обязательно делать это прямо сейчас, у нас еще есть дела в хостовой ОС).

Windows, изнчально установленная на виртуалку, теперь видна в GRUB
Windows, изнчально установленная на виртуалку, теперь видна в GRUB

Изоляция GPU

Надо сделать так, чтобы хостовая операционная система не пользовалась видеокартой. Иначе libvirtd пытается обратиться к работающей видеокарте, чтобы добавить ее к виртуалке, ждет ответа - а ответа все нет, и в итоге он зависает наглухо. Чтобы ее отключить в процессе работы, нужно перезапускать всю графику. Снова отсылаю за подробностями к мужчине с ютуба.

Вот тут предлагают разные рецепты как застравить загрузиться драйвер vfio-pci вместо стандартного, но сколько я ни бился, на NVIDIA GeForce GTX 1070 у меня он не подцеплялся. Но раз уж я решил использовать ее только для виртуалки, мне не нужны отдельные драйвера для нее. Мне нужно только "изолировать" ее, то есть сделать так, чтобы она не запускалась.

Поэтому - удаляем драйвер nvidia если есть и блеклистим стандартный драйвер nouveau. Для этого идем сюда (зависит от дистрибутива):

sudo vi /etc/default/grub

И дописываем в конец переменной GRUB_CMDLINE_LINUX блокировку драйверов rd.driver.blacklist=nouveau,nova_core modprobe.blacklist=nouveau,nova_core. Вся строчка в моем случае выглядить так:

GRUB_CMDLINE_LINUX="resume=UUID=7acc885c-d6e8-489a-a63d-0b5bd28f0c7a rhgb quiet rd.driver.blacklist=nouveau,nova_core modprobe.blacklist=nouveau,nova_core"

Перезаписываем конфигурацию grub:

sudo grub2-mkconfig -o /etc/grub2-efi.cfg

Как будем проверять драйвера? Давайте зафиксируем, какие драйвера работают сейчас и сравним:

$ lspci -nnk|grep NVIDIA -A3
0e:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP104 [GeForce GTX 1070] [10de:1b81] (rev a1)
	Subsystem: NVIDIA Corporation GP104 [GeForce GTX 1070] [10de:1b81]
	Kernel driver in use: nouveau
	Kernel modules: nouveau
0e:00.1 Audio device [0403]: NVIDIA Corporation GP104 High Definition Audio Controller [10de:10f0] (rev a1)
	Subsystem: NVIDIA Corporation Device [10de:1b81]
	Kernel driver in use: snd_hda_intel
	Kernel modules: snd_hda_intel

Перезагрузка! И вот что мы видим:

$ lspci -nnk|grep VGA -A3
0b:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 24 [Radeon RX 6400/6500 XT/6500M] [1002:743f] (rev c7)
	Subsystem: Sapphire Technology Limited Device [1da2:e458]
	Kernel driver in use: amdgpu
	Kernel modules: amdgpu
0e:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP104 [GeForce GTX 1070] [10de:1b81] (rev a1)
	Subsystem: NVIDIA Corporation GP104 [GeForce GTX 1070] [10de:1b81]
	Kernel modules: nouveau

Kernel driver in use пропал. Дополнительно, у меня погас третий монитор, включенный в видеокарту NVIDIA.

Изоляция завершена, можно пробрасывать.

Проброс GPU в виртуальную машину

Итак, пробрасываем PCI-устройство:

Проброс PCI GPU
Проброс PCI GPU

Жмем старт и... получаем ошибку:

Ошибка при PCI Passthrough
Ошибка при PCI Passthrough

Но рано расстраиваться. Читаем текст:

{"driver":"vfio-pci","host":"0000:0e:00.0","id":"hostdev1","bus":"pci.6","addr":"0x0"}: vfio 0000:0e:00.0: group 16 is not viable
Please ensure all devices within the iommu_group are bound to their vfio bus driver.

Он ругается на то, что не все устройства из группы № 16 были проброшены. А что у нас там за устройства?

IOMMU группа №16
IOMMU группа №16

Добавляем второе устройство тоже. И тут у меня оживает третий монитор, подключенный напрямую к видеовыходу. И о чудо! мы видим из винды карту NVIDIA!

Дисплей QXL, на гостевой машине виден GPU
Дисплей QXL, на гостевой машине виден GPU

И экранов у виртуалки два: виртуальный QXL и физический с выхода видеокарты:

Два дисплея на виртуалке QXL и физический с выхода видеокарты
Два дисплея на виртуалке QXL и физический с выхода видеокарты

Осталось две проблемы:

  1. через окошко Spice-QXL по-прежнему все тормозит

  2. не получается управлять курсором на отдельном мониторе

    Давайте пробросим второй комплект клавиатура-мышь. Это легко делается стандартными средствами virt-manager:

Пробрасываем нужные нам USB-устройства
Пробрасываем нужные нам USB-устройства

Сюрприз от CPU

Ну все, теперь можно играть... "Герои" летают, но почему же так люто тормозит Балда? Даже скриншотов не поделал, так сильно руки тряслись. Жесткий норм, видеокарта норм, памяти я вагон целый отсыпал... остался процессор. Что не так?

Угадайте, что не так
Угадайте, что не так

Нашел объяснение, что виртуалка плохо переносит такую конфигурацию ЦПУ.

Вот как это выглядит изнутри виртуалки:

Два виртуальных CPU? почему так?
Два виртуальных CPU? почему так?

В итоге получилось переделать конфигурацию процессора:

Вот теперь правильно нарезаны сокеты, ядра и потоки
Вот теперь правильно нарезаны сокеты, ядра и потоки

Изнутри тоже совсем другое дело. Играть стало нормально.

8 vCPU уже нормально. Игра идет как надо.
8 vCPU уже нормально. Игра идет как надо.

В итоге - виртуалка работает, сразу пробрасывает на видеовыход видеокарты. Можно играть в игры...

Избавляемся от лишних мониторов

...но неудобно держать отдельный монитор на столе только под эти цели. Равно как и неудобно постоянно перещелкивать действующий на второй вход.

Вот был бы такой RDP, чтобы как RDP только быстрее... И такие оказывается есть! И их достаточно много. Из бесплатного на помощь приходят Moonlight (клиент) и Sunshine (сервер). Настройка достаточно простая, по инструкции. Это веб-консоль сервера:

Sunshine
Sunshine

Это клиент:

Moonlight
Moonlight

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

Убираем виртуальный дисплей

Осталось немного прибраться. Давайте уберем виртуальные дисплеи. Для этого:

  1. Убираем USB перенаправители SpiceVMC, Канал (spice), Звук (они будут блокировать удаление дисплея)

  2. Видео именяем с QXL на None

  3. Удаляем вот эту часть из конфига (у меня дисплей Spice никак не хотел удаляться из графического интерфейса):

<graphics type="spice">
      <listen type="none"/>
      <image compression="off"/>
    </graphics>
    <audio id="1" type="spice"/>

Выводы

Итак, я собрал сетап мечты: основная система Linux и быстрая игровая виртуалка под Windows (хз зачем, под wine же тоже все норм было), в которую если надо можно загрузиться из UEFI на bare-metal.

Комментарии (11)


  1. jaelynn23
    23.06.2025 19:21

    короче: есть два стула


    1. Ghaeskaerr Автор
      23.06.2025 19:21

      Но теперь ты можешь садиться на один, не слезая с другого


      1. jaelynn23
        23.06.2025 19:21


        1. jaelynn23
          23.06.2025 19:21

          они знают
          с этой картинке планировал начать
          с этой картинке планировал начать


  1. PwrUsr
    23.06.2025 19:21

    Использую в чём то похожу конфигурацию под проксмоксом... основная задача система отдельно от прокса, то есть вытащил диск воткнул в другой комп (да хоть через переходник ЮСБ - проверено) и работай на своей любимой системе где надо (этакий 2GO своими руками)


  1. selfdoor
    23.06.2025 19:21

    отличная статья! использовал proxmox с проброшенной видеокартой, где в виртуальной машине крутилась винда, но вот про moonlight не знал, раздражал стандартный RDP. спасибо автору!


  1. nrndda
    23.06.2025 19:21

    Вместо блокирования загрузки nouveau и nova_core лучше отдать устройство в pci-stub или в vfio-pci : pci-stub.ids=1002:665c,1002:0002


    1. Ghaeskaerr Автор
      23.06.2025 19:21

      я это вскользь упомянул, у меня это почему-то не сработало: что бы я ни делал, драйвер был nvidia, устройство подхватывалось хостовой ОС и его уже нельзя было передать на виртуалку.
      надо будет еще покопать в этом направлении


      1. nrndda
        23.06.2025 19:21

        Нужно чтобы CONFIG_PCI_STUB или CONFIG_VFIO_PCI не были модулями. Если они включены модулями, то их надо добавлять в initrd, прописывать в modules-load и pci-stub.ids писать уже в modprobe. Через модули у меня нет опыта, только догадки.


  1. vbaev
    23.06.2025 19:21

    Здорово! А ещё на подумать у твоего процессор 6 ядер и 12 потоков. Это значит что 6 полноценных ядра и 6 smt урезанных.

    И у твоей виртуалке может оказаться 2 реальный и 6 smt. И ядра лучше выделять парами большое ядро и его же smt ) Ну и основная система не должна на эти ядра прыгать. Называется это NUMA

    Есть ещё двух чиплетные процессоры например 7900, там ты сможешь получить две независимые системы


  1. 0x131315
    23.06.2025 19:21

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