KVM, paso de PCI, Looking Glass y todo-todo-todo

Después de una transición exitosa a los desarrolladores de software de Linux, llegó el momento en que un poco de trabajo, y también cambió el sistema operativo principal. Las preocupaciones fueron causadas por el software de plataforma necro para apoyar proyectos existentes. Parte del software funcionó a través del vino. Sin embargo, resultó que cierto software se niega a trabajar bajo el vino. Se decidió ejecutar software en la máquina virtual QEMU + KVM. El software comenzó a ejecutarse, pero trabajar en él fue bastante inconveniente. Las tarjetas de video virtuales de software no difieren en rendimiento, y el soporte de gráficos 3D es muy modesto. Tuve que descubrir la pandereta y buscar una salida.

¡Asigne una tarjeta de video separada al sistema de invitado!


No tardó mucho en encontrar una salida, pero la idea de golpear una pandereta con un reflector era muy extraña. Sobre el tema del reenvío de tarjetas de video a una máquina virtual, Internet está repleto de instrucciones de varios tiempos y para varios hardware. ¿Qué es un gran artículo en el sitio de Arch Linux [0] . Daré una versión resumida de las instrucciones para reenviar una tarjeta de video.

0. Compruebe que el hardware es compatible con IOMMU


Por ejemplo, aquí [1] .

1. Incluimos soporte de IOMMU en un núcleo.


cat / etc / default / grub
GRUB_CMDLINE_LINUX_DEFAULT = "quiet splash amd_iommu = on"
o
GRUB_CMDLINE_LINUX_DEFAULT = "splash silencioso intel_iommu = on"


No olvides sudo update-grub .

2. Seleccionamos la tarjeta de video del controlador


Buscamos los dispositivos necesarios y vemos qué controladores los usan.

lspci -nnk
04: 00.0 Controlador compatible con VGA [0300]: NVIDIA Corporation GT218 [GeForce 210] [ 10de: 0a65 ] (rev a2)
Controlador de kernel en uso: nouveau
Módulos del kernel: nvidiafb, nouveau
04: 00.1 Dispositivo de audio [0403]: Controlador de audio de alta definición NVIDIA Corporation [ 10de: 0be3 ] (rev a1)
Controlador de kernel en uso: snd_hda_intel
Módulos del kernel: snd_hda_intel


Agregue módulos VFIO para que se carguen en el momento del arranque.

cat / etc / modules | grep vfio
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd


Configuramos el módulo VFIO para que intercepte los dispositivos, evitando que se carguen los controladores principales. Si es necesario, agregue a la lista negra el controlador principal.

cat /etc/modprobe.d/vfio.conf
opciones vfio-pci ids = 10de: 0a65,10de: 0be3
lista negra nouveau


3. Reinicie y verifique que todo funcionó


IOMMU encendido.

dmesg | grep -e DMAR -e IOMMU -e AMD-Vi
DMAR: Tecnología de virtualización Intel® para E / S dirigida
o
AMD-Vi: encontrado IOMMU a las 0000: 00: 00.2 cap 0x40
AMD-Vi: Reasignación de interrupción habilitada
AMD-Vi: Lazy IO / TLB flushing habilitado


Los dispositivos compuestos cayeron en un solo grupo.

para un en / sys / kernel / iommu_groups / *; encuentra $ a -type l; hecho | sort --version-sort
/sys/kernel/iommu_groups/15/devices/0000:01:00.0
/sys/kernel/iommu_groups/15/devices/0000:01:00.1
/sys/kernel/iommu_groups/16/devices/0000:02:00.0
/sys/kernel/iommu_groups/17/devices/0000:03:00.0
/sys/kernel/iommu_groups/18/devices/0000:04:00.0
/sys/kernel/iommu_groups/18/devices/0000:04:00.1


Controladores KVM y VFIO cargados.

lsmod | grep -e kvm -e vfio
 kvm_amd 94208 0
 ccp 90112 1 kvm_amd
 kvm 622592 1 kvm_amd
 vfio_pci 45056 0
 vfio_virqfd 16384 1 vfio_pci
 irqbypass 16384 2 vfio_pci, kvm
 vfio_iommu_type1 24576 0
 vfio 28672 2 vfio_iommu_type1, vfio_pci


Tarjeta de video para SO huésped capturada por VFIO.

