Miras Proxmox, intentas pasar una GPU, HBA o NIC a una VM y te aparece la clásica ducha fría: “IOMMU no habilitado”. Has activado “algo” en la BIOS, has reiniciado dos veces y ahora te preguntas si la máquina te está tomando el pelo.
Este problema casi nunca es místico. Normalmente es una de cinco cosas: conmutadores de firmware, el archivo del bootloader equivocado, parámetros del kernel faltantes, módulos VFIO ausentes o una placa que agrupa dispositivos como si quisiera evitar que tengas hobbies. Lo resolveremos de forma segura, con evidencia en cada paso y con opciones de reversión para que no conviertas un host remoto en un ladrillo a las 2 a. m.
Qué es realmente IOMMU (y por qué a Proxmox le importa)
Un IOMMU (Intel VT-d, AMD-Vi) es una unidad de gestión de memoria para dispositivos. Las CPU tienen una MMU que traduce direcciones de memoria virtual a física para procesos. El IOMMU hace el mismo tipo de traducción para DMA (Acceso Directo a Memoria) desde dispositivos PCIe: NICs, HBAs, GPUs, controladores USB y compañía.
El passthrough PCI depende de esto porque cuando entregas un dispositivo real a una VM necesitas que el host haga cumplir “este dispositivo solo puede hacer DMA en la memoria de esta VM”. Sin eso, un dispositivo podría garabatear sobre la memoria del host o de otra VM. Dejando de lado la seguridad, también es estabilidad: un DMA aleatorio en el lugar equivocado produce el tipo de pánicos de kernel creativos.
Así que Proxmox comprueba IOMMU. Si no lo detecta, se niega a fingir que todo está bien. Eso no es Proxmox siendo quisquilloso. Es Proxmox evitando que tu controlador de almacenamiento se convierta accidentalmente en un generador de arte abstracto.
Un mantra de fiabilidad que vale la pena llevar en el bolsillo viene de John Allspaw, idea parafraseada: La fiabilidad viene de diseñar pensando en la falla y aprender de ella, no de fingir que las fallas no ocurrirán.
Esa es la postura aquí: haz cambios, verifícalos, conserva la reversión.
Además: “IOMMU no habilitado” es un mensaje sobre el host. Aún no tiene que ver con la configuración de tu VM. No pierdas tiempo editando archivos de VM hasta que el host demuestre que tiene IOMMU activado y funcionando.
Datos e historia interesantes (por qué esto es un lío)
- Hecho 1: La marca de IOMMU de Intel es VT-d; VT-x es virtualización de CPU. La gente las confunde constantemente, incluso en menús de BIOS de proveedores.
- Hecho 2: La implementación IOMMU de AMD se suele llamar AMD-Vi, y el interruptor en la BIOS a menudo aparece etiquetado simplemente como “IOMMU”.
- Hecho 3: El passthrough PCI temprano en Linux se basaba en el viejo enfoque “pciback” antes de que VFIO se convirtiera en el estándar. VFIO ganó porque es más sensato y seguro.
- Hecho 4: Los límites de grupo IOMMU provienen de las tablas ACPI y de la topología PCIe. Dos CPUs idénticas con dos placas base diferentes pueden comportarse de forma radicalmente distinta.
- Hecho 5: “ACS” (Access Control Services) es una característica de PCIe que ayuda a aislar dispositivos detrás de switches/bridges. Algunas placas de consumo lo omiten o lo implementan parcialmente.
- Hecho 6: El kernel de Linux ha soportado remapeo de DMA durante mucho tiempo, pero los valores por defecto y las heurísticas cambiaron entre versiones—especialmente en el equilibrio rendimiento vs seguridad.
- Hecho 7: Las GPUs de consumo de NVIDIA históricamente han peleado con la virtualización de varias maneras; los controladores modernos son mejores, pero la tradición persiste porque la gente tiene cicatrices.
- Hecho 8: El “remapeo de interrupciones” forma parte de la historia: ayuda a mantener las interrupciones de dispositivos correctamente aisladas. Su ausencia puede bloquear algunos setups avanzados de passthrough.
- Hecho 9: Proxmox hace esto accesible, pero debajo sigue siendo Linux: parámetros de arranque, initramfs, módulos, sysfs y el ocasional problema de firmware.
Ese es el contexto. Ahora la parte práctica: haz que el host demuestre que puede hacer IOMMU, luego que demuestre que puede aislar el dispositivo que te interesa, y luego pásalo.
Guía rápida de diagnóstico
Si estás de guardia, no quieres filosofía. Quieres la ruta más rápida para “¿es esto BIOS, bootloader, kernel o topología de hardware?” Aquí está el orden que más veces gana.
Primero: confirma la realidad de las extensiones de CPU y del conmutador de firmware
- ¿El CPU/plataforma soporta VT-d/AMD-Vi?
- ¿Está activado en la BIOS/UEFI (no solo “virtualización” sino IOMMU/VT-d específicamente)?
- ¿Reiniciaste después de cambiarlo? (Un reinicio en caliente suele contar, pero algunas placas requieren ciclo de alimentación completo).
Segundo: confirma que el kernel recibió los parámetros correctos
- Revisa la línea de comando real de arranque en
/proc/cmdline. - No confíes en el archivo que editaste hasta que lo veas reflejado en el kernel en ejecución.
Tercero: confirma que el kernel inicializó realmente IOMMU
- Busca líneas DMAR/IOMMU en
dmesg. - Verifica que
/sys/kernel/iommu_groupsexista y esté poblado.
Cuarto: verifica agrupamientos antes de culpar a VFIO
- Un mal agrupamiento IOMMU es un problema de topología/firmware, no de VFIO.
- Sé consciente de lo que estás dispuesto a hacer: mover la tarjeta a otro slot, o aceptar los riesgos del ACS override.
Quinto: solo entonces enlaza el dispositivo a vfio-pci
- Identifica el dispositivo por vendor:device ID.
- Enlázalo en initramfs para que el driver del host no lo capture primero.
Este orden evita el error clásico: pasar una hora en la vinculación VFIO mientras IOMMU sigue apagado en la capa de firmware.
Seguridad previa al vuelo: no te quedes varado
Habilitar IOMMU suele ser seguro. Lo inseguro es cómo la gente lo hace: editar la configuración de arranque equivocada, añadir parámetros agresivos, reiniciar un host remoto sin acceso fuera de banda y descubrir que no vuelve.
Antes de tocar nada:
- Confirma que tienes acceso a consola (IPMI/iDRAC/iLO, KVM-over-IP, o al menos alguien que pueda conectar un monitor).
- Programa una ventana de reinicio. Esto es territorio de kernel/firmware; vas a reiniciar.
- Haz una copia de seguridad de los archivos de configuración que cambies y conserva una entrada de arranque conocida buena si es posible.
- Conoce tu modo de arranque: GRUB vs systemd-boot. Proxmox puede usar cualquiera dependiendo del método de instalación y del layout de almacenamiento.
Broma corta #1: Si estás habilitando IOMMU en una caja remota sin consola, no haces SRE—haces arte performativo.
Tareas prácticas: comandos, salidas, decisiones (12+)
Estas tareas están ordenadas como yo las haría en un host Proxmox de producción. Cada una incluye lo que significa y qué decisión tomas después.
Task 1: confirma extensiones de virtualización del CPU (chequeo de cordura)
cr0x@server:~$ lscpu | egrep -i 'Vendor ID|Model name|Virtualization|Flags'
Vendor ID: GenuineIntel
Model name: Intel(R) Xeon(R) CPU E-2278G @ 3.40GHz
Virtualization: VT-x
Flags: ... vmx ...
Qué significa: VT-x (Intel) o SVM (AMD) es virtualización de CPU. Esta salida no confirma VT-d/AMD-Vi, pero te indica que no estás en hardware antiguo.
Decisión: Procede. Si no ves vmx (Intel) o svm (AMD), puede que estés en el modo BIOS equivocado, o la virtualización esté deshabilitada completamente.
Task 2: identifica si estás en Intel o AMD (para elegir parámetros del kernel)
cr0x@server:~$ lscpu | awk -F: '/Vendor ID/ {print $2}'
GenuineIntel
Qué significa: Intel usa intel_iommu=on; AMD usa amd_iommu=on. Sí, hay otros modos, pero empieza simple.
Decisión: Elige el parámetro correcto para tu plataforma. Un parámetro equivocado normalmente no hace nada, y así es como acabas “seguro de haberlo habilitado”.
Task 3: confirma modo de arranque y bootloader (GRUB vs systemd-boot)
cr0x@server:~$ proxmox-boot-tool status
Re-executing '/usr/sbin/proxmox-boot-tool' in new private mount namespace..
System currently booted with uefi
Found 1 ESP(s) configured:
/dev/disk/by-uuid/9A1B-2C3D mounted on /boot/efi
Configured with: systemd-boot
Qué significa: Este host usa systemd-boot. Editar /etc/default/grub sería una buena pérdida de tiempo.
Decisión: Si ves systemd-boot, normalmente editarás /etc/kernel/cmdline y ejecutarás proxmox-boot-tool refresh. Si ves GRUB, edita /etc/default/grub y ejecuta update-grub.
Task 4: comprueba la línea de comando actual del kernel (la fuente de la verdad)
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet
Qué significa: Actualmente no hay parámetros de IOMMU en efecto.
Decisión: Añade los parámetros correctos y reinicia. No sigas con VFIO hasta que esto cambie.
Task 5A (systemd-boot): establece parámetros del kernel de forma segura
cr0x@server:~$ sudo cp -a /etc/kernel/cmdline /etc/kernel/cmdline.bak
cr0x@server:~$ echo "root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt" | sudo tee /etc/kernel/cmdline
root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt
Qué significa: Has establecido los parámetros para Intel. iommu=pt usa modo passthrough para dispositivos del host (a menudo mejor rendimiento, mantiene aislamiento para VFIO).
Decisión: Refresca las entradas de arranque e integración initramfs usando las herramientas de Proxmox.
Task 6A (systemd-boot): aplica y sincroniza la configuración de arranque
cr0x@server:~$ sudo proxmox-boot-tool refresh
Re-executing '/usr/sbin/proxmox-boot-tool' in new private mount namespace..
Running hook script 'proxmox-auto-removal'..
Copying kernel and creating EFI boot entry
Refreshing /dev/disk/by-uuid/9A1B-2C3D
Success.
Qué significa: Tu nuevo cmdline del kernel está ahora en el entorno de arranque UEFI que usa Proxmox.
Decisión: Reinicia cuando tengas acceso a consola.
Task 5B (alternativa GRUB): establece parámetros del kernel
cr0x@server:~$ sudo cp -a /etc/default/grub /etc/default/grub.bak
cr0x@server:~$ sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 intel_iommu=on iommu=pt"/' /etc/default/grub
cr0x@server:~$ grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"
Qué significa: Los parámetros se incrustarán en la configuración generada por GRUB en el siguiente paso.
Decisión: Ejecuta update-grub y reinicia.
Task 6B (alternativa GRUB): regenera la configuración de GRUB
cr0x@server:~$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.8.12-4-pve
Found initrd image: /boot/initrd.img-6.8.12-4-pve
done
Qué significa: La configuración de GRUB está actualizada. Aún no está activa hasta el reinicio.
Decisión: Reinicia con la consola lista.
Task 7: reinicia y verifica que el cmdline cambió realmente
cr0x@server:~$ sudo reboot
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt
Qué significa: Ya no estás adivinando. El kernel en ejecución tiene parámetros de IOMMU.
Decisión: Ahora revisa los logs del kernel para confirmar la inicialización.
Task 8: confirma que IOMMU se inicializó en dmesg (DMAR de Intel o IOMMU de AMD)
cr0x@server:~$ dmesg | egrep -i 'DMAR|IOMMU|AMD-Vi|Interrupt Remapping' | head -n 20
[ 0.000000] DMAR: IOMMU enabled
[ 0.000000] DMAR: Host address width 39
[ 0.123456] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[ 0.234567] DMAR: Interrupt remapping enabled
Qué significa: Esto es lo que cuenta. Si no ves “IOMMU enabled” (o equivalentes de AMD), aún no has terminado.
Decisión: Si falta, vuelve atrás: ajustes de firmware, parámetro de arranque equivocado o limitación de plataforma.
Task 9: comprueba que existen grupos IOMMU en sysfs
cr0x@server:~$ ls -1 /sys/kernel/iommu_groups | head
0
1
10
11
12
13
14
15
16
17
Qué significa: Existen grupos. Eso sugiere fuertemente que IOMMU está operativo.
Decisión: Pasa a identificar tu dispositivo y verificar el aislamiento.
Task 10: lista dispositivos PCI y encuentra el que quieres pasar
cr0x@server:~$ lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation Device [8086:3ec2]
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]
Qué significa: La GPU está en 01:00.0 y su función de audio en 01:00.1. Para GPUs, normalmente haces passthrough de ambas funciones juntas.
Decisión: Anota las direcciones BDF y los vendor:device IDs. Los necesitarás para el binding VFIO y la configuración de la VM.
Task 11: ve qué driver del kernel posee actualmente el dispositivo
cr0x@server:~$ lspci -nnk -s 01:00.0
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
Subsystem: Hewlett-Packard Company Device [103c:12a3]
Kernel driver in use: nouveau
Kernel modules: nouveau
Qué significa: El driver del host nouveau agarró la GPU. Eso competirá con VFIO.
Decisión: Planea enlazar este dispositivo a vfio-pci temprano (initramfs) y bloquear drivers conflictivos si es necesario.
Task 12: carga módulos VFIO (y hazlos persistentes)
cr0x@server:~$ printf "vfio\nvfio_iommu_type1\nvfio_pci\nvfio_virqfd\n" | sudo tee /etc/modules-load.d/vfio.conf
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
cr0x@server:~$ sudo modprobe vfio_pci
cr0x@server:~$ lsmod | egrep '^vfio'
vfio_pci 16384 0
vfio_iommu_type1 45056 0
vfio 65536 2 vfio_pci,vfio_iommu_type1
Qué significa: VFIO está disponible ahora y se cargará en el arranque en el futuro.
Decisión: Luego enlaza los IDs específicos a vfio-pci y reconstruye initramfs para que el binding ocurra antes de que los drivers del host adjunten el dispositivo GPU.
Task 13: enlaza vendor:device IDs específicos a vfio-pci
cr0x@server:~$ echo "options vfio-pci ids=10de:1eb1,10de:10f8 disable_vga=1" | sudo tee /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:1eb1,10de:10f8 disable_vga=1
Qué significa: En el arranque, vfio-pci debería reclamar esos IDs.
Decisión: Si esta es tu única GPU y dependes de la consola local, párate y piensa. Pasar la única tarjeta de vídeo puede dejar al host “sin cabeza” de maneras sorprendentes.
Task 14: blacklist de drivers GPU conflictivos (solo si hace falta)
cr0x@server:~$ printf "blacklist nouveau\noptions nouveau modeset=0\n" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
Qué significa: Evita que el driver libre de NVIDIA se enlace primero. La lógica es similar para otros dispositivos (p. ej., ixgbe para ciertas NICs), pero blacklistear drivers de NIC puede cortarte tu propio cable de red. No lo hagas a la ligera.
Decisión: Reconstruye initramfs y reinicia para asegurar el binding temprano.
Task 15: reconstruye initramfs (para que el binding VFIO ocurra temprano)
cr0x@server:~$ sudo update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.8.12-4-pve
Qué significa: La selección de drivers en el arranque ahora respetará tu configuración VFIO antes.
Decisión: Reinicia y verifica que el dispositivo sea reclamado por vfio-pci.
Task 16: verifica que el dispositivo ahora esté enlazado a vfio-pci
cr0x@server:~$ sudo reboot
cr0x@server:~$ lspci -nnk -s 01:00.0
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
Subsystem: Hewlett-Packard Company Device [103c:12a3]
Kernel driver in use: vfio-pci
Kernel modules: nouveau
Qué significa: Perfecto. El host ve la tarjeta y vfio-pci la posee. La línea “Kernel modules” puede seguir listando módulos posibles; lo que importa es “driver in use”.
Decisión: Ahora verifica la pertenencia a grupos IOMMU para asegurarte de que puedas pasarla de forma segura.
Task 17: lista grupos IOMMU con dispositivos (la verdad de la topología)
cr0x@server:~$ for g in /sys/kernel/iommu_groups/*; do \
echo "IOMMU Group ${g##*/}"; \
for d in "$g"/devices/*; do echo " $(lspci -nn -s ${d##*/})"; done; \
done | sed -n '1,40p'
IOMMU Group 1
00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:1901]
IOMMU Group 2
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
IOMMU Group 3
03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]
Qué significa: Las funciones de la GPU están aisladas en su propio grupo. Eso es lo que quieres. Si tu GPU comparte grupo con, por ejemplo, un controlador SATA o un controlador USB que necesitas en el host, tienes un problema.
Decisión: Si el aislamiento es bueno, procede a la configuración de la VM. Si no, entras en la zona de “mover ranura / actualizar BIOS / decisión sobre ACS override”.
Task 18: comprueba que KVM es realmente usable (no lo omitas en plataformas extrañas)
cr0x@server:~$ lsmod | egrep 'kvm|vfio'
kvm_intel 380928 0
kvm 1032192 1 kvm_intel
vfio_pci 16384 0
vfio_iommu_type1 45056 0
vfio 65536 2 vfio_pci,vfio_iommu_type1
Qué significa: La virtualización está presente (kvm_intel o kvm_amd) y la pila VFIO está cargada.
Decisión: Si KVM no está cargado, estás resolviendo otro problema (virtualización de BIOS deshabilitada o complejidades de virtualización anidada). No lo confundas con IOMMU.
Task 19: verifica que Proxmox vea IOMMU de forma visible para el usuario
cr0x@server:~$ pvesh get /nodes/$(hostname)/hardware/pci --noborder | head -n 20
┌─────────┬───────────────────────────────────────────────────────────┬────────────┬────────────┬─────────────┬───────────────┐
│ class │ device │ id │ iommugroup │ subsystem_id │ subsystem_name │
╞═════════╪═══════════════════════════════════════════════════════════╪════════════╪════════════╪═════════════╪═══════════════╡
│ 0x0300 │ NVIDIA Corporation TU104GL [Quadro RTX 4000] │ 0000:01:00 │ 2 │ 103c:12a3 │ Hewlett-Packard│
└─────────┴───────────────────────────────────────────────────────────┴────────────┴────────────┴─────────────┴───────────────┘
Qué significa: Proxmox puede mapear dispositivos a grupos IOMMU. Eso es un fuerte indicador de que tu trabajo anterior es correcto.
Decisión: Configura el passthrough en la VM. Si Proxmox aún muestra “IOMMU no habilitado” en este punto, probablemente estés viendo un estado de UI obsoleto, el nodo equivocado o lo habilitaste en el host equivocado.
GRUB vs systemd-boot en Proxmox: elige la palanca correcta
Este es el tiempo que más veo desperdiciado en entornos reales: alguien edita GRUB, pero el sistema arranca con systemd-boot; o edita /etc/kernel/cmdline, pero el sistema usa GRUB. Ambos enfoques son “trabajo Linux válido” que no cambia nada en el host en ejecución.
Cómo distinguir rápido
- systemd-boot (común con raíz ZFS, UEFI):
proxmox-boot-tool statusmuestra “Configured with: systemd-boot”. Editas/etc/kernel/cmdliney ejecutasproxmox-boot-tool refresh. - GRUB:
efibootmgr -va menudo muestra GRUB, yproxmox-boot-toolpuede no estar en uso. Editas/etc/default/gruby ejecutasupdate-grub.
Parámetros del kernel que suelen ser valores por defecto sensatos
- Intel:
intel_iommu=on iommu=pt - AMD:
amd_iommu=on iommu=pt
Parámetros que la gente añade porque lo vio online (y por qué hay que ser cauteloso)
pcie_acs_override=downstream,multifunction: puede dividir grupos artificialmente; además reduce las garantías de aislamiento. Úsalo solo cuando entiendas el riesgo y lo aceptes.intel_iommu=on,igfx_off: puede ayudar con quirks de iGPU en algunos sistemas, pero no lo sigas a ciegas.iommu=soft: no es lo que quieres para passthrough; es un modo de reserva y puede derrotar tu objetivo.
La mentalidad correcta: añade los parámetros mínimos para habilitar IOMMU. Verifica. Luego resuelve el agrupamiento. Luego resuelve el binding. Todo lo demás es condimento, no el plato principal.
Vincular dispositivos a VFIO (sin robar tu disco de arranque)
Una vez que IOMMU funciona, VFIO es el mecanismo que hace manejable el passthrough. La idea central es simple: indica al host que adjunte un dispositivo a vfio-pci en lugar de su driver habitual, para que QEMU pueda tomarlo para la VM.
La forma segura: enlazar por vendor:device ID, no por “lo que esté en 01:00.0”
Enlazar por dirección PCI puede funcionar, pero enlazar por ID suele ser más robusto entre reinicios y cambios de topología. También es más peligroso si eres descuidado: si enlazas por accidente tu controlador de almacenamiento, tendrás un reinicio muy educativo.
Qué pasar juntos
- GPUs: normalmente función VGA + función de audio HDMI/DP.
- HBAs: todo el controlador. No pases discos individuales de un controlador que también usas en el host, salvo que te gusten los casos límite.
- Controladores USB: pasar todo el controlador suele ser mejor que passthrough por dispositivo, especialmente para dongles y dispositivos de baja latencia.
- NICs: pueden ser excelentes, pero piensa en el acceso de gestión. Si pasas la única NIC, podrías cortar tu sesión SSH en pleno vuelo.
Cuándo hacer blacklist de drivers
Si el driver del host agarra el dispositivo antes que VFIO, el binding puede fallar. El blacklist ayuda, pero es una herramienta tosca. Hacer blacklist del driver de una GPU en un servidor sin cabeza está bien. Hacer blacklist del driver de una NIC en un host remoto es la forma más rápida de descubrir si realmente tienes IPMI.
Broma corta #2: Hacer blacklist del driver de tu única NIC es una vía rápida para lograr cumplimiento “air-gapped”.
Grupos IOMMU: cómo leerlos y qué hacer con agrupaciones malas
Los grupos IOMMU son la frontera de seguridad. Los dispositivos en el mismo grupo no pueden aislarse de forma segura entre sí para propósitos de passthrough. En la práctica, esto significa: si pasas un dispositivo de un grupo a una VM, normalmente necesitas pasar todos los dispositivos de ese grupo, o aceptar un riesgo aumentado.
Cómo se ve un “mal agrupamiento”
Una pesadilla común: la GPU comparte un IOMMU group con un controlador SATA, un controlador USB o un bridge PCI que también hospeda dispositivos que necesitas. Proxmox con frecuencia rechazará el passthrough o mostrará advertencias fuertes. Eso no es Proxmox dramatizando; refleja la capacidad de la plataforma para aislar DMA.
Tres palancas que realmente funcionan (ordenadas por corrección)
- Mueve la tarjeta a otro slot PCIe. Slot distinto, puertos downstream distintos, agrupamiento distinto. Es la solución “gratis” más efectiva.
- Actualiza el firmware BIOS/UEFI. Los proveedores a veces corrigen problemas con tablas ACS/DMAR. A veces no, pero vale la pena intentarlo antes de los hacks.
- Parámetro de kernel ACS override. Esto puede dividir grupos por la fuerza. También puede darte una falsa sensación de aislamiento. Úsalo solo si aceptas el modelo de riesgo (normalmente en homelab; raramente en entornos regulados).
Qué hago en producción
En entornos de producción donde la frontera VM importa, evito ACS override. Si la placa no agrupa bien los dispositivos, elijo otro hardware, o rediseño: SR-IOV para NICs cuando sea posible, o un servicio a nivel de host en lugar de passthrough.
Si estás haciendo un “workstation en una VM” en una sola máquina y estás dispuesto a cambiar aislamiento estricto por funcionalidad, ACS override puede ser aceptable. Solo no pretendas que es “la misma seguridad”. No lo es.
Tres microhistorias corporativas desde el terreno
1) Incidente causado por una suposición errónea: “virtualización habilitada” significaba VT-d habilitado
Un equipo desplegó un nuevo cluster Proxmox para un laboratorio que alojaba un montón de appliances en VMs. Uno de esos appliances necesitaba pasar una NIC de doble puerto para temporización de paquetes y un requisito de soporte del proveedor. El ingeniero que hizo la instalación habilitó “Intel Virtualization Technology” en la BIOS, verificó que KVM se cargó y siguió adelante.
Durante la ventana de corte, el passthrough falló con “IOMMU no habilitado.” El equipo asumió que era una regresión de Proxmox porque el kernel se había actualizado recientemente. Persiguieron configuraciones VFIO durante una hora, reconstruyeron initramfs dos veces y pusieron en blacklist un driver que no importaba. Mientras tanto, el entorno antiguo ya se estaba drenando y apagando porque el plan era “cambio limpio”.
La solución fue vergonzosamente simple: la BIOS tenía dos conmutadores separados—VT-x y VT-d. VT-x estaba habilitado; VT-d estaba deshabilitado por defecto. La máquina reinició, DMAR apareció en dmesg y todo funcionó.
La lección no fue “lee el manual”. La lección fue: siempre verifica el estado del kernel en ejecución (/proc/cmdline, dmesg, /sys/kernel/iommu_groups) antes de tocar VFIO. Las suposiciones son cómodas. La producción no lo es.
2) Optimización que salió mal: ACS override como atajo
Otro entorno quería maximizar densidad. Tenían hosts con placas de consumo (esas que lucen bien en una hoja de especificaciones). Necesitaban pasar varios dispositivos por host: una GPU para workloads tipo VDI y un controlador USB para dongles de licencias. El agrupamiento era pésimo: varios puertos root y endpoints cayeron en un gran grupo IOMMU.
Alguien encontró el parámetro ACS override y lo vendió como “solución limpia”. Sí dividió los grupos. Proxmox dejó de quejarse. El despliegue siguió y los dashboards quedaron en verde.
Semanas después, comenzaron a ver problemas raros pero desagradables: las VMs ocasionalmente se quedaban bloqueadas bajo I/O pesado. El host no se caía, pero la VM afectada quedaba no responsiva y los reinicios a veces fallaban. No hubo una única causa obvia. Solo timeouts de VFIO dispersos y ruido ocasional de PCIe AER.
Finalmente revertieron el ACS override y replantearon el diseño: movieron cargas críticas a servidores con mejor aislamiento PCIe y usaron redirección USB por red cuando era tolerable. La “optimización” no fue por rendimiento; fue por cronograma. Compró tiempo y estabilidad de costes.
La moraleja: ACS override no es un almuerzo gratis. Es un compromiso que deberías documentar como riesgo, no una “solución final”.
3) Práctica aburrida pero correcta que salvó el día: reinicio escalonado y entradas de arranque para reversión
Una empresa enfocada en almacenamiento corría hosts Proxmox con HBAs para ZFS y una NIC dedicada en passthrough para una VM firewall. Necesitaban habilitar IOMMU en un subconjunto de hosts para soportar una nueva tarjeta PCIe. Lo hicieron de la forma lenta y correcta: un host a la vez, fuera de horas, con consola fuera de banda verificada.
También mantuvieron un plan de reversión que era casi ofensivamente poco glamoroso. Antes de cambiar parámetros de arranque, copiaron el archivo de configuración relevante, anotaron el /proc/cmdline actual y aseguraron que había una entrada de arranque conocida y buena disponible. En hosts con systemd-boot verificaron proxmox-boot-tool status y ejecutaron proxmox-boot-tool refresh explícitamente. Nada de “creo que se sincroniza automáticamente”.
En el tercer host, habilitar IOMMU expuso un bug de firmware: la máquina arrancó, pero la enumeración PCIe cambió y un nombre de NIC se desplazó. Su VM firewall no arrancó porque su configuración referenciaba un mapeo de interfaz que ya no existía. Como el cambio fue escalonado, solo un segmento del sitio se vio afectado y la reversión fue sencilla.
Lo arreglaron fijando el nombrado de interfaces de forma más robusta y luego continuaron host por host. La práctica que les salvó no fue ingeniosa—fue hacer un cambio a la vez y tener una forma de volver atrás. La victoria en fiabilidad fue aburrida.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: la UI de Proxmox dice “IOMMU no habilitado” después de que “habilitaste virtualización” en BIOS
Causa raíz: VT-x/SVM habilitado, pero VT-d/AMD-Vi (IOMMU) sigue deshabilitado, o requiere un ciclo de alimentación.
Solución: Habilita VT-d (Intel) o IOMMU/AMD-Vi (AMD) explícitamente en firmware. Luego arranque en frío si es necesario. Confirma con dmesg | egrep -i 'DMAR|AMD-Vi'.
2) Síntoma: editaste GRUB, pero /proc/cmdline nunca cambia
Causa raíz: El host usa systemd-boot, no GRUB (común en setups UEFI + ZFS).
Solución: Edita /etc/kernel/cmdline, ejecuta proxmox-boot-tool refresh, reinicia y vuelve a comprobar /proc/cmdline.
3) Síntoma: /proc/cmdline incluye intel_iommu=on, pero dmesg no muestra líneas DMAR
Causa raíz: El firmware aún deshabilita VT-d, o la plataforma no lo soporta, o las tablas DMAR están rotas/ocultas por ajustes de BIOS (a veces “Above 4G decoding” y ajustes relacionados de PCIe interactúan).
Solución: Revisa opciones de firmware, actualiza BIOS, intenta activar “Above 4G decoding” en algunas plataformas (especialmente para múltiples GPUs) y verifica los logs al arrancar.
4) Síntoma: IOMMU habilitado, pero tu GPU comparte un grupo con media máquina
Causa raíz: Soporte ACS pobre / topología PCIe en la placa base. Común en placas de consumo.
Solución: Mueve la tarjeta a otro slot, actualiza BIOS o acepta el riesgo de ACS override. Si esto es producción con necesidades estrictas de aislamiento: cambia hardware.
5) Síntoma: la VM no arranca; “device is in use” o “cannot bind to vfio”
Causa raíz: El driver del host aún posee el dispositivo (nouveau/nvidia/amdgpu, o un driver de almacenamiento/NIC), o el binding no estaba en initramfs.
Solución: Enlaza con /etc/modprobe.d/vfio.conf, reconstruye initramfs, reinicia, confirma Kernel driver in use: vfio-pci.
6) Síntoma: el host arranca, pero la consola local está muerta después del binding VFIO
Causa raíz: Has enlazado la única GPU a VFIO. El host no tiene nada con qué mostrar.
Solución: Usa una iGPU para la consola del host, añade una GPU económica adicional para el host, o asume el modo sin cabeza + gestión remota.
7) Síntoma: el passthrough funciona, pero el rendimiento es extraño (picos de latencia)
Causa raíz: Remapeo de interrupciones deshabilitado, peculiaridades MSI/MSI-X, gestión de energía o desacople CPU/NUMA. No es estrictamente “IOMMU no habilitado”, pero a menudo se descubre justo después.
Solución: Confirma el remapeo de interrupciones en dmesg, revisa la localidad NUMA, considera fijar vCPUs y evita pasar dispositivos entre nodos NUMA si puedes.
8) Síntoma: después de habilitar IOMMU, cambiaron los nombres de interfaces de red y las VMs perdieron conectividad
Causa raíz: Cambió la enumeración PCI; el nombrado predecible de interfaces cambió; la configuración del bridge referencia nombres antiguos.
Solución: Usa nombrado estable (por MAC en la configuración de red de Proxmox), verifica /etc/network/interfaces y trata la habilitación de IOMMU como un “reinicio con posibles cambios de enumeración”.
Listas de verificación / plan paso a paso
Paso a paso: habilitar IOMMU de forma segura en un host Proxmox
- Consigue acceso a consola (IPMI/iDRAC/iLO). Si no puedes, detente.
- Identifica la plataforma: Intel vs AMD (
lscpu). - Habilita la opción en firmware: VT-d (Intel) o IOMMU/AMD-Vi (AMD). Guarda y reinicia. Si no aparece después, haz un arranque en frío.
- Identifica el bootloader:
proxmox-boot-tool status. - Añade parámetros del kernel: Intel
intel_iommu=on iommu=pto AMDamd_iommu=on iommu=pt. - Aplica los cambios del bootloader: systemd-boot
proxmox-boot-tool refresh; GRUBupdate-grub. - Reinicia.
- Verifica:
/proc/cmdlinecontiene tus parámetrosdmesgmuestra DMAR/IOMMU enabled/sys/kernel/iommu_groupsestá poblado
Paso a paso: preparar un dispositivo para passthrough
- Identifica el dispositivo:
lspci -nny captura vendor:device IDs. - Comprueba el grupo: enumera IOMMU groups; asegúrate de que el dispositivo no esté pegado a dispositivos críticos del host.
- Carga módulos VFIO de forma persistente (
/etc/modules-load.d/vfio.conf). - Enlaza IDs a vfio-pci (
/etc/modprobe.d/vfio.conf). - Haz blacklist del driver del host solo si es necesario (evita blacklistear drivers de NIC/almacenamiento a menos que lo tengas claro).
- Reconstruye initramfs y reinicia.
- Verifica el binding:
lspci -nnkmuestraKernel driver in use: vfio-pci. - Solo entonces adjunta el dispositivo a la VM en Proxmox.
Lista de reversión (porque los adultos planifican reversión)
- Elimina los parámetros IOMMU del kernel de GRUB o
/etc/kernel/cmdline. - Elimina o comenta el binding de IDs en
/etc/modprobe.d/vfio.conf. - Elimina las blacklists que añadiste.
- Reconstruye initramfs.
- Refresca la configuración del bootloader (GRUB/systemd-boot).
- Reinicia y confirma que el driver original vuelva a poseer el dispositivo.
Preguntas frecuentes
1) ¿VT-x es lo mismo que VT-d?
No. VT-x es virtualización de CPU. VT-d es IOMMU para dispositivos. Puedes tener VT-x funcionando (KVM cargado) mientras VT-d está apagado y el passthrough falla.
2) En AMD, ¿qué debo habilitar en la BIOS?
Busca “IOMMU” o “AMD-Vi.” “SVM” es virtualización de CPU, no remapeo DMA de dispositivos. Normalmente quieres ambos habilitados para virtualización Proxmox + passthrough.
3) ¿Necesito iommu=pt?
Usualmente es un buen valor por defecto en hosts que hacen passthrough. Puede reducir la sobrecarga para dispositivos del host a la vez que mantiene aislamiento para VFIO. Si estás depurando, puedes quitarlo para simplificar, pero la mayoría de setups funcionan bien con él.
4) ¿Por qué Proxmox sigue diciendo “IOMMU no habilitado” después de poner parámetros del kernel?
Porque los parámetros del kernel pueden no estar aplicados (editaste la configuración del bootloader equivocada), o el firmware VT-d/AMD-Vi está apagado, o no reiniciaste. Verifica /proc/cmdline primero. Si no muestra los parámetros, nada más importa.
5) ¿Qué hago si los grupos IOMMU son terribles?
Primero prueba otro slot PCIe y una actualización de BIOS. Si eso falla, decide si aceptas el riesgo de ACS override. Si necesitas aislamiento fuerte, no “arregles” hardware malo con un hack de kernel—usa mejor hardware.
6) ¿Puedo pasar un dispositivo USB sin pasar todo el controlador?
Sí, mediante passthrough USB a nivel de QEMU. Pero para dispositivos inestables (dongles, gear VR, entrada de baja latencia), pasar todo el controlador USB suele ser más fiable.
7) ¿Necesito deshabilitar el driver GPU del host?
Sólo si el driver del host se enlaza a la GPU antes que VFIO. El enfoque más limpio es el binding de IDs VFIO en initramfs. El blacklist ayuda cuando el driver es agresivo, pero es una herramienta tosca.
8) ¿Habilitar IOMMU romperá algo?
Usualmente no. Ocasionalmente cambia la enumeración PCI o expone bugs de firmware. Por eso haces reinicios escalonados, verificas el nombrado de red y mantienes opciones de reversión.
9) ¿Puedo habilitar IOMMU sin reiniciar?
No. Esto es una característica que se inicializa en tiempo de arranque por hardware/firmware y kernel. Si alguien te dice lo contrario, te está vendiendo sensaciones.
10) ¿Cuál es la diferencia entre pasar por dirección PCI y por vendor:device ID?
El binding por dirección apunta a una ruta/slot específico; el binding por ID apunta a un modelo de dispositivo. El binding por ID es común y estable pero puede atrapar más dispositivos de los previstos si tienes duplicados. En producción, sé explícito y verifica con lspci -nnk tras el reinicio.
Conclusión: siguientes pasos que realmente avanzan
Si ves “IOMMU no habilitado”, no te vuelvas loco editando configuraciones de VM. Haz que el host demuestre que IOMMU está habilitado:
- Verifica el conmutador en firmware: VT-d/AMD-Vi está activado.
- Verifica que los parámetros del kernel se aplicaron vía
/proc/cmdline. - Verifica que el kernel inicializó IOMMU vía
dmesgy/sys/kernel/iommu_groups. - Verifica el aislamiento del dispositivo vía IOMMU groups antes de enlazar y pasar.
Luego haz VFIO de forma disciplinada: enlaza los IDs correctos, reconstruye initramfs, reinicia, confirma que vfio-pci posee el dispositivo y solo entonces adjúntalo a la VM.
Finalmente, decide como adulto sobre el agrupamiento: primero mueve slots y actualiza firmware; considera ACS override solo si aceptas el trade-off. El passthrough más seguro es el que tu hardware estuvo diseñado para soportar.