virtio-nvgpu da acceso casi nativo a la GPU NVIDIA dentro de invitados KVM
El dispositivo virtio reenvía los ioctl del driver de kernel de NVIDIA entre invitado y anfitrión, sin traducir API, y deja el frame del invitado dentro del 2% del metal desnudo.
virtio-nvgpu es un dispositivo virtio que da a un invitado KVM acceso casi nativo a una GPU NVIDIA. No traduce API: reenvía los ioctl del driver de kernel de NVIDIA entre el invitado Linux y el anfitrión al nivel de ABI del propio driver, así que el invitado ejecuta los drivers de usuario sin tocar, las mismas bibliotecas, el mismo Vulkan y NVENC, la misma tarjeta. El objetivo es streaming sin monitor: un compositor dentro de la VM renderiza, compone y codifica en la GPU, y saca vídeo comprimido. La tarjeta se queda en el anfitrión.
Dentro del 2% del metal desnudo
Las cifras están medidas en una RTX 3060 con el driver 595.99.02, invitado contra el mismo equipo en metal desnudo y con carga Vulkan headless idéntica. Con frames de 39 ms el invitado va un 0,4% por debajo, dentro del ruido; a 9,9 ms, un 0,7% por debajo; a 2,0 ms, un 1,7% por encima; a 0,5 ms, un 7,1%; y a 0,05 ms, un 40,8%. Despertar cuesta unos 0,02 ms. Por encima de unos 2 ms por frame, que es cualquier frame de un juego, el invitado está dentro del 2%.
La CPU es la otra mitad. A unos 100 fps sin limitar el ritmo durante 12 segundos, un invitado gasta 0,37 s de CPU frente a los 0,40 s del metal desnudo. En un bucle de render no se gasta nada en reenviar, porque no se reenvía nada: el driver de usuario de NVIDIA envía por memoria que tiene mapeada, y esa memoria es del anfitrión. A lo largo de 813.691 frames el backend sirvió 13.792 mensajes, un cruce cada 59 frames y casi todo montaje del dispositivo.
Cuatro invitados y la letra pequeña
Cuatro invitados sobre la misma RTX 3060 con la misma carga dan 25,84, 26,49, 25,57 y 25,79 fps: 103,7 en conjunto frente a 102,9 de un solo invitado, con percentiles 50 de 39,165, 39,164, 39,168 y 39,165 ms. El total no se mueve al añadir invitados y el reparto es par a cuatro decimales. Los cuatro renderizan y codifican H.264 a la vez, cada uno a 60 Hz, sin tocar el límite de sesiones NVENC. Cuatro es lo que se ejecutó, no un límite encontrado.
En seguridad, el propio repositorio lo dice sin adornos: no hay frontera IOMMU entre el trabajo de GPU del invitado y el anfitrión. La tarjeta pertenece al driver de NVIDIA del anfitrión y vive en su dominio IOMMU; el invitado recibe la interfaz ioctl del driver, no el dispositivo. Lo que separa la memoria del invitado de la del anfitrión es la MMU de la GPU, con tablas de páginas que RM programa en su nombre, así que el driver del anfitrión está en la TCB. Los ioctl que el perfil de ABI no describe se rechazan en vez de reenviarse; las clases RM_ALLOC, los comandos de control de RM y los ioctl de UVM y modeset no se filtran. Es reducción de superficie de ataque, no aislamiento por hardware: VFIO con IOMMU sigue siendo más fuerte, y para inquilinos que no confían entre sí sigue siendo la respuesta.
Se distribuyen perfiles de ABI 535.129.03, 580.178.04 y 595.71.05, casados por rango, y se rechaza cualquier versión anterior al primero. La comparación con metal desnudo es sobre 595.99.02; una A2000 con 615.71.09 presenta, codifica y ha emitido un juego real, pero sin comparación directa contra su anfitrión. El repositorio separa driver/ (GPL-2.0, el módulo de kernel del invitado), device/ (Apache-2.0, el dispositivo virtio como crate de Rust sin ningún VMM entre sus dependencias), isolate/ (Apache-2.0, todavía una nota de diseño: el helper aislado por invitado que debe guardar los descriptores reales está sin construir) y gen/, las tablas de ABI generadas.
Queda bastante por ver. CUDA se reenvía pero solo está probado hasta la enumeración. Nadie ha pasado de cuatro invitados ni ha metido más de un juego real a la vez. En la A2000, uno de dos lanzamientos perdió la captura porque el swapchain rechazó TRANSFER_SRC; un relanzamiento funcionó y no se registró el código de error.

