Los grupos IOMMU son una trampa: cómo lograr passthrough limpio de GPU/NVMe sin lágrimas

¿Te fue útil?

No compraste una GPU para verla sentada detrás de un hipervisor haciendo nada. No compraste un disco NVMe para pasarlo por un controlador emulado como si fuera 2009. Querías rendimiento casi nativo en una VM, y en su lugar te encontraste con un muro etiquetado grupo IOMMU 12.

La trampa es que los grupos IOMMU parecen un problema de marcar una casilla—hasta que se convierten en un problema de topología, firmware y particularidades de la plataforma. La buena noticia: hay un camino limpio, y consiste principalmente en negarse a adivinar.

Qué son realmente los grupos IOMMU (y por qué duelen)

Un grupo IOMMU es la forma que tiene el kernel de decir: “estos dispositivos PCIe no se pueden aislar entre sí de forma segura, así que se tratan como un único dominio de seguridad.” Si pasas un dispositivo del grupo a una VM, confías implícitamente en que todo lo demás en ese grupo no haga DMA indiscriminado contra el host o la VM.

Ese “no se pueden aislar” es la clave. El límite del grupo no lo define tu intuición, la etiqueta del slot en la placa madre ni lo cara que fue la GPU. Lo define la topología PCIe y el comportamiento de Access Control Services (ACS) de los switches/bridges entre el dispositivo y el puerto raíz de la CPU. Si ACS no proporciona aislamiento adecuado (o no lo anuncia), el kernel no fingirá que lo hace.

La consecuencia práctica

Passthrough limpio significa que el dispositivo que quieres—GPU o NVMe—cae en un grupo IOMMU sin nada más que te importe. Idealmente: la GPU y su función de audio juntas, quizá un controlador USB si lo colocaste deliberadamente, y ya. Cuando tu GPU comparte un grupo con tu controlador SATA, una interfaz de red y la mitad del chipset, no estás haciendo “passthrough de GPU.” Estás practicando “esperanza como servicio”.

Dos modelos mentales malos que causan la mayor parte del dolor

  • “Los grupos IOMMU los fija el SO.” El SO informa lo que el hardware y el firmware exponen. No puedes configurar ACS que falte en un switch downstream barato.
  • “Si arranca, es seguro.” La seguridad aquí es aislamiento DMA y remapeo de interrupciones bajo estrés, reinicios en caliente y recuperación de errores. Arrancar no demuestra casi nada.

El filo: el parche de ACS override

En muchas plataformas de consumo, la gente “arregla” agrupaciones feas forzando el comportamiento de ACS mediante el parámetro de kernel pcie_acs_override. Esto puede dividir grupos de una forma que parece perfecta.

Pero es una mentira que le cuentas al kernel. Puede ser una mentira útil en un homelab. En producción o en entornos multiinquilino, es una concesión de seguridad. Le pides al kernel que asuma aislamiento donde la infraestructura puede no aplicarlo.

Usa ACS override solo cuando puedas aceptar el riesgo: host de un solo usuario, invitados de confianza, sin hosting compartido y entiendes el radio de explosión. Si no: cambia la plataforma, cambia el slot o cambia el plan.

Broma #1: ACS override es como poner un cartel de “No entrar” en una puerta sin cerradura. Mejora la sensación, no la seguridad.

Hechos históricos e información relevante

  • VT-d y AMD-Vi no se hicieron para gamers. VT-d de Intel y la IOMMU de AMD (AMD-Vi) surgieron de la necesidad de virtualizar E/S de forma segura en servidores y entornos multiinquilino.
  • DMA fue el “confía en mí, hermano” original. Los dispositivos PCI clásicos podían hacer DMA en la memoria del host con poca restricción; IOMMU existe en gran parte para evitar que un dispositivo escribiera sobre todo.
  • ACS es una característica del tejido PCIe, no de Linux. Linux solo puede agrupar según lo que reporte la jerarquía PCIe sobre lo que se puede aislar.
  • El remapeo de interrupciones forma parte de la historia de seguridad. Incluso con aislamiento DMA, el enrutamiento/remapeo de interrupciones roto puede convertirse en un problema de estabilidad y seguridad bajo carga.
  • Las GPUs se volvieron dispositivos “raros” para passthrough por su comportamiento de reset. Muchas GPUs no fueron diseñadas para un reset limpio por función (FLR) desde un invitado; algunas necesitan resets de bus y otras no se resetean limpiamente en absoluto.
  • NVMe suele ser más fácil que las GPUs… hasta que no lo es. Los controladores NVMe a menudo se comportan bien con FLR y gestión de namespaces, pero las peculiaridades de gestión de energía y ASPM pueden morderte.
  • SR-IOV normalizó la idea de compartir dispositivos de forma segura. Los proveedores de red y almacenamiento impulsaron SR-IOV con fuerza; la virtualización de GPU (vGPU) siguió un camino distinto y más ligado a proveedores.
  • Las placas de consumo se optimizaron por coste, no por aislamiento. Muchos chipsets de escritorio cuelgan múltiples funciones detrás de bridges o switches compartidos que no exponen ACS como lo hacen las plataformas de servidor.