lspci -nnk
04: 00.0 Controlador compatible con VGA [0300]: NVIDIA Corporation GT218 [GeForce 210] [ 10de: 0a65 ] (rev a2)
Controlador de kernel en uso: vfio-pci
Módulos del kernel: nvidiafb, nouveau
04: 00.1 Dispositivo de audio [0403]: Controlador de audio de alta definición NVIDIA Corporation [ 10de: 0be3 ] (rev a1)
Controlador de kernel en uso: vfio-pci
Módulos del kernel: snd_hda_intel


4. Configure QEMU e inicie el SO invitado


Instalar, si aún no está instalado
sudo apt install qemu-kvm qemu-utils seabios ovmf virt-viewer

Cree un disco donde se instalará el SO huésped
qemu-img create -f raw -o preallocation = full guest.img 50G
o
Falocate -l 50G guest.img

Iniciamos la máquina virtual sin reenviar la tarjeta de video para instalar el SO huésped. Dado que hay una vista en Looking Glass, entonces para el invitado vale la pena elegir Windows 10. También se admite Windows 8 / 8.1 de acuerdo con los últimos datos.

vga_qxl.sh
#! / bin / bash
Especia del visor remoto: //127.0.0.1: 5900 y
sudo qemu-system-x86_64 \
-máquina q35, accel = kvm \
-enable-kvm \
-pu host, kvm = apagado, verifique \
-smp cpus = 2, sockets = 1, núcleos = 2, hilos = 1 \
-m 6G \
-rtc base = localtime, reloj = host \
-dispositivo piix3-usb-uhci \
-dispositivo usb-tablet \
-drive if = pflash, format = raw, readonly, file = / usr / share / OVMF / OVMF_CODE.fd \
-drive file = 'w10.iso', if = ide, format = raw, index = 2, media = cdrom, cache = none \
-drive file = 'virtio-win-0.1.141_st.iso', if = ide, format = raw, index = 3, media = cdrom, cache = none \
-drive file = 'guest.img', if = ide, format = raw, index = 4, media = disk, cache = writeback \
-vga qxl \
-spice port = 5900, addr = 127.0.0.1, disable-ticketing \
-monitor stdio \
-netdev usuario, id = n1, ipv6 = apagado, smb = "/ media / user / data" \
-dispositivo e1000, netdev = n1, mac = 67: 77: 78: 88: 89: 99 \
"$ @"

5. Reenviamos la tarjeta de video al SO huésped


Para comenzar, arranque con dos tarjetas de video. Observamos que la tarjeta reenviada apareció en el sistema, colocamos los controladores y nos aseguramos de que funcionen.

vga_qxl_pass.sh
#! / bin / bash
Especia del visor remoto: //127.0.0.1: 5900 y
sudo qemu-system-x86_64 \
-máquina q35, accel = kvm \
-enable-kvm \
-pu host, kvm = apagado, verifique \
-smp cpus = 2, sockets = 1, núcleos = 2, hilos = 1 \
-m 6G \
-rtc base = localtime, reloj = host \
-dispositivo piix3-usb-uhci \
-dispositivo usb-tablet \
-drive if = pflash, format = raw, readonly, file = / usr / share / OVMF / OVMF_CODE.fd \
-drive file = 'virtio-win-0.1.141_st.iso', if = ide, format = raw, index = 3, media = cdrom, cache = none \
-drive file = 'guest.img', if = ide, format = raw, index = 4, media = disk, cache = writeback \
-vga qxl \
-spice port = 5900, addr = 127.0.0.1, disable-ticketing \
-dispositivo ioh3420, bus = pcie.0, addr = 1c.0, multifunción = encendido, puerto = 1, chasis = 1, id = root \
-dispositivo vfio-pci, host = 04: 00.0, bus = root, addr = 00.0, multifunción = on \
-dispositivo vfio-pci, host = 04: 00.1, bus = root, addr = 00.1 \
-monitor stdio \
-netdev usuario, id = n1, ipv6 = apagado, smb = "/ media / user / data" \
-dispositivo e1000, netdev = n1, mac = 67: 77: 78: 88: 89: 99 \
"$ @"

Después de cómo funcionaba la tarjeta de video reenviada, y en el administrador de dispositivos escribe "El dispositivo funciona bien", iniciamos la máquina virtual solo con la tarjeta de video reenviada.

