Implementamos una máquina virtual de Windows con un reenvío de tarjeta de video virtual usando QEMU e Intel GVT-g

Cómo hacer que Intel GVT-g funcione


Hola a todos! Intel ofreció una excelente solución al eterno problema: "Tengo una computadora portátil en Linux y necesito ejecutar Windows con aceleración de hardware, pero no tengo una computadora portátil pesada con dos GPU y refrigeración líquida". Utilizando su arquitectura de GPU u otra cosa, lograron hacerlo para que pueda dividir su GPU Intel integrada en dos o más GPU.


Desafortunadamente, esto no es tan simple ... La documentación está un poco desactualizada, y algunas cosas se rompen de una manera incomprensible sin razón aparente. Por lo tanto, en esta publicación le diré cómo configurar una máquina virtual de Windows acelerada por hardware con virtio y controladores rápidos Intel GVT-g.


Para hacer esto, necesitará una GPU más o menos moderna ( Nota del traductor : según la documentación oficial , GVT-g admite tarjetas de video integradas, comenzando con la quinta generación de Intel Core y la cuarta generación de Xeon ).


Captura de pantalla de Windows


Paso 1: configurar el núcleo


Verifique que tenga una nueva versión del núcleo. Parece que las opciones para GVT-g se incluyeron antes de la versión 4.8, pero definitivamente funcionaron peor, por lo que recomiendo usar el último kernel disponible. Si eres lo suficientemente original como para construir tu núcleo, habilita estas opciones . También deshabilite la eliminación de ksyms no utilizados, ya que esta opción causa un error .


Ahora necesita arreglar los argumentos de la línea de comando del núcleo. Las opciones importantes son:


i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=on i915.enable_guc=0 

Asegúrese de no anular enable_guc=0 con algo que permita la carga de GuC, ya que esto provocará una caída deprimente del controlador i915. Cuando arranque, vaya a su entorno de trabajo y verifique el directorio /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/ . Si no existe, GVT-g no funciona. Revise los registros y / o llore en la almohada.


Como solución al problema, puede agregar estos módulos a initramfs y eliminar el i915 desde allí.


Para un registro más detallado, puede establecer la variable drm.debug en algún valor, por ejemplo, establecerla en 0x02 incluirá mensajes de los controladores.


Paso 2: crea un amigo virtual


Dentro de mdev_supported_types puede encontrar un conjunto completo de directorios. Este conjunto está determinado por la cantidad de memoria gráfica, cada subdirectorio corresponde a algún tipo de GPU virtual. El archivo de description contiene información sobre la memoria y las resoluciones compatibles con esta GPU virtual. Si la creación de una GPU virtual con gran memoria utilizando la salida UUID en el archivo /create le da un error incomprensible, entonces tiene varias opciones. Primero, vaya al BIOS y agregue memoria de video, si es posible. Si esto no funciona, puede detener su DM, cambiar al framebuffer, crear la vGPU deseada desde allí y luego regresar a x11. Desafortunadamente, este método genera muchos errores y no permite alcanzar 60 FPS en mi computadora portátil. Una alternativa es crear una vGPU más pequeña y usar un programa especial para aumentar la resolución (CRU). De esta manera, logré alcanzar 60 FPS, y hubo muchos menos errores y congelaciones.


Puede crear vGPU con este comando:


 $ echo ${vGPU_UUID} | sudo tee /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/${vGPU_TYPE}/create 

Y eliminar: esto:


 $ echo 1 | sudo tee /sys/bus/mdev/devices/${vGPU_UUID}/remove 

Nota del traductor :
Puede generar un UUID para vGPU utilizando el comando uuidgen sin argumentos. La variable $ {vGPU_TYPE} denota uno de los tipos enumerados en el directorio mdev_supported_types . También vale la pena señalar que vGPU debe recrearse en cada reinicio, no se guardan entre los inicios del sistema operativo.


Paso 3: Cortana te grita


El siguiente paso es mucho mejor soportado y mucho más lento y doloroso: instalar Windows 10. No use torrents o descargas no oficiales, o la versión anterior de Windows, el enlace correcto está aquí . También vale la pena descargar la imagen del disco con controladores virtio diseñados específicamente para acelerar los invitados aquí . Instale libvirt y virt-manager y ejecute libvirtd :


 # systemctl start libvirtd 