Una idea para tener visible: La esperanza no es una estrategia — atribuida a muchos operadores a lo largo de los años, y la versión SRE es “mide, luego cambia”.

Diseño para passthrough limpio: elige batallas que puedas ganar

1) Empieza por la topología, no por flags del kernel

Antes de tocar GRUB, averigua qué compraste realmente: qué slots son puertos raíz de CPU, cuáles son carriles del chipset, cuáles comparten un switch downstream y cuáles comparten un bridge con “todo lo demás.” Los diagramas de marketing omiten cosas. Necesitas ver el árbol PCIe.

2) Prefiere carriles conectados a la CPU para dispositivos de passthrough

Las GPUs y NVMe de alto rendimiento se comportan mejor cuando están en puertos raíz de CPU. Los dispositivos conectados al chipset suelen compartir ancho de banda y límites de aislamiento, y son más propensos a acabar en grupos IOMMU gigantes con otros controladores.

3) No pases el dispositivo desde el que arrancas

Sí, puedes hacerlo. Sí, puedes lograr que funcione. Y sí, es un generador de caídas cuando hay actualizaciones de firmware, cambios en initramfs o cambios en la enumeración de dispositivos. Mantén el arranque del host en algo aburrido: un SSD SATA pequeño, un par espejado o un M.2 dedicado que nunca entregues a los invitados.

4) GPUs: planifica resets y propiedad de la pantalla

Los fallos en passthrough de GPU a menudo no son “problemas de IOMMU.” Son problemas de reset, ROM o de propiedad del controlador.

  • Reset: Si la GPU no puede resetearse limpiamente entre paradas/inicios de VM, tendrás el temido “funciona una vez después del arranque”.
  • ROM: Algunas configuraciones necesitan un archivo ROM de GPU; otras se rompen si fuerzas uno.
  • Propiedad del host: Si el host carga un controlador y agarra el framebuffer de la GPU temprano, desacoplarla después puede ser desordenado.

5) NVMe: decide entre passthrough y almacenamiento virtual según el dominio de fallo

El passthrough NVMe es excelente para cargas sensibles a la latencia, VMs de juego o appliances de un solo inquilino. Pero cambia quién puede recuperarse de errores.

Si el controlador NVMe se queda colgado y el invitado lo posee, el host no puede necesariamente volver a ponerlo en marcha sin derribar la VM. Si necesitas HA a nivel host, snapshots, replicación o recuperación predecible, un disco virtual sobre una capa de almacenamiento gestionada por el host suele ganar—aunque sea un poco más lento.

6) La única postura sensata de seguridad: trata a los invitados con passthrough como de confianza

VFIO + IOMMU es un aislamiento fuerte cuando la plataforma lo soporta correctamente, pero el passthrough amplía el control del invitado sobre hardware real. Si tu invitado no es de confianza, replantea. Si tu plataforma necesita ACS override, no finjas que estás construyendo un sistema multiinquilino endurecido.

Tareas prácticas: comandos, salidas, decisiones

Vas a diagnosticar esto más rápido tratándolo como cualquier otro problema de operaciones: observa, cambia una cosa, observa otra vez. Abajo hay tareas concretas que puedes ejecutar en un host Linux KVM (incluyendo entornos tipo Proxmox) con notas sobre cómo interpretar la salida y qué decisión tomar.

Tarea 1: Verificar que IOMMU está habilitado (arranque del kernel y dmesg)

cr0x@server:~$ dmesg | egrep -i 'iommu|dmar|amd-vi' | head -n 30
[    0.000000] ACPI: DMAR 0x0000000079B2B000 0000A8 (v01 INTEL  SKL      00000001 INTL 00000001)
[    0.000000] DMAR: IOMMU enabled
[    0.000000] DMAR: Host address width 39
[    0.000000] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[    0.000000] DMAR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
[    0.000000] DMAR: Enabled IRQ remapping in x2apic mode

Significado: Quieres ver “IOMMU enabled” (Intel: DMAR) o “AMD-Vi: Enabled.” Puntos extra si aparece “IRQ remapping enabled”.

