Я сижу под 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.

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


  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. Johan_Palych
        23.06.2025 19:21

        Есть Sunshine fork - Apollo. Добавлены фичи.


        1. Testman2023
          23.06.2025 19:21

          Будем посмотреть


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

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


          1. alan008
            23.06.2025 19:21

            Затычку для HDMI не предлагать?

            На озоне гуглится по фразе "hdmi эмулятор". Цена 300 р.


      1. Kirthgreat4
        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. fshp
      23.06.2025 19:21

      Потоки smt не урезанные. Это 2 ядра с одним АЛУ. Т.е. два набора регистров, но в один момент времени обрабатывается только один из них. Выигрыш только за счёт того, что уменьшается количество переключений контекста, который в противном случае должен быть сохранен, а потом восстановлен из оперативки.

      Конечно, если выделить виртуалке два потока одного ядра под видом двух обычных ядер, то чуда не произойдёт. Но qemu умеет задавать топологию cpu, а libvirt пинить потоки kvm на ядра cpu.

      Урезанные это энергоэффективные ядра у intel.


      1. vbaev
        23.06.2025 19:21

        Да не правильно сказал, при hyper treading это не урезанное ядро, а часть полного ядра, которая может дать прирост максимум 40% при удачных условиях и работе в паре с основным. Малые ядра Интел без HT значительно быстрее чем smt ядра


      1. Viacheslav01
        23.06.2025 19:21

        В спуерскалярных процессорах алу не одно, именно в эту особенность и метится smt, т.к. зависимость по входу и выходу одного потока команд часто не позволяет загрузить все исполнительные порты, а два потока вполне себе независисмы и позволяют использовать простаивающие порты исполнения.

        Два набора регистров в общем случае не нужно, регистров переименования вполне хватит для этих нужд.

        Выполнение команд разных потоков идет именно параллельно, а не последовательно. Прирост производительности в основном из за этого, а не из за экономии на переключении контекста, хотя переключение тоже экономит. А 100% производительности трудно достичь из за конкуренции за порты исполнения.

        Но если сделать синтетику в которой потоки не конкурируют за порты, например считают только простые операции int или в одном потоке int а во втором float то 100% вполне реальны. А вот если два потока считают например одни и те же операции для которых есть только один порт исполнения, то прибавка будет стремиться к нулю.


        1. fshp
          23.06.2025 19:21

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

          А АЛУ из общего пула используются, или у двух потоков свой набор и к соседям лезть они не могут?


          1. Viacheslav01
            23.06.2025 19:21

            Отличный вопрос, зависит от того, что для вас АЛУ.

            Если брать классику цпу без суперскалярности, то в ядре одно АЛУ которое действительно может выполнять одно действие за раз. И при таком раскладе СМТ действительно имело бы выигрыш только в виде в двое сокращенного времени переключения контекста.

            В суперскалярном процессоре, алу это набор портов исполнения и все они специализированные, т.е. это может быть например:
            1) 2 порта для простых int операций, таких как сложение, вычитание, сдвиг, битовые оперции.
            2) 2 порта для сложных int операций, таких как умножение/деление.
            3) 2 порта float
            4) 2 порта загрузка/сохранение

            Теоретические такая конфигурация позволяет выполнять 8 команд одновременно. Но заполнить работой все эти устройства тоже не так просто.

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

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

            А в случае если есть smt загрузка станет еще выше за счет того, что у процессора будет N потоков независимых команд.

            Физически да как минимум у такого процессора будет по декодеру команд на поток и по копии управляющих и архитектурных регистров.

            С другой стороны у нас есть VLIW у которой вообще 100500 портов исполнения и компилятор собирает программу так, что бы максимально загрузить все порты исполнения, но сам процессор ничего не делает для их загрузки. Поэтому потенциально оно может работать очень быстро, на что и надеялись, а на практике увы. Опять же там smt не возможна в принципе, т.к. команды выполняются строго последовательно.


  1. 0x131315
    23.06.2025 19:21

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


    1. Lev3250
      23.06.2025 19:21

      Я бы посмотрел на такой монитор...


      1. fshp
        23.06.2025 19:21

        На Samsung это неюзабельно. Экран делится на 2 половинки, куда вписывется изображение в оригинальном разрешении со всеми вытекающими глазами артефактами даунскейла. HDR не работает. Ну а справа WiDi, потому что второй источник только по воздуху можно пустить, но не по кабелю. Половина площади не задействована.


        1. Lev3250
          23.06.2025 19:21

          Вот о чем и речь. Тот идеальный монитор с картинкой в картинке, что описывает человек выше, если и существует, то я такого не видел. Интересна модель. А такие, как этот самсунг, они не подходят


          1. Alpine_Ice
            23.06.2025 19:21

            Ну например dell u3824dw вполне... если я правильно понял о чем речь...


          1. 0x131315
            23.06.2025 19:21

            Таких мониторов много, нужно искать по запроcу "мониторы с pip". А вот инфы об этом к сожалению мало - мало кто это реально использует.

            В мониторах есть два режима: pip и pbp. В режиме pip можно менять размер и позицию субокна, в режиме pbp экран делится на две половинки, и там уже ничего толком не регулируется.

            Примеры настроек меню:

            И как это выглядит https://www.youtube.com/watch?v=qvt_7CUu898 правда тут моник маленький у человека, так что выглядит скорее забавно, чем полезно

            Чтобы это нормально использовать, нужна достаточно большая панель, порядка 40-50 дюймов, чтобы окно другой ОС воспринималось полноценно, как обычное FullHD окно, тогда там текст нормального размера, легко читаемый, и можно открыть какое-нибудь приложение на "весь экран" в пределах выделенной области, чтобы оно воспринималось просто как отдельное окно на хосте. Если потребуется, в меню, или по кнопке с пульта, можно менять источники местами (быстро растянуть окно на всю панель), перекидывать аудиопоток (если это не виртуалка, тогда внутри хоста звук не микшируется) или переключать kvm.


  1. Habr4687544
    23.06.2025 19:21

    Интересно! Когда-то у меня был вот такой сетап: пека с виндой и хорошей видеокартой стоит под столом, для игр и прочего. На столе ноутбук для работы. И тот и другой подключены к двум моникам, так что можно кнопками выбора видеовхода переключаться. В один прекрасный день совмещать игры и работу показалось губительным для продуктивности, и пека уехала под стол в соседнюю комнату на рабочее место жены. Пока такой сетап считаю идеальным, рабочая и не рабочая зоны разделены, лучше концентрируюсь на задачах, и лучше отдыхаю за играми.