vga_pass.sh
#! / bin / bash
sudo qemu-system-x86_64 \
-máquina q35, accel = kvm \
-enable-kvm \
-pu host, kvm = apagado, verifique \
-smp cpus = 2, sockets = 1, núcleos = 2, hilos = 1 \
-m 6G \
-rtc base = localtime, reloj = host \
-dispositivo piix3-usb-uhci \
-dispositivo usb-tablet \
-drive if = pflash, format = raw, readonly, file = / usr / share / OVMF / OVMF_CODE.fd \
-drive file = 'virtio-win-0.1.141_st.iso', if = ide, format = raw, index = 3, media = cdrom, cache = none \
-drive file = 'guest.img', if = ide, format = raw, index = 4, media = disk, cache = writeback \
-vga none \
-dispositivo ioh3420, bus = pcie.0, addr = 1c.0, multifunción = encendido, puerto = 1, chasis = 1, id = root \
-dispositivo vfio-pci, host = 04: 00.0, bus = root, addr = 00.0, multifunción = on \
-dispositivo vfio-pci, host = 04: 00.1, bus = root, addr = 00.1 \
-monitor stdio \
-netdev usuario, id = n1, ipv6 = apagado, smb = "/ media / user / data" \
-dispositivo e1000, netdev = n1, mac = 67: 77: 78: 88: 89: 99 \
"$ @"

Conectamos un monitor y admiramos la imagen de escritorio del sistema operativo invitado.

El lugar donde terminan las decisiones simples


Y entonces comienza la diversión. Alguien, todo está bien, la imagen se ha ido y todo es simple. Mi experiencia tropezó dos veces en la etapa de falta de imagen. La primera vez fue el reenvío de la tarjeta gráfica integrada del procesador Intel 6700T HD 530, las salidas de video estaban vacías y la falla se atribuyó al hecho de que los complementos no funcionan bien. La segunda vez se volcó el Nvidia GF210 externo, que ya se había comprado especialmente para experimentos. El resultado fue aún más interesante. En el modo no EFI, la tarjeta de video se reenvió con éxito e incluso mostró una imagen, pero apagó el sistema operativo invitado .

El reenvío posterior podría colgar el host. Un par de horas de búsqueda fácil en Google lleva al hecho de que el problema de congelar una tarjeta de video es bastante común. Esto conduce a un apagado incorrecto de la máquina virtual y, con alguna posibilidad, incluso a un apagado correcto. Como salida, se recomienda reenviar en modo EFI. Pero VBIOS Nvidia GF210 no es compatible con EFI ...

Coser o no coser, esa es la cuestión


No coser QEMU admite la falsificación de VBIOS al reenviar una tarjeta de video. Pero VBIOS todavía tiene que ser enseñado para soportar el modo EFI. Por lo general, se recomienda verificar esto antes de comenzar a reenviar la tarjeta de video, por ejemplo aquí [2] . Pero uno tiene que lidiar con lo que es, y no quería buscar una nueva tarjeta de video con soporte EFI. Entonces necesita parchear VBIOS. Todas las operaciones realizadas con VBIOS se realizan bajo su propio riesgo. Usé un paquete de software e instrucciones para ello desde aquí [3] . Después de leer VBIOS obtenemos el archivo gt210.rom , parche y en la salida tenemos gt210_uefi.rom . Aquí es donde debe deslizar la tarjeta de video al cargar la máquina virtual.

vga_pass_rom.sh
#! / bin / bash
sudo qemu-system-x86_64 \
-máquina q35, accel = kvm \
-enable-kvm \
-pu host, kvm = apagado, verifique \
-smp cpus = 2, sockets = 1, núcleos = 2, hilos = 1 \
-m 6G \
-rtc base = localtime, reloj = host \
-dispositivo piix3-usb-uhci \
-dispositivo usb-tablet \
-drive if = pflash, format = raw, readonly, file = / usr / share / OVMF / OVMF_CODE.fd \
-drive file = 'virtio-win-0.1.141_st.iso', if = ide, format = raw, index = 3, media = cdrom, cache = none \
-drive file = 'guest.img', if = ide, format = raw, index = 4, media = disk, cache = writeback \
-vga none \
-dispositivo ioh3420, bus = pcie.0, addr = 1c.0, multifunción = encendido, puerto = 1, chasis = 1, id = root \
-dispositivo vfio-pci, host = 04: 00.0, bus = root, addr = 00.0, multifunción = on, romfile = gt210_uefi.rom \
-dispositivo vfio-pci, host = 04: 00.1, bus = root, addr = 00.1 \
-monitor stdio \
-netdev usuario, id = n1, ipv6 = apagado, smb = "/ media / user / data" \
-dispositivo e1000, netdev = n1, mac = 67: 77: 78: 88: 89: 99 \
"$ @"