Ejecute virt-manager y asegúrese de estar conectado a la sesión del sistema libvirt , no al usuario:
Ventana Virt-manager


Nota del traductor :
Para que virt-manager pueda conectarse a la sesión del sistema, puede ejecutarlo como root, pero es mejor configurar la autorización, por ejemplo, como se sugiere en Arch Wiki .


Una vez que haya hecho esto, puede comenzar a crear una máquina virtual. En el cuadro de diálogo de configuración, seleccione la descarga de la imagen iso local y busque la imagen descargada. Si virt-manager no lo reconoce como una imagen de Windows 10, selecciónelo manualmente, ya que esto acelerará Windows, ya que virt-manager en este caso proporciona algunas interfaces de virtualización de Microsoft. Cree una imagen de disco o una partición LVM y configúrela según lo necesite. La interfaz de configuración antes de la instalación es muy limitada, por lo que generalmente comienzo la instalación y la detengo inmediatamente para configurar completamente todo. Aquí hay algunas configuraciones:
Configuración de CPU de máquina virtual
Configuración de red de máquina virtual


Nota del traductor :
A pesar del hecho de que la publicación sobre la configuración de una máquina virtual en una computadora portátil, por alguna razón, se omite la pregunta sobre la distribución de la red mediante un adaptador inalámbrico. El hecho es que la configuración de red predeterminada en virt-manager no es adecuada para una red inalámbrica. En esta situación, la respuesta a esta pregunta y sus comentarios pueden ayudar. El autor también sugiere usar el BIOS en lugar de UEFI, probablemente debido a que UEFI requiere una configuración adicional. Además, parece que tianocore aún no funciona con GVT-g, vea el error 935 . En mi caso, sin embargo, la VM se inició, pero Windows no reconoció el monitor al que estaba conectada la tarjeta de video integrada.


Si necesita acceso rápido al disco o incluso la capacidad de la máquina virtual para comprimir la imagen del disco al eliminar archivos de la máquina virtual (sondeo TRIM, para esto necesita crear la imagen con el comando qemu-img create -f qcow2 -o preallocation=metadata,lazy_refcounts , la instrucción completa está aquí ), configurar la unidad principal para usar SCSI. Necesitará controladores para la máquina virtual para Windows para comprender este formato, así que conecte el disco de controlador virtio descargado previamente para Windows 10. De manera predeterminada, usan un IDE, pero puede acelerar la instalación varias veces y usar menos código heredado si lo usa. para DVD SCSI. Windows admite esto fuera de la caja. También puedes:


  • Forzar USB para usar USB 3.0
  • Agregue canales spice, spice-webdav y qemu-ga para copiar y pegar y compartir archivos entre la VM y el host.
  • Eliminar el hardware virtual no utilizado
  • Cambie la tarjeta de video emulada a QXL y cambie la pantalla a SPICE, NO escuchando la red (incluso loopback) ( Nota del traductor: de lo contrario, la VM simplemente se bloquea ).
  • Cambie el tipo de chip a Q35, configurando junto a la configuración del BIOS.
  • Alimentar al perro

También puedes acostumbrarte a tu nuevo amigo virsh edit . Si lo ejecuta usando sudo -E , sus variables de entorno, en particular EDITOR, se usarán para la edición, y usará la sesión del sistema libvirt, no la del usuario. En este archivo, por ejemplo, puede asignar una correspondencia entre procesadores físicos y virtuales, debido a qué cachés de procesador son más consistentes y el planificador se comporta de manera no tan extraña. Aquí hay un ejemplo de XML que puedes poner allí:


 <vcpu placement='static'>6</vcpu> <cputune> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='2'/> <vcpupin vcpu='2' cpuset='3'/> <vcpupin vcpu='3' cpuset='5'/> <vcpupin vcpu='4' cpuset='6'/> <vcpupin vcpu='5' cpuset='7'/> </cputune> <features> <hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='8191'/> <runtime state='on'/> <synic state='on'/> <stimer state='on'/> </hyperv> </features> <cpu mode='host-passthrough' check='none'> <topology sockets='1' cores='3' threads='2'/> </cpu> 

