GVT-G – это технология, позволяющая виртуализировать встроенную в процессоры Intel Core видеокарту. Можно создать несколько таких виртуальных видеокарт и раздать виртуальным машинам. Каждая виртуальная машина будет иметь доступ к настоящему аппаратному 3d-ускорителю. Пока работает только под KVM и XEN. Есть возможность выводить картинку с этой виртуальной видеокарты на реальную. Но у нас же сервер. Нам не для игр. Поэтому ограничимся доступом по Remote Desktop.
1. Берем комп с процессором Intel Core поколения 5 или новее. В BIOS выставляем максимально возможный размер видеопамяти.
2. Ставим ubuntu 18.04. Мой любимый debian не подойдет, поскольку у него в ядре выключен CONFIG_DRM_I915_GVT_KVMGT. Можно пересобрать ядро самостоятельно, но нам же надо быстро.
3. Обновляем
# apt update # apt dist-upgrade -y
4. Ставим libvirt
# apt install libvirt-daemon-system
5. Добавляем в /etc/default/grub:
GRUB_CMDLINE_LINUX="i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=on i915.enable_guc=0"
Не забываем обновить конфиг:
# update-grub
Перезагружаемся и после перезагрузки убеждаемся, что у нас получилось:
# ls /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/ i915-GVTg_V5_2 i915-GVTg_V5_4 i915-GVTg_V5_8
В каждом из этих каталогов есть файл available_instances, в котором указано, сколько виртуальных видеокарт можно создать одновременно. В файле description написано, какие параметры будут у этих видеокарт.
6. Придумываем UUID и создаем виртуальную видеокарту.
# echo "df7aee77-abed-4c3c-b6b0-3e38db57f13d" > "/sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create"
Эту процедуру придется повторять руками после каждой загрузки или прибить гвоздями куда-нибудь в /etc/rc.local.
7. Создаем виртуалку примерно такого вида:
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> <name>win1</name> <uuid>d68571d2-3dd1-4aa2-a780-36160afff657</uuid> <memory unit='KiB'>3145728</memory> <currentMemory unit='KiB'>3145728</currentMemory> <vcpu placement='static'>2</vcpu> <os> <type arch='x86_64' machine='pc-q35-2.11'>hvm</type> <bootmenu enable='yes' timeout='3000'/> </os> <features> <acpi/> <apic/> <hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='8191'/> <vpindex state='on'/> <synic state='on'/> <stimer state='on'/> </hyperv> <vmport state='off'/> <ioapic driver='kvm'/> </features> <cpu mode='host-passthrough' check='partial'> <topology sockets='1' cores='2' threads='1'/> <cache mode='passthrough'/> </cpu> <clock offset='localtime'> <timer name='rtc' tickpolicy='catchup'/> <timer name='pit' tickpolicy='delay'/> <timer name='hpet' present='no'/> <timer name='hypervclock' present='yes'/> </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> <emulator>/usr/bin/kvm</emulator> <disk type='block' device='disk'> <driver name='qemu' type='raw' discard='unmap'/> <source dev='/virt/raw/win1/raw'/> <target dev='sda' bus='scsi'/> <boot order='1'/> <address type='drive' controller='0' bus='0' target='0' unit='0'/> </disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='/virt/iso/win10-64.iso'/> <target dev='sdb' bus='sata'/> <readonly/> <address type='drive' controller='0' bus='0' target='0' unit='1'/> </disk> <controller type='scsi' index='0' model='lsisas1068'> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </controller> <controller type='usb' index='0' model='qemu-xhci'> <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='sata' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> </controller> <controller type='pci' index='0' model='pcie-root'/> <controller type='pci' index='1' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='1' port='0x8'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='pcie-root-port'/> <target chassis='2' port='0x9'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> </controller> <interface type='bridge'> <mac address='54:52:00:e7:2f:2a'/> <source bridge='br-int'/> <model type='e1000'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <serial type='pty'> <target type='isa-serial' port='0'> <model name='isa-serial'/> </target> </serial> <console type='pty'> <target type='serial' port='0'/> </console> <input type='tablet' bus='usb'> <address type='usb' bus='0' port='1'/> </input> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes'> <listen type='address'/> </graphics> <memballoon model='none'/> </devices> </domain>
Ключевое тут – чипсет pc-q35-2.11.
8. Запускаем виртуалку, подключаемся по VNC и ставим Windows 10. Настраиваем сеть, разрешаем Remote Desktop. Подключаемся по Remote Desktop, скачиваем драйвера для видеокарты. Выключаем виртуалку.
9. Добавляем новое устройство vfio-pci c uuid нашей виртуальной видеокарты.
... </graphics> <hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci'> <source> <address uuid='df7aee77-abed-4c3c-b6b0-3e38db57f13d'/> </source> <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> </hostdev> <memballoon model='none'/> ...
10. Загружаем виртуалку, подключаемся по Remote Desktop и устанавливаем драйвер для видеокарты. На этом пункте уже можно остановиться, 3D на виртуальной машине уже есть. Но…
11. …поскольку примерно с п.9 подключаться по VNC бессмысленно (всегда будет только черный экран), можно убрать из xml вот этот блок:
<graphics type='vnc' port='-1' autoport='yes'> <listen type='address'/> </graphics>
и добавить дополнительный аргумент в командную строку qemu:
... </devices> <qemu:commandline> <qemu:arg value='-nographic'/> </qemu:commandline> </domain>
Вот теперь точно всё.