Iniciamos la máquina virtual y miramos.

Oscuridad


Las salidas de la tarjeta de video brillaban en la oscuridad. Una vez más, la moral pasó la prueba del fracaso. Lo primero que viene a la mente es que el sistema operativo invitado se bloquea al inicio. Registros, necesito sus registros. Para hacer esto, ejecute vga_qxl.sh . Nos fijamos en el lanzamiento anterior. Y allí todo está bien, excepto que la comida se tiró bruscamente. Resulta que funciona, aunque no funciona. La primera idea era conectarse a través de RDP y ver qué pasa allí, pero aún así es mejor usar VNC, por ejemplo tightvnc [4] . Instalamos VNC, configuramos el puerto 5600 y reenviamos este puerto para acceder desde el host.

vga_vnc_pass_rom.sh
#! / bin / bash
sudo qemu-system-x86_64 \
-máquina q35, accel = kvm \
-enable-kvm \
-pu host, kvm = apagado, verifique \
-smp cpus = 2, sockets = 1, núcleos = 2, hilos = 1 \
-m 6G \
-rtc base = localtime, reloj = host \
-dispositivo piix3-usb-uhci \
-dispositivo usb-tablet \
-drive if = pflash, format = raw, readonly, file = / usr / share / OVMF / OVMF_CODE.fd \
-drive file = 'virtio-win-0.1.141_st.iso', if = ide, format = raw, index = 3, media = cdrom, cache = none \
-drive file = 'guest.img', if = ide, format = raw, index = 4, media = disk, cache = writeback \
-vga none \
-dispositivo ioh3420, bus = pcie.0, addr = 1c.0, multifunción = encendido, puerto = 1, chasis = 1, id = root \
-dispositivo vfio-pci, host = 04: 00.0, bus = root, addr = 00.0, multifunción = on, romfile = gt210_uefi.rom \
-dispositivo vfio-pci, host = 04: 00.1, bus = root, addr = 00.1 \
-monitor stdio \
-netdev usuario, id = n1, hostfwd = tcp: 127.0.0.1: 5600-: 5600, ipv6 = apagado, smb = "/ media / user / data" \
-dispositivo e1000, netdev = n1, mac = 67: 77: 78: 88: 89: 99 \
"$ @"

Nos conectamos y vemos la máquina en funcionamiento, solo el monitor tiene un extraño monitor genérico no PnP (Universal Monitor no es PnP). Hay una imagen, por lo que puede intentar ejecutar Looking Glass.

Espejo


Aunque esta tecnología utiliza OpenGL, no se necesita espacio después de gl. Pero debe leer las instrucciones [5] en el sitio web del proyecto. Para el sistema operativo invitado, descargue la aplicación de captura de pantalla looking-glass-host.exe [6] , descargue e instale Microsoft Visual C ++ 2015 Redistributable [7] , descargue el controlador para el dispositivo IVSHMEM [8] . Para el host, agregamos dependencias, descargamos y compilamos la aplicación cliente.

build_looking_glass_a12.sh
#! / bin / bash
sudo apt-get install cmake libsdl2-dev libsdl2-ttf-dev nettle-dev libspice-protocol-dev libfontconfig1-dev libx11-dev fonts-freefont-ttf libconfig-dev
wget github.com/gnif/LookingGlass/archive/a12.tar.gz
tar -xf a12.tar.gz
cd LookingGlass-a12
cliente / compilación mkdir
cliente cd / build
cmake ../
hacer

Iniciamos la máquina virtual con el dispositivo IVSHMEM. El tamaño de memoria de 32Mb se selecciona para una resolución de 1920x1080.