En este fragmento, configuro la VM para que vea un procesador con tres núcleos físicos, cada uno de los cuales tiene dos hyperthreads. Además, cada procesador / hiperproceso se conecta a su propio hiperproceso y esta correspondencia no cambia. El Programador de Windows conoce hyperthreads y puede usarlos correctamente, sin contarlos como procesadores separados. También habilito algunas interfaces de Hyper-V que están desactivadas de manera predeterminada y pueden no tener efecto. Si usa SPICE, puede agregar las siguientes líneas para deshabilitar la compresión, ya que la red externa todavía no se usa para acceder a la VM.


 <graphics type='spice'> <listen type='none'/> <image compression='off'/> <jpeg compression='never'/> <zlib compression='never'/> <playback compression='off'/> <streaming mode='off'/> <!-- <gl enable='yes' rendernode='/dev/dri/by-path/pci-0000:00:02.0-render'/>     ,     libvirt --> </graphics> 

Ahora puede configurar el orden de arranque e iniciar la instalación de Windows. Si usa una unidad virtio o SCSI, Windows no la encontrará. Deberá instalar el controlador SCSI desde la unidad que conectó, se encuentran en el directorio virtscsi/amd64 . Todo debería funcionar sin problemas, y Windows debería arrancar en un modo lento y miserable no acelerado. Cortana comenzará a gritarte y tu red no funcionará. Romperlo todo en el escritorio. Allí, inicie el administrador de dispositivos, encuentre todos los dispositivos no identificados y actualice los controladores para ellos desde el disco que conectó. Obtendrá un Windows un poco más rápido.


Paso 4: la parte divertida


Hay tres formas de obtener la pantalla virtual de VM acelerada de Windows en la pantalla de su máquina.


  • VNC o algún otro protocolo de acceso remoto (por lo general, esta es una solución muy mala). En esta opción, solo necesita conectar vGPU y desactivar todas las demás pantallas y tarjetas de video. Establezca también la configuración display='off' . No necesita la opción igd-opregion muestra más adelante.
  • SPICE (No pude alcanzar 30 FPS o más, pero el portapapeles general y la transferencia de archivos entre la VM y el host funcionan).
  • Interfaz QEMU incorporada en GTK + (el portapapeles compartido y la transferencia de archivos no funcionan, pero puede lograr 60 FPS con un parche).

Independientemente de lo que pretenda usar, aún debe usar la segunda opción para instalar los controladores para la GPU. Los controladores integrados de Microsoft no funcionan muy bien con GVT-g en el momento de la escritura, y a menudo se rompen. Antes de conectar la vGPU a la VM, es recomendable descargar el controlador más reciente de Intel (Aparentemente, Intel está cambiando su enfoque para distribuir controladores , por lo que en el futuro este paso puede ser diferente o no ser necesario). Ahora asegúrese de haber creado vGPU. Abra virt-manager y reemplace el QXL rápido y bueno con un Cirrus lento para evitar conflictos. Para conectar vGPU a la máquina virtual, debe abrir virsh edit y agregar el siguiente fragmento en alguna parte:


 <domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> <hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='on'> 

 <address uuid='fff6f017-3417-4ad3-b05e-17ae3e1a4615'/> 

  <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> <rom enabled='no'/> </hostdev> <graphics type='spice'> <listen type='none'/> <image compression='off'/> <jpeg compression='never'/> <zlib compression='never'/> <playback compression='off'/> <streaming mode='off'/> <gl enable='yes' rendernode='/dev/dri/by-path/pci-0000:00:02.0-render'/> <!--      , virt-manager     ,        GL. ,      ,   auto. --> </graphics> <qemu:commandline> <qemu:arg value='-set'/> <qemu:arg value='device.hostdev0.x-igd-opregion=on'/> <!-- libvirt     ,      --> </qemu:commandline> </domain> 

Nota: cuando proporcione un fragmento XML como este, debe agregarlo al actual si es posible, sin reemplazar nada.


