Las fallas en el passthrough PCI rara vez se anuncian con dignidad. Aparecen como una VM que arranca y muestra una pantalla negra, una NIC que desaparece bajo carga, o un host que se congela justo cuando lo estás demostrando. Entonces todos señalan a VFIO como si fuera el villano de un dibujo animado de sábado por la mañana.
La mayoría de las veces, VFIO está haciendo su trabajo: negarse a hacer algo inseguro o imposible. Tu verdadero enemigo suele ser uno de doce requisitos previos aburridos: conmutadores del firmware, agrupación IOMMU, comportamiento de reinicio, enrutamiento de interrupciones, o ese parámetro de kernel “temporal” que olvidaste que añadiste hace tres meses.
Playbook de diagnóstico rápido
Si estás de guardia, no empiezas con filosofía. Empiezas con un bucle de triaje que responde tres preguntas: (1) ¿se activó realmente IOMMU?, (2) ¿está el dispositivo aislado?, y (3) ¿puede reiniciarse limpiamente entre arranques de VM?
Primero: confirma que la plataforma es capaz y que IOMMU está habilitado
- Conmutadores BIOS/UEFI: Intel VT-d o AMD-Vi, y idealmente “Above 4G decoding” para GPUs modernas y HBAs.
- El kernel detecta IOMMU: revisa dmesg en busca de líneas DMAR/AMD-Vi.
Segundo: confirma que el aislamiento de grupos IOMMU es razonable
- Lista los grupos IOMMU y asegúrate de que el dispositivo no esté pegado a tu controlador SATA, controlador USB o puerto raíz del chipset que no puedes sacrificar.
- Si dependes de ACS override, trátalo como último recurso y como un compromiso de seguridad, no como una “solución”.
Tercero: confirma el binding a VFIO y el comportamiento de reinicio
- Asegúrate de que el dispositivo se vincule a
vfio-pcien el host y no a un controlador del proveedor. - Revisa el soporte FLR y las peculiaridades de reinicio (especialmente en GPUs).
Luego: verifica el lado de la VM (tipo de máquina, UEFI/OVMF, peculiaridades de ROM)
- Elige un tipo de máquina QEMU estable, y no mezcles hábitos de la era SeaBIOS con dispositivos de la era OVMF.
- Si es una GPU, decide pronto si necesitas un VBIOS volcado y si necesitas pasar también la función de audio.
Ese orden suena obvio hasta que ves a alguien pasar dos horas ajustando argumentos de QEMU cuando el BIOS tenía VT-d desactivado. Lo que me lleva a la única ley del passthrough: castiga la asunción con intereses.
Hechos rápidos y contexto (para que dejes de adivinar)
- Hecho 1: El nombre de marketing de Intel para IOMMU es VT-d; el de AMD es AMD-Vi. Resuelven la misma clase de problemas: aislamiento y remapeo de DMA.
- Hecho 2: VFIO no siempre fue el enfoque por defecto. El método más antiguo pci-stub existía, pero VFIO trajo un marco más limpio y seguro para la asignación de dispositivos en Linux.
- Hecho 3: Los grupos IOMMU no son “algo de Linux”. Son una realidad de hardware/topología mostrada por ACPI y las capacidades PCIe. Linux solo es el mensajero.
- Hecho 4: ACS (Access Control Services) es una característica de PCIe que puede mejorar el aislamiento. Muchas placas de consumo la implementan parcial o creativamente—a menudo del tipo de “creativo” que no quieres en producción.
- Hecho 5: “Above 4G decoding” importa porque las BAR grandes (Base Address Registers) en GPUs y dispositivos modernos no caben bien en el espacio de direcciones de 32 bits legado.
- Hecho 6: Los problemas de reinicio de GPU no son folklore. Algunas GPUs no se reinician completamente sin un Function Level Reset (FLR) o sin un comportamiento específico del proveedor, y el host puede no ser capaz de re-inicializarlas tras apagar una VM.
- Hecho 7: SR-IOV no apareció para facilitarte la vida. Existe para dividir una función PCIe física en funciones virtuales, pero multiplica las formas en que puedes malconfigurar firmware, controladores y aislamiento.
- Hecho 8: MSI/MSI-X fueron una gran mejora en rendimiento y estabilidad respecto a las interrupciones antiguas basadas en líneas—y fuente de dolor cuando el remapeo de interrupciones no está habilitado correctamente.
- Hecho 9: Proxmox es “simplemente Debian con opiniones”, lo cual es buena noticia: la mayoría de la depuración es depuración estándar de Linux una vez que dejas de tratar la interfaz como magia.
Una cita que tengo pegada en mi tablero mental: idea parafraseada
— W. Edwards Deming, sobre mejorar sistemas mejorando el proceso, no gritando a los resultados. En el mundo del passthrough, tu “proceso” es el bucle de verificación a continuación.
Lista de verificación / plan paso a paso (12+ verificaciones con comandos)
Esta es la parte donde dejas de “probar cosas” y empiezas a recopilar evidencia. Cada tarea incluye: un comando, qué significa la salida y la decisión que tomas.
1) Identifica los dispositivos y funciones PCI exactos que quieres pasar
cr0x@server:~$ lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation Device [8086:3e0f]
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104 [GeForce RTX 2080] [10de:1e87]
01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
03:00.0 Ethernet controller [0200]: Intel Corporation I350 Gigabit Network Connection [8086:1521]
Qué significa: Necesitas el BDF (bus:device.function) y los IDs vendor:device. Las GPUs suelen tener múltiples funciones (VGA + audio). Las NICs pueden tener varios puertos/funciones también.
Decisión: Anota el conjunto completo de funciones que debes pasar juntas. Si pasas 01:00.0 pero olvidas 01:00.1, tendrás rarezas después y culparás a QEMU por tu contabilidad.
2) Verifica las banderas de virtualización de la CPU (no lo saltes porque “es un servidor”)
cr0x@server:~$ lscpu | egrep -i 'Virtualization|Flags'
Virtualization: VT-x
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid
Qué significa: VT-x/AMD-V es para ejecutar VMs; no es VT-d/AMD-Vi. Aun así, si esto falta, estás depurando el conjunto de características equivocado.
Decisión: Si falta virtualización, detente. Arregla BIOS/UEFI primero. Si esto es una máquina alquilada, confirma que no estás en una SKU hostil a la virtualización.
3) Confirma que IOMMU está habilitado en el firmware y activo en Linux
cr0x@server:~$ dmesg | egrep -i 'DMAR|IOMMU|AMD-Vi' | head -n 30
[ 0.000000] DMAR: IOMMU enabled
[ 0.000000] DMAR: Host address width 39
[ 0.084123] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[ 0.084129] DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap c90780106f0462 ecap f020de
[ 0.251990] DMAR: Intel(R) Virtualization Technology for Directed I/O
Qué significa: Quieres “IOMMU enabled” y que aparezca temprano en el arranque. Si ves errores sobre remapeo de interrupciones o “no IOMMU found”, hoy no harás passthrough.
Decisión: Si IOMMU no está habilitado, verifica los conmutadores del BIOS (VT-d/AMD-Vi) y revisa los parámetros de la línea de comandos del kernel.
4) Verifica que los parámetros del cmdline del kernel sean correctos (y no se saboteen)
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-5-pve root=ZFS=rpool/ROOT/pve-1 ro quiet intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction
Qué significa: intel_iommu=on (o amd_iommu=on) habilita IOMMU. iommu=pt usa el modo passthrough para dispositivos del host por rendimiento; es común y suele estar bien.
Decisión: Si ves intel_iommu=off o no hay parámetros IOMMU y dmesg está silencioso, arregla la configuración de GRUB/systemd-boot y reinicia. Si ves pcie_acs_override, trátalo como “estamos doblando las reglas”.
5) Confirma que el remapeo de interrupciones está habilitado (la estabilidad bajo carga vive aquí)
cr0x@server:~$ dmesg | egrep -i 'remapping|x2apic|irq' | head -n 50
[ 0.000000] DMAR-IR: Enabled IRQ remapping in x2apic mode
[ 0.000000] x2apic enabled
Qué significa: El remapeo de IRQ es una característica de seguridad y corrección. Sin él, algunos dispositivos e interrupciones MSI pueden comportarse como una casa encantada bajo carga.
Decisión: Si el remapeo de IRQ no está habilitado, revisa el BIOS por “Interrupt Remapping” u opciones de virtualización relacionadas. En algunas plataformas, un BIOS desactualizado es la causa.
6) Inspecciona los grupos IOMMU (esto decide lo que puedes pasar con seguridad)
cr0x@server:~$ for d in /sys/kernel/iommu_groups/*/devices/*; do echo "IOMMU Group ${d#*/iommu_groups/*}: $(lspci -nns ${d##*/})"; done | sort -V | sed -n '1,30p'
IOMMU Group 0: 00:00.0 Host bridge [0600]: Intel Corporation Device [8086:3e0f]
IOMMU Group 1: 00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:1901]
IOMMU Group 12: 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104 [GeForce RTX 2080] [10de:1e87]
IOMMU Group 12: 01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
IOMMU Group 13: 03:00.0 Ethernet controller [0200]: Intel Corporation I350 Gigabit Network Connection [8086:1521]
Qué significa: Los dispositivos en el mismo grupo pueden hacer DMA entre sí a menos que la plataforma proporcione aislamiento adecuado. Si tu GPU comparte grupo con un controlador USB que necesitas en el host, estás atascado o a punto de hacer algo arriesgado.
Decisión: Si el agrupamiento es limpio, continúa. Si el agrupamiento es caótico, considera mover el dispositivo a otro slot, cambiar configuraciones de bifurcación, actualizar el BIOS, o—solo si aceptas la compensación—usar ACS override.
7) Verifica que el dispositivo soporte reinicio (FLR) o nota que no lo hace
cr0x@server:~$ lspci -s 01:00.0 -vv | egrep -i 'Capabilities:.*Express|FLR|Reset' -n
12:Capabilities: [60] Express (v2) Endpoint, MSI 00
55: DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis- FLR+
Qué significa: FLR+ sugiere soporte de Function Level Reset. No es garantía de felicidad, pero es una buena señal. Algunos dispositivos (especialmente GPUs antiguas) pasarán una vez y luego quedarán atascados hasta un reinicio del host.
Decisión: Si no hay FLR y ves problemas recurrentes de “device is in use” o “failed to reset”, planifica operativamente: reinicio del host entre asignaciones, o elige hardware distinto.
Chiste #1: El passthrough PCI es como salir con una impresora: todo parece bien hasta que realmente necesitas que funcione.
8) Asegúrate de que el host vincule el dispositivo a vfio-pci (y no a nouveau/nvidia/amdgpu)
cr0x@server:~$ lspci -k -s 01:00.0
01:00.0 VGA compatible controller: NVIDIA Corporation TU104 [GeForce RTX 2080]
Subsystem: Micro-Star International Co., Ltd. [MSI] TU104 [GeForce RTX 2080]
Kernel driver in use: vfio-pci
Kernel modules: nvidiafb, nouveau
Qué significa: “Kernel driver in use” debe ser vfio-pci. “Kernel modules” puede listar módulos posibles; eso está bien.
Decisión: Si un controlador del proveedor está en uso, corrige el binding: añade los IDs del dispositivo a vfio-pci, lista en blacklist a controladores en conflicto, rebuild initramfs, reinicia y vuelve a comprobar.
9) Confirma que los módulos vfio se cargan y están presentes en initramfs
cr0x@server:~$ lsmod | egrep 'vfio|kvm'
vfio_pci 16384 0
vfio_pci_core 73728 1 vfio_pci
vfio_iommu_type1 45056 0
vfio 45056 2 vfio_pci_core,vfio_iommu_type1
kvm_intel 401408 0
kvm 1343488 1 kvm_intel
Qué significa: Si los módulos núcleo de VFIO no están cargados, no estás listo. Si solo se cargan después de que el controlador del host agarró el dispositivo, aún puedes perder la carrera.
Decisión: Si el orden de carga de módulos es incorrecto, añade los módulos a /etc/modules, asegura los IDs correctos en vfio-pci, y regenera initramfs para que vfio se vincule temprano.
10) Verifica que Proxmox/QEMU realmente use IOMMU en la configuración de la VM
cr0x@server:~$ qm config 101 | egrep -i 'hostpci|machine|bios|efidisk|args'
bios: ovmf
machine: q35
hostpci0: 01:00,pcie=1,x-vga=1
hostpci1: 01:00.1,pcie=1
efidisk0: local-lvm:vm-101-disk-0,efitype=4m,pre-enrolled-keys=1
args: -cpu host
Qué significa: Para GPUs y muchos dispositivos PCIe, q35 + pcie=1 es el valor por defecto sensato. Pasar tanto la GPU como su función de audio evita dispositivos medio-adjuntos. OVMF es típico para Windows moderno y Linux invitado UEFI.
Decisión: Si ves tipos de máquina legados y flags extraños copiados de un post viejo, simplifica. Pasa a q35 + OVMF a menos que tengas una razón específica para no hacerlo.
11) Revisa la contención de recursos del host: latencia I/O y steal CPU pueden parecer “inestabilidad de passthrough”
cr0x@server:~$ pveperf
CPU BOGOMIPS: 71999.84
REGEX/SECOND: 6068330
HD SIZE: 76.80 GB (rpool/ROOT/pve-1)
FSYNCS/SECOND: 1098.55
DNS EXT: 55.76 ms
Qué significa: FSYNCS/SECOND es una prueba cruda pero útil para la latencia del almacenamiento. Si está terrible, tu “stutter de GPU en passthrough” podría ser el invitado bloqueado en disco.
Decisión: Si el almacenamiento es lento, deja de ajustar VFIO y empieza a optimizar almacenamiento: revisa ajustes ZFS sync, salud del SLOG, firmware del controlador y profundidad de cola. O mueve los discos de la VM fuera del pool con problemas.
12) Verifica hugepages/presión de mapeo IOMMU y disponibilidad de memoria
cr0x@server:~$ grep -E 'HugePages|AnonHugePages|MemAvailable' /proc/meminfo | head
MemAvailable: 58723452 kB
AnonHugePages: 10240000 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Qué significa: Si has fijado hugepages o has dejado al host sin recursos, la asignación de dispositivos puede fallar de maneras que parecen no relacionadas. Algunos entornos usan hugepages deliberadamente; eso está bien. Pero debes saber que lo hiciste.
Decisión: Si la memoria está justa, reduce la memoria de la VM, deja de sobreaprovisionar o añade RAM. Si necesitas hugepages, configúralas intencionalmente y documenta como un adulto.
13) Revisa si se usa ACS override y comprende el radio de impacto
cr0x@server:~$ grep -R "pcie_acs_override" -n /etc/default/grub /etc/kernel/cmdline 2>/dev/null
/etc/default/grub:6:GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction"
Qué significa: ACS override puede dividir grupos artificialmente. Puede hacer posible el passthrough en plataformas de consumo que de otro modo no aislarían dispositivos correctamente.
Decisión: Si esto es un homelab, podrías aceptarlo. Si es producción con multi-tenancy hostil o cumplimiento estricto, evítalo. Mejor hardware es más barato que explicar un incidente de aislamiento DMA.
14) Valida la necesidad de VBIOS de la GPU (especialmente cuando la GPU es primaria)
cr0x@server:~$ dmesg | egrep -i 'vfio|rom|bar|vga' | tail -n 30
[ 12.912345] vfio-pci 0000:01:00.0: enabling device (0000 -> 0003)
[ 12.934567] vfio-pci 0000:01:00.0: BAR 0: assigned [mem 0xf6000000-0xf6ffffff 64bit]
[ 12.945678] vfio-pci 0000:01:00.0: BAR 2: assigned [mem 0xd0000000-0xdfffffff 64bit pref]
[ 13.012345] vfio-pci 0000:01:00.0: vfio_ecap_init: hiding ecap 0x19@0x900
Qué significa: La asignación de BAR es normal. Si falta salida en el invitado, la GPU puede necesitar un archivo ROM, especialmente si fue usada como pantalla de arranque del host (el firmware puede no exponer una option ROM limpia).
Decisión: Si el invitado nunca inicializa la GPU y has confirmado todo lo demás, prueba proporcionando un ROM VBIOS limpio y asegúrate de que no estás peleando con un controlador de consola del host.
15) Revisa patrones de rechazo de controlador / Código 43 de NVIDIA (invitados Windows)
cr0x@server:~$ qm showcmd 101 --pretty | egrep -i 'kvm=|hidden|vendor|cpu host' | head -n 50
-cpu host,hv_time,hv_relaxed,hv_vapic,hv_spinlocks=0x1fff
-machine type=q35,accel=kvm
-smbios type=1,uuid=2b4b9a2a-4a1a-4c3c-9f28-8ed0f843b2c1
Qué significa: Los controladores modernos de NVIDIA para consumo solían detectar virtualización y negarse a funcionar bien en algunos casos. El panorama ha cambiado con el tiempo, pero “el controlador se niega en la VM” todavía ocurre dependiendo de la GPU, la rama del controlador y la configuración del invitado.
Decisión: Si te topas con síntomas tipo Code 43, confirma que usas aceleración KVM, passthrough de CPU host y las enlightenments razonables de Hyper-V. No empieces con hacks aleatorios de “ocultar KVM” a menos que estés reproduciendo una regresión específica.
16) Verifica que el dispositivo no esté siendo usado por el host (handles abiertos, servicios o bridges)
cr0x@server:~$ lsof /dev/vfio/* 2>/dev/null | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
qemu-sys 4212 root 25u CHR 246,0 0t0 123 /dev/vfio/12
Qué significa: Si un proceso QEMU previo aún mantiene el grupo VFIO, tu siguiente inicio fallará. Esto también detecta momentos de “la VM sigue ejecutándose en alguna parte”.
Decisión: Si ves un proceso huérfano, complétalo limpiamente. Si no muere, recolecta logs primero y luego termínalo. Los reinicios a veces son la opción menos mala cuando se trata de dispositivos PCIe bloqueados.
17) Confirma el estado SR-IOV (si pasas VFs)
cr0x@server:~$ lspci -s 03:00.0 -vv | egrep -i 'SR-IOV|Virtual Function' -n
210:Capabilities: [160] Single Root I/O Virtualization (SR-IOV)
220: Total VFs: 8, Initial VFs: 0, Number of VFs: 4, Function Dependency Link: 00
Qué significa: SR-IOV está presente y configurado para 4 VFs. Si las VFs esperadas no aparecen, falta firmware, controlador o configuración en sysfs.
Decisión: Si no se crean VFs, habilita SR-IOV en el BIOS (si aplica), asegura que el controlador del host lo soporte y configura la creación de VFs explícitamente. Si mezclas VFs y PF en passthrough, asegúrate de entender las restricciones del dispositivo.
Tres micro-historias corporativas desde el terreno
Micro-historia 1: el incidente causado por una suposición equivocada
El equipo heredó un clúster Proxmox que “ya hacía passthrough de GPU”. El anterior dueño dejó una nota: “funciona, no tocar.” Esa nota se enmoheció.
Se aplicó una actualización menor: nuevo kernel, nuevo firmware, mismo hardware. Lunes por la mañana: las VMs de render arrancaban pero las GPUs no se adjuntaban. El panel parecía normal. Los usuarios vieron pantallas negras y dieron opiniones ruidosas.
El primer ingeniero persiguió argumentos de QEMU. Después alguien persiguió controladores de Windows. La tercera persona hizo lo único útil: comprobó los grupos IOMMU y notó que habían cambiado. La GPU ahora estaba agrupada con un puente PCIe que también incluía un controlador USB que el host necesitaba. “Funcionaba” antes porque el BIOS antiguo tenía una enumeración y comportamiento de agrupación PCIe diferente.
La suposición equivocada fue sutil: “los grupos IOMMU son estables tras actualizaciones.” No lo son. Las actualizaciones de firmware, cambios de kernel e incluso la población de slots pueden reordenar la topología. Eso no es Linux caprichoso; es la plataforma exponiendo nueva información o enrutamiento.
La solución fue aburrida: mover la GPU a otro slot, desactivar un controlador onboard no usado para simplificar el árbol, y actualizar el runbook para revalidar grupos tras cambios de firmware. El incidente no acabó con heroísmos. Acabó con una lista de verificación.
Micro-historia 2: la optimización que salió mal
Otra organización quería “máximo rendimiento” para una VM sensible a latencia que usaba NICs en passthrough. Alguien activó todos los ajustes de rendimiento que había oído: hugepages, fijación de CPU, isolcpus, tweaks de irqbalance, ajustes agresivos de energía. Lucía impresionante. También volvió el sistema frágil.
Funcionó de maravilla durante una semana. Luego un reinicio del host durante mantenimiento y la VM empezó a perder paquetes. El passthrough de la NIC aún se adjuntaba, pero el tráfico tenía jitter y taponamientos ocasionales. En el host, la distribución de interrupciones se veía desigual; un núcleo se ahogaba.
El culpable no era VFIO. El aislamiento de CPU “optimizador” fijó demasiado, y las interrupciones quedaron atascadas en un conjunto de CPU no óptimo tras el arranque. El host hacía trabajo extra moviendo interrupciones y manejando ruido de timers en un rincón raro del scheduler.
Deshicieron la mitad del “tuning”, mantuvieron solo lo que podían medir, y reintrodujeron irqbalance con reglas de afinidad explícitas. El rendimiento bajó ligeramente en el benchmark sintético. La latencia real mejoró y el sistema dejó de ser una escultura de cristal.
Chiste #2: Cada vez que “optimizas” un sistema sin mediciones, una interrupción aterriza en el peor núcleo posible por despecho.
Micro-historia 3: la práctica aburrida pero correcta que salvó el día
Un equipo gestionaba una pequeña flota de nodos Proxmox para cargas mixtas: VMs intensivas en almacenamiento y un par de escritorios con passthrough de GPU. Nada sofisticado. Lo que sí tenían era disciplina.
Mantenían un artefacto simple por host: un archivo de texto con versiones de firmware, cmdline del kernel, listado de grupos IOMMU y los dispositivos previstos para passthrough. Tras cualquier actualización de BIOS o cambio de hardware, re-ejecutaban la colección de artefactos. Tomaba diez minutos. La gente se quejaba. Lo hacían igual.
Una tarde un nodo reinició inesperadamente tras un evento de energía. Al volver, una VM GPU falló al iniciar con un error de grupo VFIO. El ingeniero de guardia comparó los grupos IOMMU de hoy con el artefacto conocido bueno. La GPU ahora compartía grupo con un controlador SATA porque una configuración de firmware se había revertido.
La solución fue inmediata: restaurar la configuración del BIOS, validar grupos IOMMU y reiniciar la VM. Sin adivinanzas, sin conocimiento tribal, sin “probar un kernel distinto.” La práctica aburrida no hizo famoso a nadie, que es el punto.
Errores comunes: síntoma → causa raíz → solución
Esta sección existe porque todos repetimos los mismos fallos, solo con distintos hostnames.
1) La VM no arranca: “failed to set iommu for container” / “no IOMMU detected”
Síntoma: QEMU se niega a arrancar con un error de IOMMU/VFIO.
Causa raíz: VT-d/AMD-Vi deshabilitado en BIOS, cmdline del kernel incorrecto, o arrancado en un kernel sin IOMMU habilitado.
Solución: Habilita VT-d/AMD-Vi en firmware, añade intel_iommu=on o amd_iommu=on, reinicia y confirma via dmesg.
2) La VM arranca pero el dispositivo no aparece dentro del invitado
Síntoma: El OS invitado arranca, pero la GPU/NIC no aparece, o aparece con errores.
Causa raíz: BDF incorrecto, dispositivo multifunción faltante (audio de GPU), dispositivo no ligado a vfio-pci, u error del controlador invitado.
Solución: Vuelve a comprobar lspci -nn, pasa todas las funciones necesarias, confirma Kernel driver in use: vfio-pci y valida los controladores del invitado.
3) Funciona una vez tras el boot, luego falla hasta reiniciar el host
Síntoma: El primer arranque de VM tras arrancar el host funciona; arranques posteriores fallan o la GPU queda negra.
Causa raíz: El dispositivo carece de reinicio fiable (sin FLR), o peculiaridad de reinicio del proveedor (común en algunas GPUs).
Solución: Elige hardware con soporte FLR, prueba módulos de reinicio específicos del kernel/proveedor cuando proceda, o acepta reinicios de host como solución operacional temporal.
4) Congelaciones aleatorias del host bajo carga
Síntoma: El host se bloquea durante I/O intenso de VMs o carga de GPU, a veces requiriendo corte de energía.
Causa raíz: Remapeo de interrupciones roto, BIOS con bugs, overclocks inestables, o suministro de energía/entrega PCIe marginal (sí, incluso en builds “server”).
Solución: Confirma DMAR-IR: Enabled IRQ remapping, actualiza BIOS, desactiva overclocks, revisa alimentación. Si la plataforma es de consumo, trátala como tal.
5) El rendimiento es terrible aunque el passthrough “funcione”
Síntoma: FPS bajos, stutter, picos de latencia, pérdida de paquetes o paradas intermitentes.
Causa raíz: Latencia de almacenamiento, contención CPU, modelo de CPU incorrecto, o interrupciones mal enrutadas. El passthrough no te inmuniza del resto del host.
Solución: Mide: pveperf, iostat, top, distribución de interrupciones. Arregla los cuellos de botella antes de tocar flags de VFIO.
6) El dispositivo está atascado en un grupo IOMMU con “todo”
Síntoma: La GPU comparte grupo con USB/SATA/dispositivos del chipset.
Causa raíz: La topología de la placa no tiene aislamiento ACS; dispositivo detrás del mismo root complex; cableado del slot.
Solución: Mueve slots, cambia configuraciones PCIe en BIOS, actualiza firmware, o acepta el riesgo de ACS override. Si es para aislamiento en producción, elige una placa que se comporte como si lo fuera.
Checklists / plan paso a paso
Si quieres algo que puedas pegar en un ticket, usa esta secuencia. Es intencionalmente repetitiva; la repetición es lo que acorta los incidentes.
Verificación base del host (haz esto una vez por nodo, luego tras cualquier actualización de BIOS)
- Confirma banderas de virtualización:
lscpuy guarda la salida. - Confirma IOMMU activo:
dmesg | egrep -i 'DMAR|AMD-Vi|IOMMU'. - Confirma remapeo de IRQ:
dmesg | egrep -i 'DMAR-IR|remapping'. - Captura cmdline del kernel:
cat /proc/cmdliney guárdalo. - Vuelca grupos IOMMU y guárdalos como artefacto.
Verificación por dispositivo (cada vez que añades un dispositivo en passthrough)
- Registra IDs y funciones del dispositivo:
lspci -nn. - Revisa la pertenencia a grupos: volcado de grupos y confirma aislamiento.
- Verifica capacidad de reinicio:
lspci -vvy anota FLR. - Vincula a vfio-pci y confirma con
lspci -k.
Verificación por VM (cada vez que cambia la configuración de la VM)
- Confirma tipo de máquina y BIOS:
qm config VMID. - Confirma que las entradas hostpci incluyan todas las funciones requeridas.
- Confirma modo CPU: prefiere
-cpu hostsalvo razón de compatibilidad. - En fallo, comprueba quién mantiene el grupo VFIO:
lsof /dev/vfio/*.
Dos reglas de “deja de cavar”
- Si IOMMU no está habilitado en dmesg, deja de ajustar args de QEMU. Arregla firmware/cmdline primero.
- Si tu grupo IOMMU está sucio y estás considerando ACS override, detente y decide si aceptas el riesgo. No lo hagas a ciegas.
Preguntas frecuentes
1) ¿Necesito tanto VT-x como VT-d (o AMD-V y AMD-Vi)?
VT-x/AMD-V es para virtualización de CPU. VT-d/AMD-Vi es para IOMMU (remapeo DMA) y es de lo que depende el passthrough PCI. Normalmente quieres ambos.
2) ¿Es iommu=pt seguro?
Común y generalmente seguro para rendimiento en hosts donde no quieres forzar la sobrecarga de traducción en dispositivos no passthrough. No sustituye un aislamiento correcto; solo cambia cómo el host usa el IOMMU.
3) ¿Debo usar ACS override?
Sólo si entiendes las implicaciones de seguridad y corrección. Puede hacer que hardware de consumo sea usable para homelabs. También puede crear un aislamiento que parece real pero no es tan fuerte como el comportamiento ACS nativo del hardware.
4) ¿Por qué mi GPU necesita que se pase su función de audio?
Muchas GPUs exponen un controlador de audio HDMI/DP como una función PCI separada. Los invitados pueden comportarse mejor cuando ambas funciones se asignan, y evita que el host se vincule a la función remanente.
5) ¿SeaBIOS u OVMF?
OVMF (UEFI) es la opción moderna por defecto, especialmente para Windows 11 y GPUs más nuevas. SeaBIOS puede funcionar para invitados más antiguos, pero mezclar supuestos antiguos con GPUs nuevas es como acabar en territorio de “pantalla negra”.
6) Mi dispositivo está en el mismo grupo IOMMU que un puente PCI. ¿Siempre es malo?
No automáticamente. Los puentes pueden ser parte de la topología. Lo que importa es si el grupo incluye dispositivos que no puedes o no deberías pasar juntos. Si el grupo incluye un controlador USB chipset que necesitas en el host, tienes un problema práctico.
7) ¿Por qué se rompe el passthrough tras una actualización de kernel?
Las actualizaciones de kernel pueden cambiar el comportamiento de controladores, el orden de inicialización e incluso cómo se aplican quirks. Las actualizaciones de firmware también pueden cambiar la enumeración PCIe. Por eso guardas artefactos (cmdline, grupos, binding) y revalídas después de las actualizaciones.
8) ¿Pueden los problemas de rendimiento de ZFS parecer problemas de VFIO?
Sí. Si el almacenamiento del invitado se corta, verás saltos, lag de entrada y timeouts “aleatorios” que la gente atribuye erróneamente a GPUs o NICs. Mide la latencia de almacenamiento antes de reescribir configs de VM.
9) ¿Necesito volcar y pasar un archivo ROM VBIOS?
A veces. Es más común cuando la GPU fue inicializada por el firmware del host como pantalla primaria, o cuando la plataforma no expone una option ROM limpia al invitado. Si todo lo demás verifica y aún obtienes pantalla negra, es un experimento razonable siguiente.
10) ¿Por qué el host a veces necesita reinicio después de detener una VM en passthrough?
Porque no todos los dispositivos se reinician de forma fiable. Si el dispositivo no puede volver a un estado limpio, la siguiente asignación falla. No es Proxmox dramatizando; es el hardware negándose a olvidar lo ocurrido.
Conclusión: siguientes pasos que realmente funcionan
Cuando el passthrough falla, tu trabajo no es ser más listo que VFIO. Tu trabajo es demostrar que la plataforma proporciona los prerrequisitos que VFIO requiere: IOMMU habilitado, aislamiento de grupos limpio, binding de controlador correcto y un dispositivo que se reinicie como si respetara los límites.
Haz esto a continuación:
- Captura y guarda tres artefactos por host:
/proc/cmdline, listado de grupos IOMMU ylspci -kpara los dispositivos en passthrough. - Si usas ACS override, escríbelo como una decisión de riesgo, no como un ajuste. Decide si el hardware debe reemplazarse.
- Antes de cambiar args de VM, verifica IOMMU y remapeo IRQ en dmesg. Si están mal, detente y arregla firmware/cmdline.
- Para dispositivos inestables, prueba explícitamente el comportamiento de reinicio: inicia VM, detén VM, inicia otra vez—sin reiniciar el host. Si falla, trata el reinicio como la causa raíz hasta que se demuestre lo contrario.
Una vez que puedas reproducir la falla con evidencia, VFIO deja de ser un chivo expiatorio y se convierte en lo que es: un portero estricto que hace cumplir las reglas que tu plataforma prometió poder seguir.