vga_vnc_lg_pass_rom.sh
#! / bin / bash
si [! -f / dev / shm / looking-glass]; entonces
toque / dev / shm / espejo
chown `whoami`: kvm / dev / shm / looking-glass
chmod 660 / dev / shm / looking-glass
fi
sudo qemu-system-x86_64 \
-máquina q35, accel = kvm \
-enable-kvm \
-pu host, kvm = apagado, verifique \
-smp cpus = 2, sockets = 1, núcleos = 2, hilos = 1 \
-m 6G \
-rtc base = localtime, reloj = host \
-dispositivo piix3-usb-uhci \
-dispositivo usb-tablet \
-drive if = pflash, format = raw, readonly, file = / usr / share / OVMF / OVMF_CODE.fd \
-drive file = 'virtio-win-0.1.141_st.iso', if = ide, format = raw, index = 3, media = cdrom, cache = none \
-drive file = 'guest.img', if = ide, format = raw, index = 4, media = disk, cache = writeback \
-vga none \
-dispositivo ioh3420, bus = pcie.0, addr = 1c.0, multifunción = encendido, puerto = 1, chasis = 1, id = root \
-dispositivo vfio-pci, host = 04: 00.0, bus = root, addr = 00.0, multifunción = on, romfile = gt210_uefi.rom \
-dispositivo vfio-pci, host = 04: 00.1, bus = root, addr = 00.1 \
-dispositivo ivshmem-plain, memdev = ivshmem, bus = pcie.0 \
-objeto de memoria del objeto, id = ivshmem, share = on, mem-path = / dev / shm / looking-glass, size = 32M \
-monitor stdio \
-netdev usuario, id = n1, hostfwd = tcp: 127.0.0.1: 5600-: 5600, ipv6 = apagado, smb = "/ media / user / data" \
-dispositivo e1000, netdev = n1, mac = 67: 77: 78: 88: 89: 99 \
"$ @"

Nos conectamos a través de VNC, instalamos el controlador en el dispositivo IVSHMEM, tal vez se instalará un controlador estándar, ubicado en los "Dispositivos del sistema". Comenzamos looking-glass-host.exe . En el host, ejecute ./LookingGlass-a12/client/build/looking-glass-client .

En esto, un sistema con NVidia GF210 funcionó para mí, y luego se lanzó Intel HD530 por la misma ruta. Hubo un pequeño problema con la resolución de la pantalla, para cambiar a una resolución rara, por ejemplo 2048x1152, tuve que usar la Utilidad de resolución personalizada [9] .

Otro matiz, al agregar la aplicación looking-glass-host.exe a la carga automática, debe configurar el inicio de sesión automático del usuario, por razones de seguridad, el sistema operativo invitado no permite capturar la pantalla de inicio de sesión.

Epílogo


Si no establece una tarea, obtener una imagen en una salida de video física, entonces este resultado será suficiente para obtener una máquina virtual que funcione con una tarjeta de video física y control sensible. La gestión se lleva a cabo desde el host en una ventana separada o en pantalla completa. Sin embargo, hay matices.

Rendimiento Los recursos generales para la virtualización y no el sistema operativo invitado más eficiente no le permitirán trabajar cómodamente en hardware débil y medio bajo. Se requerirá un potente procesador de al menos 6-8 núcleos, una buena tarjeta gráfica para un sistema operativo invitado, 16 GB + RAM, al menos 8 GB para cada sistema operativo. Y bailando con una pandereta para aprovechar al máximo el hierro.
Paciencia Si no funciona de inmediato, tendrá que pasar tiempo y tiempo decentemente. Busca, lee, prueba. Nuevamente, mira, lee e intenta nuevamente. Dejaré algunos enlaces más que encontré, tal vez habrá más información útil. [10] [11] [12]

Referencias

Precaución, los enlaces se abren en esta ventana.

0. https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF
1. https://en.wikipedia.org/wiki/List_of_IOMMU-supporting_hardware
2. https://www.techpowerup.com/vgabios/
3. https://www.win-raid.com/t892f16-AMD-and-Nvidia-GOP-update-No-requests-DIY.html
4. https://www.tightvnc.com/download.php
5. https://looking-glass.hostfission.com/quickstart
6. https://github.com/gnif/LookingGlass/releases
7. https://www.microsoft.com/en-us/download/details.aspx?id=48145
8. https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/upstream-virtio/
9. https://www.monitortests.com/forum/Thread-Custom-Resolution-Utility-CRU
10. https://heiko-sieger.info/running-windows-10-on-linux-using-kvm-with-vga-passthrough
11. https://ycnrg.org/vga-passthrough-with-ovmf-vfio/
12. https://www.reddit.com/r/VFIO/comments/8h352p/guide_running_windows_via_qemukvm_and_intel_gvtg/

Source: https://habr.com/ru/post/es433878/


All Articles