Verifique que haya creado UUID únicos para todas las vGPU que está utilizando y que los números de ranura no entren en conflicto con ninguno de los otros dispositivos PCI. Si el número de ranura es posterior a la GPU Cirrus, la máquina virtual se bloqueará. Ahora puede iniciar la máquina virtual. ¡Necesita instalar virt-viewer para ver ambas pantallas! Puedes conectarte a una VM usando el comando


 $ sudo -E virt-viewer --attach 

Una de las pantallas estará en blanco o sin inicializar, la segunda es una pantalla familiar, pequeña y no acelerada. Expanda y, una vez ingresado, instale el controlador para la GPU. Si tienes suerte, todo funcionará de inmediato. De lo contrario, debe apagar y reiniciar la VM (no reiniciar) utilizando la pantalla de trabajo. Ahora es el momento de abrir una terminal y ejecutar dmesg -w adentro. Este comando le dará información útil sobre problemas y progreso general usando vGPU. Por ejemplo, en el momento del arranque, KVM se quejará de MSR bloqueados, entonces debería recibir algunos mensajes de acceso incorrectos cuando se inicializa vGPU. Si hay demasiados, algo está mal.


Si el sistema se inicia, puede abrir la configuración de pantalla y apagar la pantalla no acelerada. Se puede ocultar una pantalla en blanco a través del menú Ver en virt-viewer . En principio, las máquinas virtuales ya se pueden usar, pero hay algunas cosas que se pueden hacer para lograr una mayor resolución y mayor velocidad.


La utilidad CRU es muy útil. Puede jugar con él, e incluso si se topa con algunos artefactos gráficos o incluso una pantalla casi completamente negra, como resultó para mí, puede ejecutar el archivo Restart64.exe que viene con el programa para reiniciar el subsistema de gráficos de Windows. Personalmente, uso esta utilidad para usar una resolución más alta en una vGPU más modesta.


Para lograr un excelente 60 FPS, debe cambiar al monitor QEMU incorporado en GTK + sin admitir un portapapeles compartido con el host y bollos similares, así como cambiar una línea y reconstruir QEMU. También necesitará agregar un montón de argumentos desagradables de línea de comando a su XML. Retire la pantalla SPICE y la tarjeta gráfica Cirrus y off el atributo de display de su vGPU (libvirt no admite la pantalla en GTK + y no permitirá el arranque desde display='on' sin una pantalla).


  <qemu:commandline> <qemu:arg value='-set'/> <qemu:arg value='device.hostdev0.x-igd-opregion=on'/> <qemu:arg value='-set'/> <qemu:arg value='device.hostdev0.display=on'/> <qemu:arg value='-display'/> <qemu:arg value='gtk,gl=on'/> <qemu:env name='DISPLAY' value=':1'/> <qemu:env name='GDK_SCALE' value='1.0'/> </qemu:commandline> 

El escalado de HiDPI en el monitor QEMU funciona muy mal, por lo que lo desactivaremos. Además, deberá establecer la variable DISPLAY en el número de pantalla que está utilizando. Para dar al usuario que ejecuta qemu acceso al servidor X, use el comando:


 # xhost si:localuser:nobody 

Si esto no funciona, intente xhost + , pero asegúrese de estar usando un firewall. De lo contrario, intente un método más seguro.


Con tales trucos, aún no obtendrá más de 30 FPS debido a este estúpido error en QEMU, si no lo repara cambiando la línea, como se indica en el enlace del comentario. Asegúrese de construir solo QEMU para x86-64, a menos que tenga la intención de usarlo en otra plataforma. Adjunté mi PKGBUILD, que no cambia la línea, sino que solo recopila QEMU para x86_64 sin soporte de almacenamiento de red aquí .


Si te pierdes en algún lugar del camino, puedes ver mi XML actual para libvirt .


Enlaces utiles


Guía oficial de ajuste de GVT-g
Guía del usuario de Dma-buf
Artículo de configuración de Intel GVT-g en el Wiki de NixOS
Artículo de Arch Wiki sobre libvirt
Configuración de red en KVM en la interfaz inalámbrica
Sitio web de Intel GVT-g


PD: Gracias aNNiMON por ayudarme a corregir el texto de traducción y corregir errores.

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


All Articles