Decisión: Si no ves IOMMU habilitado, arregla configuraciones de firmware (VT-d/AMD-Vi) y parámetros del kernel antes de cualquier otra cosa.

Tarea 2: Confirmar la línea de comandos del kernel (capturar flags erróneos)

cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12 root=ZFS=rpool/ROOT/default ro quiet intel_iommu=on iommu=pt

Significado: intel_iommu=on o amd_iommu=on habilita la IOMMU; iommu=pt suele mejorar el rendimiento del host usando mapeos passthrough para dispositivos no VFIO.

Decisión: Mantén iommu=pt para rendimiento salvo que estés depurando algo exótico; es comúnmente adecuado.

Tarea 3: Listar grupos IOMMU y localizar el “grupo monstruo”

cr0x@server:~$ for g in /sys/kernel/iommu_groups/*; do echo "IOMMU Group $(basename "$g")"; for d in "$g"/devices/*; do echo -n "  "; lspci -nns "$(basename "$d")"; done; done | sed -n '1,80p'
IOMMU Group 0
  00:00.0 Host bridge [0600]: Intel Corporation Device [8086:1237]
IOMMU Group 1
  00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:460d]
IOMMU Group 12
  01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2684] (rev a1)
  01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:22bc] (rev a1)
IOMMU Group 13
  02:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Significado: Esto es la verdad. Tu GPU suele ser dos funciones (gráfica + audio) y debería estar en el mismo grupo. Un controlador NVMe idealmente está solo o con hermanos inofensivos que no necesitas.

Decisión: Si tu dispositivo objetivo comparte grupo con dispositivos críticos del host (controlador SATA, NIC que necesitas, controlador USB usado para entrada del host), detente y rediseña: otro slot, otra placa base o acepta el riesgo del ACS override.

Tarea 4: Ver el árbol PCIe (encontrar el bridge que causa la fusión de grupos)

cr0x@server:~$ lspci -tv
-+-[0000:00]-+-00.0  Intel Corporation Device 1237
 |           +-01.0-[01]----00.0  NVIDIA Corporation Device 2684
 |           |            \-00.1  NVIDIA Corporation Device 22bc
 |           +-03.0-[02]----00.0  Samsung Electronics Co Ltd NVMe SSD Controller a808
 |           \-14.0  Intel Corporation Device 7ae0

Significado: Buscas dónde se conecta tu dispositivo: puertos raíz de CPU vs bridges del chipset. El árbol te ayuda a correlacionar “agrupamiento malo” con un bridge upstream particular.

Decisión: Si la GPU/NVMe está detrás de un switch/bridge downstream compartido, prueba otro slot físico que mapee a un puerto raíz diferente.

Tarea 5: Identificar los IDs de tu GPU/NVMe para el binding a vfio-pci

cr0x@server:~$ lspci -nn | egrep -i 'vga|audio|nvme'
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2684] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:22bc] (rev a1)
02:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Significado: Los pares entre corchetes son vendor:device IDs. Vincula esos IDs a vfio-pci para mantener a los drivers del host alejados.

Decisión: Captura todas las funciones que planeas pasar (GPU + audio; a veces una GPU tiene también un controlador USB-C).

Tarea 6: Comprobar qué driver posee actualmente el dispositivo

cr0x@server:~$ lspci -k -s 01:00.0
01:00.0 VGA compatible controller: NVIDIA Corporation Device 2684 (rev a1)
	Subsystem: Gigabyte Technology Co., Ltd Device 4101
	Kernel driver in use: nvidia
	Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia

Significado: Si el host está usando nvidia o nouveau, el passthrough será más difícil. Para VFIO limpio quieres Kernel driver in use: vfio-pci.

Decisión: Si un driver no VFIO está vinculado, necesitas vincular temprano vía initramfs/configuración de modprobe o bloquear el driver.

Tarea 7: Enlazar dispositivos a vfio-pci (config de modprobe) y reconstruir initramfs

cr0x@server:~$ sudo tee /etc/modprobe.d/vfio.conf >/dev/null <<'EOF'
options vfio-pci ids=10de:2684,10de:22bc,144d:a808 disable_vga=1
EOF
cr0x@server:~$ sudo tee /etc/modprobe.d/blacklist-gpu.conf >/dev/null <<'EOF'
blacklist nouveau
blacklist nvidia
blacklist nvidiafb
EOF
cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.12

Significado: Esto fuerza a vfio-pci a reclamar esos IDs de dispositivo en el arranque, antes que otros drivers.

Decisión: Reinicia tras este cambio. Si no puedes reiniciar, no hagas “re-binding en caliente” a menos que disfrutes depurar un host sin cabeza desde el suelo.

Tarea 8: Tras el reinicio, confirmar que vfio-pci posee los dispositivos

cr0x@server:~$ lspci -k -s 01:00.0
01:00.0 VGA compatible controller: NVIDIA Corporation Device 2684 (rev a1)
	Subsystem: Gigabyte Technology Co., Ltd Device 4101
	Kernel driver in use: vfio-pci
	Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia

Significado: Los módulos pueden existir, pero “driver in use” debería ser vfio-pci.

Decisión: Si todavía se vincula a un driver GPU, tu initramfs no incluyó las opciones vfio lo suficientemente temprano, o la pila GPU de la distro lo fuerza. Arregla eso antes de tocar QEMU.

Tarea 9: Comprobar fallos VFIO e IOMMU en el log del kernel

cr0x@server:~$ sudo dmesg -T | egrep -i 'vfio|iommu|dmar|fault' | tail -n 30
[Tue Feb  4 10:10:02 2026] vfio-pci 0000:01:00.0: enabling device (0000 -> 0003)
[Tue Feb  4 10:10:02 2026] vfio-pci 0000:02:00.0: enabling device (0000 -> 0002)
[Tue Feb  4 10:12:17 2026] DMAR: [DMA Read] Request device [02:00.0] fault addr 0x7f1c9000 [fault reason 0x02] Present bit in context entry is clear

Significado: “vfio-pci … enabling device” es normal. Los fallos DMAR/IOMMU no lo son. “Present bit in context entry is clear” suele indicar un problema de mapeo o un dispositivo con comportamiento anómalo.

Decisión: Si ves fallos IOMMU recurrentes bajo carga, sospecha firmware defectuoso, remapeo de interrupciones roto o un dispositivo que no coopera con la plataforma. No lo tapes con parches temporales.

Tarea 10: Validar remapeo de interrupciones (estabilidad y seguridad)

cr0x@server:~$ dmesg | egrep -i 'interrupt remapping|irq remapping|x2apic' | head
[    0.000000] DMAR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
[    0.000000] DMAR: Enabled IRQ remapping in x2apic mode

Significado: Quieres IRQ remapping habilitado, especialmente si te importa la robustez y el aislamiento.

Decisión: Si está deshabilitado, revisa la BIOS (a veces ligado a “Above 4G decoding”, “SR-IOV” o “Intel VT-d”) y los parámetros del kernel. En algunas plataformas, habilitar x2APIC ayuda.

Tarea 11: Comprobar uso de ACS override (saber cuándo te mientes a ti mismo)

cr0x@server:~$ cat /proc/cmdline | tr ' ' '\n' | egrep 'pcie_acs_override|acs'
pcie_acs_override=downstream,multifunction

Significado: Esto es el “divisor de grupos.” Puede hacer que los grupos parezcan limpios sin que el hardware realmente lo haga cumplir.

Decisión: Si esto está presente en un host con invitados no confiables o requisitos de cumplimiento, elimínalo y arregla el hardware/topología en su lugar.

Tarea 12: Comprobar velocidad/anchura del enlace PCIe (cuello de botella de rendimiento escondido a la vista)

cr0x@server:~$ sudo lspci -s 02:00.0 -vv | egrep -i 'LnkCap|LnkSta'
LnkCap: Port #0, Speed 16GT/s, Width x4, ASPM L1, Exit Latency L1 <8us
LnkSta: Speed 8GT/s (downgraded), Width x2 (downgraded)

Significado: Tu NVMe es capaz de PCIe Gen4 x4, pero está funcionando a Gen3 x2. Eso no es un problema de virtualización. Es un problema de slot, BIOS, riser o integridad de señal.

Decisión: Arregla el entrenamiento del enlace antes de medir nada. Cambia de slot, elimina risers, actualiza BIOS o fuerza la generación PCIe en el firmware si es posible.

Tarea 13: Comprobar pertenencia al grupo IOMMU de un solo dispositivo (vista quirúrgica)

cr0x@server:~$ dev=0000:02:00.0; readlink -f /sys/bus/pci/devices/$dev/iommu_group
/sys/kernel/iommu_groups/13

Significado: Te dice exactamente a qué grupo pertenece el dispositivo, útil para scripts y seguimiento de cambios.

Decisión: Si esto cambia tras actualizaciones de BIOS o mover slots, actualiza tu documentación de aprovisionamiento y las configuraciones de VM. No asumas estabilidad.

Tarea 14: Adjuntar vía QEMU/Libvirt y verificar que el invitado vea el dispositivo real

cr0x@server:~$ sudo virsh domblklist win11-gpu
 Target   Source
------------------------------------------------
 vda      /var/lib/libvirt/images/win11.qcow2

cr0x@server:~$ sudo virsh dumpxml win11-gpu | egrep -n 'hostdev|address|vfio' | head -n 40
132:    
133:      
134:        
135:

Significado: La definición de la VM incluye una asignación de dispositivo PCI host. Ese es tu passthrough.

Decisión: Si el invitado ve un controlador de almacenamiento genérico en lugar del modelo NVMe, no pasaste realmente el controlador—you pasaste un disco virtual.

Tarea 15: Medir latencia y E/S dentro del invitado vs host (buscar sobrecarga de virtualización)

cr0x@server:~$ sudo fio --name=randread --filename=/dev/nvme0n1 --ioengine=io_uring --direct=1 --bs=4k --iodepth=32 --numjobs=1 --runtime=15 --time_based --rw=randread
randread: (groupid=0, jobs=1): err= 0: pid=24111: Tue Feb  4 10:21:12 2026
  read: IOPS=182k, BW=712MiB/s (747MB/s)(10.4GiB/15001msec)
    slat (nsec): min=820, max=12514, avg=1790.12, stdev=402.21
    clat (usec): min=49, max=412, avg=173.40, stdev=21.11

Significado: Esta es la referencia en host. Compárala con ejecuciones similares dentro del invitado sobre el NVMe passthrough. Brechas grandes sugieren moderación de interrupciones, gestión de energía o problemas de afinidad CPU—no solo VFIO.

Decisión: Si la latencia en el invitado es mucho peor que en el host, revisa topología de CPU, C-states y si la VM usa MSI/MSI-X correctamente.

Tarea 16: Comprobar si tu NVMe soporta reset de forma sensata (evitar “funciona una vez”)

cr0x@server:~$ sudo nvme id-ctrl /dev/nvme0 | egrep -i 'frmw|oacs|oncs|vwc|lpa' | head
oacs    : 0x17
oncs    : 0x5f
vwc     : 0x1
lpa     : 0x3

Significado: Las capacidades varían; principalmente compruebas que el controlador no sea una rareza barata que se comporte de forma extraña ante resets/eventos de energía.

Decisión: Si la estabilidad del passthrough es pobre, cambia a un controlador más empresarial o al menos a un modelo conocido por comportarse bien en virtualización.

Guion de diagnóstico rápido

Esta es la rutina de “tengo 20 minutos y un VP encima.” El objetivo es identificar si tu cuello de botella es aislamiento, propiedad, reset o simple ancho de banda PCIe.

Primero: topología y aislamiento (no depures fantasmas)

  1. Comprueba los grupos IOMMU y confirma que el dispositivo objetivo no esté pegado a dispositivos críticos del host.
  2. Revisa el árbol PCIe para ver de qué bridge/puerto raíz cuelga el dispositivo.
  3. Comprueba ACS override y decide si te sientes cómodo con el perfil de riesgo.

Segundo: propiedad y binding de drivers (lo aburrido que rompe todo)

  1. Confirma que vfio-pci esté en uso para cada función que pases.
  2. Escanea dmesg en busca de errores VFIO, fallos DMAR y estado del remapeo de interrupciones.
  3. Verifica la configuración de la VM para asegurarte de que incluye hostdev y que no estés benchmarking un disco virtual por accidente.

Tercero: rendimiento y estabilidad (donde “funciona” se vuelve “útil”)

  1. Comprueba ancho/velocidad del enlace por degradaciones (dispositivo Gen4 funcionando a Gen3 x1 es clásico).
  2. Ejecuta una prueba fio corta en host e invitado para comparar patrones de latencia e IOPS.
  3. Busca síntomas de “funciona una vez” relacionados con resets tras parar/iniciar la VM.

Si haces esto en orden, evitas el mayor tiempo perdido: ajustar flags de QEMU por un problema que en realidad es una decisión de enrutamiento de la placa base.

Tres microhistorias corporativas desde la trinchera

Microhistoria 1: El incidente causado por una suposición equivocada

Una empresa mediana construyó una “piscina de GPUs” interna para cargas CI: compilar, probar y ocasionales ejecuciones CUDA. Compraron un conjunto de estaciones de trabajo de consumo, pusieron un par de GPUs en cada una y corrieron KVM con VFIO. Parecía limpio en pruebas iniciales. Una GPU por VM. Todo contento.

Luego llegó una actualización del kernel y el agrupamiento IOMMU cambió sutilmente en un subconjunto de hosts. Mismo modelo de placa, diferentes revisiones de firmware. En esos hosts, una GPU terminó agrupada con un controlador USB que también alojaba el dongle KVM fuera de banda usado por manos remotas. Nadie lo notó porque la VM seguía arrancando.

Durante un reciclado rutinario de VM, VFIO tomó todo el grupo IOMMU. El host no se cayó, pero perdió efectivamente el acceso de entrada remoto. Eso no hubiera sido fatal—salvo que eran “estaciones de trabajo” en una sala cerrada sin BMC real, y la única vía remota era a través de ese controlador USB. Dos personas pasaron la noche coordinando un reinicio físico a través de zonas horarias.

La suposición equivocada no fue “IOMMU existe.” Fue “los grupos IOMMU son estables y consistentes en hardware idéntico.” No lo son. Firmware, cableado de los slots e incluso cambios menores en la enumeración PCIe pueden mover el queso.

La solución fue dolorosamente ordinaria: estandarizar versiones de BIOS, fijar SKUs de hardware y añadir una verificación previa que valide la pertenencia a grupos antes de aprovisionar una VM con GPU. También dejaron de conectar su única ruta de gestión remota a un controlador que podría ser arrebatado por una VM.

Microhistoria 2: La optimización que salió mal

Otra organización quería almacenamiento de baja latencia dentro de una VM Windows que ejecutaba una herramienta de procesamiento de datos con un modelo de licencias quisquilloso. Pasaron un NVMe directamente a la VM. El rendimiento fue espectacular. Los benchmarks eran dignos de gráficas.

Luego llegó la realidad: la VM a veces hacía pantallazo azul bajo ráfagas intensas de escritura, y cuando pasaba, el controlador NVMe a veces quedaba atascado. El host veía un dispositivo que existía pero no completaba comandos. Un reinicio cálido no lo recuperaba de forma fiable. A veces necesitaban un ciclo de energía completo del chasis.

Habían optimizado por la métrica equivocada. Optimizaban por rendimiento en estado estable, no por comportamiento de recuperación. La parte que salió mal no fue que el passthrough sea malo; fue que el dominio de fallo se movió al OS invitado y su pila de drivers, y el hardware no se reseteaba de forma fiable en su plataforma.

La solución final fue dejar de fingir que necesitaban NVMe crudo para esa carga. Migraron la VM a un disco virtual respaldado por la pila de almacenamiento del host con caching de escritura configurado sanamente y snapshots periódicos. Mantuvieron un NVMe de passthrough dedicado en el host para un subconjunto pequeño de cargas que realmente lo requerían, con controladores conocidos y una ruta de reset probada.

Perdieron algo de gloria en benchmarks y ganaron un sistema que se puede reparar sin que alguien vaya al centro de datos con el dedo listo para el botón de encendido.

Microhistoria 3: La práctica aburrida pero correcta que salvó el día

Un equipo de servicios financieros ejecutaba unas pocas VMs de estaciones de trabajo de alto valor para ingeniería y visualización. Tenían gestión de cambios estricta, lo cual es impopular hasta que es lo único entre tú y el caos. Su runbook requería capturar la topología PCIe y listados de grupos IOMMU como artefactos cada vez que cambiaba el firmware.

Un trimestre, una actualización de firmware del proveedor “mejoró la compatibilidad PCIe.” En staging nada falló. Pero su diff de artefactos mostró que el grupo de una GPU ahora incluía un nuevo hermano: una función bridge PCIe previamente oculta. Eso no importaba para bare metal, pero importaba para VFIO porque el bridge metía otros dispositivos.

Como lo notaron antes del despliegue, pararon. Probaron slots alternativos, encontraron uno que mantenía aislada la GPU y actualizaron su estándar físico: “La GPU debe ir en el slot X; el passthrough NVMe debe estar en el slot M.2 CPU Y.”

Cuando el despliegue en producción ocurrió, fue aburrido. Sin sorpresas. El equipo pareció casi decepcionado.

Broma #2: La gestión de cambios es como el hilo dental—nadie quiere hacerlo, y las consecuencias de saltárselo son caras y extrañas.

Errores comunes: síntomas → causa raíz → solución

1) La VM no arranca: “Device is in use” / “cannot reset”

Síntomas: Errores de QEMU sobre reset del dispositivo, o “device is in use.” La VM arranca solo una vez por arranque.

Causa raíz: El driver del host agarró el dispositivo primero, o el dispositivo no soporta FLR limpiamente, o falta una ruta de bus reset adecuada.

Solución: Vincula a vfio-pci en initramfs; evita el framebuffer del host; considera otro modelo de GPU; asegúrate de que el dispositivo esté solo en su grupo; para GPUs con bugs de reset, prueba quirks de reset específicos del proveedor o cambia hardware.

2) El passthrough de GPU funciona, pero el rendimiento es terrible

Síntomas: FPS bajos, stutter, alto uso CPU o el invitado se comporta como si usara un adaptador de pantalla básico.

Causa raíz: La GPU no está realmente pasada (usa virtio-gpu), enlace PCIe degradado, driver del invitado no instalado o problemas de scheduling/afinidad de CPU.

Solución: Verifica que el invitado vea el modelo de GPU; revisa el lspci -vv del host para estado del enlace; instala drivers adecuados en el invitado; fija vCPUs a núcleos físicos y evita sobrecommit para cargas sensibles a latencia/juego interactivo.

3) Passthrough NVMe con buenos benchmarks, luego se corrompe o desaparece

Síntomas: Errores de I/O en el invitado, resets NVMe, dispositivo desaparece hasta reinicio/ciclo de energía.

Causa raíz: Bugs de firmware del controlador bajo virtualización, problemas de gestión de energía/ASPM, comportamiento de reset roto o inestabilidad de la plataforma.

Solución: Desactiva ASPM para ese enlace si hace falta; actualiza BIOS/firmware NVMe; prueba otro controlador; si necesitas fiabilidad, cambia a discos virtuales gestionados por el host.

4) Tras habilitar IOMMU, la red del host se rompe o vuelve inestable

Síntomas: Pérdida de paquetes, resets de NIC, picos de latencia extraños.

Causa raíz: Algunos drivers/plataformas se comportan distinto con remapeo DMA; problemas de remapeo de interrupciones; BIOS defectuosa.

Solución: Asegura que IRQ remapping esté habilitado; actualiza BIOS; prueba otro kernel; considera iommu=pt; si es un bug de plataforma, no lo pelees—reemplaza la placa.

5) “El grupo IOMMU es enorme, así que lo pasaré todo”

Síntomas: El host pierde almacenamiento/NIC/USB; cortes súbitos al iniciar la VM.

Causa raíz: Pasar un grupo que contiene dispositivos críticos del host.

Solución: No lo hagas. Mueve el dispositivo de passthrough a otro slot/puerto raíz o cambia la plataforma. Si debes hacerlo, rediseña el host para que esos “críticos” no los necesite el host (NIC separada, unidad de arranque separada, controlador USB separado).

6) ACS override “arregla” grupos pero introduce problemas espeluznantes después

Síntomas: Fallos raros de DMA/IOMMU, inestabilidad extraña, pánico en auditorías de seguridad.

Causa raíz: Forzar divisiones de grupos sin garantías de aislamiento de hardware ACS.

Solución: Quita el override en entornos serios; muévete a hardware con ACS correcto; usa chipsets/placas workstation o servidor conocidos por agrupaciones sensatas.

Listas de verificación / plan paso a paso

Paso a paso: conseguir passthrough de GPU limpio

  1. Configuración de firmware: Habilita VT-d/AMD-Vi. Habilita “Above 4G decoding” si tienes GPUs modernas y múltiples dispositivos.
  2. Flags de arranque: Añade intel_iommu=on o amd_iommu=on; considera iommu=pt para rendimiento del host.
  3. Mapear grupos: Enumera grupos IOMMU y confirma que la GPU (y su audio) estén aisladas de dispositivos críticos del host.
  4. Elige el slot correcto: Favorece puertos raíz de CPU. Si un slot pasa por bridges/switches del chipset, suele crear grupos desordenados.
  5. Vincula temprano: Configura IDs de vfio-pci y pon en blacklist drivers GPU en conflicto; reconstruye initramfs.
  6. Confirma propiedad: Tras reiniciar, asegúrate de Kernel driver in use: vfio-pci.
  7. Config VM: Pasa todas las funciones GPU que necesites (gráfica + audio; a veces controlador USB-C).
  8. Prueba de estabilidad: Arranca/para la VM varias veces. Si solo funciona una vez, tienes un problema de reset que resolver antes de darlo por “listo.”

Paso a paso: conseguir passthrough NVMe limpio

  1. Decide el dominio de fallo: Si el invitado maneja la recuperación, passthrough está bien. Si el host debe recuperar y snapshotear, favorece discos virtuales.
  2. Aisla el controlador: Asegura que el grupo IOMMU del NVMe no incluya almacenamiento de arranque del host o una NIC que necesites.
  3. Comprueba estado del enlace: Confirma la generación y anchura PCIe esperada. Arregla degradaciones primero.
  4. Vincula a vfio-pci: Igual que con GPUs, hazlo temprano y consistente.
  5. Verificación en el invitado: Confirma que el invitado vea el controlador NVMe real y que los drivers sean correctos.
  6. Prueba de carga: Ejecuta pruebas I/O cortas y brutales. Observa dmesg del host por resets o fallos DMAR.
  7. Gestión de energía: Si encuentras problemas de estabilidad, prueba cambios en ASPM y actualizaciones de firmware.

Checklist operativo: evitar regresiones

  • Registra la topología PCIe (lspci -tv) y los grupos IOMMU como artefactos por host.
  • Estandariza versiones de BIOS/UEFI en un clúster.
  • Tras actualizaciones de firmware, revalida pertenencia a grupos y binding de dispositivos antes de volver a habilitar cargas de producción.
  • Mantén el almacenamiento de arranque del host separado de los dispositivos de passthrough.
  • Mantén una ruta de rollback para cambios de kernel e initramfs.

Preguntas frecuentes

1) ¿Por qué no puedo pasar solo un dispositivo de un grupo IOMMU?

Porque el límite del grupo es el límite de seguridad del kernel para aislamiento DMA. Si los dispositivos no se pueden aislar, pasar uno arriesga que los demás hagan DMA en memoria equivocada.

2) ¿Los grupos IOMMU son lo mismo que carriles PCIe o slots?

No. Los grupos están moldeados por la jerarquía PCIe y las capacidades ACS. Un solo slot físico puede estar detrás de un bridge que fusiona dominios de aislamiento.

3) ¿Es seguro ACS override?

Puedes aceptarlo en setups de un solo usuario y de confianza. No es una suposición segura para entornos multiinquilino o sensibles en seguridad porque puede afirmar aislamiento que el hardware no garantiza.

4) Mi GPU comparte grupo con su dispositivo de audio. ¿Es eso malo?

No, eso es normal. Normalmente pasas ambas funciones juntas. El problema es cuando el grupo incluye dispositivos críticos no relacionados del host.

5) ¿Por qué el passthrough de GPU funciona solo una vez después del reinicio?

Comúnmente un problema de reset: la GPU no soporta FLR limpiamente o la plataforma no puede resetearla tras parar la VM. Binding, quirks de ROM y comportamiento de drivers del proveedor también pueden contribuir.

6) Passthrough NVMe vs virtio-blk sobre ZFS/LVM: ¿cuál es “mejor”?

Para latencia cruda y control directo, NVMe passthrough suele ganar. Para seguridad operacional—snapshots, replicación, recuperación a nivel host—los discos virtuales sobre una capa de almacenamiento gestionada por el host suelen ganar.

7) ¿Habilitar iommu=pt debilita el aislamiento?

Normalmente aplica mapeos passthrough para dispositivos gestionados por el host para reducir sobrecarga, mientras que los dispositivos VFIO siguen usando mapeos estrictos. Se usa ampliamente; valida en tu entorno.

8) ¿Cuál es la forma más rápida de saber si los problemas de rendimiento son por PCIe?

Revisa LnkSta con lspci -vv. Si el enlace está degradado en velocidad o anchura, arregla eso antes de tocar la afinación de VMs.

9) ¿Debo pasar todo el NVMe o usar namespaces?

Si necesitas separación estricta y tu stack lo soporta, los namespaces pueden ayudar—pero sigues tratando con un solo controlador y sus peculiaridades. Para simplicidad y menos sorpresas, pasa el controlador entero.

10) ¿Puedo hacer passthrough limpio en hardware de consumo?

A veces sí—especialmente si la placa tiene buen comportamiento ACS y slots conectados a la CPU. Pero apuestas a la suerte de la topología. Si la disponibilidad importa, compra hardware diseñado para ser aburrido.

Conclusión: próximos pasos que realmente funcionan

Si quieres passthrough limpio de GPU/NVMe, deja de tratar los grupos IOMMU como un obstáculo que puedes discutir. Son un suero de la verdad del hardware.

Haz esto a continuación:

  1. Inventaría tu agrupamiento actual y el árbol PCIe. Guárdalo. Trátalo como configuración, porque lo es.
  2. Mueve el dispositivo a un slot/puerto raíz de CPU si el agrupamiento es feo.
  3. Vincula a vfio-pci temprano, confirma propiedad tras reiniciar y rehúsa depurar drivers de invitados hasta que el lado host esté limpio.
  4. Haz benchmarks de velocidad/anchura del enlace y latencia antes y después, para saber si realmente mejoraste algo.
  5. Si dependes de ACS override para “seguridad”, para y reescala el proyecto: acepta invitados de confianza o compra la plataforma correcta.

Cuando el passthrough está limpio, es un placer. Cuando no lo está, es una carrera profesional en interpretar mensajes de error. Elige el placer. Arregla la topología.

← Anterior
Cuentas de administrador local: la puerta trasera oculta en tu propio PC
Siguiente →
Monitor externo no detectado: El único controlador que te falta

Deja un comentario