El error de reinicio de GPU explicado: por qué IOMMU no es suficiente (y qué funciona)

¿Te fue útil?

Apagas una VM. La GPU debería volver al host como un boomerang bien entrenado. En cambio vuelve… mal.
Próximo arranque de VM: pantalla negra. dmesg del host: “reset failed”. Tu cluster autoscaler se encoge de hombros y programa el trabajo en un cadáver.

Si te dijeron “activa IOMMU y estarás bien”, te vendieron una media verdad confortante. IOMMU aporta aislamiento.
No garantiza el reinicio, la re-inicialización, ni que el dispositivo vuelva del estado en el que quedó bajo carga.
Este es el ecosistema del error de reinicio de GPU: parte comportamiento del silicio, parte matiz del spec PCIe, parte realidad del driver y parte dolor para el operador.

Qué se entiende por “el error de reinicio de GPU”

“Error de reinicio de GPU” no es un único bug. Es el apellido para cualquier situación en la que una GPU no puede reiniciarse y reutilizarse
de forma fiable sin un reinicio del host (o ciclo físico de alimentación). Aparece con más frecuencia en estos escenarios:

  • VFIO GPU passthrough (KVM/QEMU/libvirt) donde una GPU se asigna a una VM, luego se desvincula y se vuelve a asignar.
  • Cargas de trabajo de GPU en contenedores donde el driver del host intenta recuperarse de un kernel colgado o DMA erróneo.
  • Nodos GPU multiinquilino con MIG/SR-IOV/vGPU donde la semántica de reinicio varía según modo y firmware.
  • Tormentas AER de PCIe, flaps de enlace o una GPU que entra en un estado de bajo consumo y no vuelve limpiamente.

El problema central es simple: una GPU no es una NIC PCIe cortés. Es un SoC complejo con múltiples motores internos
(gráficos, cómputo, copia, vídeo, display), su propio firmware y gestión de energía agresiva. Cuando “reinicias un dispositivo PCIe,”
no estás necesariamente reiniciando todo ese estado interno —o lo haces en el momento equivocado— dejando al dispositivo
medio vivo que confunde al driver en la siguiente vinculación.

Broma #1: Las GPU no “se bloquean”, entran en un estado contemplativo donde reconsideran su relación con tu driver.

Hechos interesantes y contexto histórico (breve, concreto)

  1. PCIe FLR (Function Level Reset) llegó para estandarizar reinicios por función, pero muchas implementaciones tempranas fueron parciales o peculiares.
  2. Las GPU de consumo se optimizaron para una sola instancia de OS por arranque, mucho antes de que la virtualización exigiera “desconectar/conectar para siempre”.
  3. La etiqueta “reset bug” de AMD ganó tracción en la comunidad VFIO porque algunos modelos necesitaban un reinicio del bus o ciclo de energía para recuperarse.
  4. La persistencia de cómputo de NVIDIA tenía sentido para throughput HPC, pero complica el comportamiento de “desmontar y volver a enlazar” cuando esperas reinicios limpios.
  5. IOMMU se diseñó principalmente para remapeo DMA y protección, no como gestor del ciclo de vida del dispositivo.
  6. Estados de energía PCIe como D3hot/D3cold pueden romper la re-inicialización cuando firmware/BIOS y OS discrepan sobre quién controla el wake-up.
  7. ACS (Access Control Services) se volvió relevante porque las plataformas de consumo suelen agrupar múltiples dispositivos, impidiendo passthrough seguro.
  8. AER (Advanced Error Reporting) puede ser salvador para el diagnóstico, pero también puede inundar logs cuando un dispositivo se comporta mal y degradar la estabilidad del nodo.

La conclusión incómoda: “reinicio” no es una sola cosa. Es una negociación entre firmware de plataforma, topología PCIe,
capacidad del dispositivo y comportamiento del driver. Y las GPU son los dispositivos que más negociación requieren en tu host.

Por qué el aislamiento IOMMU no implica recuperabilidad

IOMMU es una barandilla. Mapea las direcciones DMA del dispositivo en un dominio de traducción para que los dispositivos no puedan garabatear
sobre memoria física arbitraria. Eso importa para seguridad y estabilidad. También permite a VFIO asignar un dispositivo a un guest de forma segura.

Pero IOMMU no:

  • garantiza que el dispositivo pueda volver a un estado limpio al desacoplarse
  • fuerza al dispositivo a respetar FLR correctamente
  • reinicia el estado interno del firmware, microcontroladores o rieles de alimentación
  • arregla una topología PCIe rota donde la GPU comparte un dominio de reinicio con otros dispositivos
  • te protege de expectativas específicas del vendor sobre la secuencia de inicialización del driver

En términos de producción: IOMMU evita que una GPU desbocada haga DMA sobre tu host hasta el abismo. No evita que la GPU sea
un aparatito obstinado que se niega a reiniciarse sin que alguien corte la alimentación.

Los dos planos de aislamiento que no debes confundir

Los operadores los mezclan porque se ven juntos en diagramas:

  • Aislamiento DMA (IOMMU): “¿Puede este dispositivo acceder solo a lo que se le permite?”
  • Aislamiento del ciclo de vida (dominio de reinicio): “¿Puede este dispositivo reiniciarse e inicializarse de forma independiente?”

Muchas plataformas te dan lo primero y fallan silenciosamente en lo segundo. Ahí es donde vive “IOMMU no es suficiente”.

Dominios de reinicio: la dependencia oculta

Una GPU está detrás de un root port, quizá detrás de un switch, a veces detrás de un chip PLX, a veces compartiendo lanes con otros dispositivos.
Incluso si la GPU está en su propio grupo IOMMU, puede compartir una línea de reinicio o dominio de alimentación con algo más.
Cuando emites un bus reset podrías reiniciar vecinos. Cuando emites FLR la GPU podría ignorarlo.
Cuando no emites nada, el driver intenta “soft reset” de motores internos y a veces falla.

Si ejecutas cargas multiinquilino, deberías tratar “reinicio independiente” como un requisito de compra, no como una ocurrencia posterior.
Aquí es donde las decisiones de plataforma de hardware aburridas superan a flags ingeniosos del kernel.

Una cita (idea parafraseada)

Idea parafraseada: la esperanza no es una estrategia: diseña sistemas para que la falla sea esperada y la recuperación rutinaria. — Gene Kranz (líder de operaciones, programa Apollo)

Mecanismos de reinicio PCIe: FLR, bus reset, hot reset y por qué las GPU son especiales

Function Level Reset (FLR)

FLR es el concepto más limpio: reiniciar solo una función PCIe (como 0000:65:00.0) sin volar todo el bus.
El OS puede solicitarlo vía sysfs, y VFIO lo usa cuando está disponible.

Realidad: algunas GPUs implementan FLR de forma que reinicia el config space pero no el estado interno del firmware que realmente te importa.
O FLR funciona solo cuando el dispositivo está en un cierto estado de energía. O “funciona” y el dispositivo vuelve con motores bloqueados.

Bus reset / secondary bus reset

Esto reinicia un segmento de bus downstream. Más enérgico que FLR. También más daño colateral.
Si tu GPU está detrás de un puente o switch PCIe, un bus reset a veces puede obligarla a cumplir.

La pega es obvia: podrías reiniciar otros endpoints detrás del mismo puente. Si tienes suerte, no es nada importante.
Si no la tienes, acabas de reiniciar tu HBA de almacenamiento en medio de una tormenta de I/O. Buena suerte explicando ese gráfico a finanzas.

Hot reset

Hot reset se acerca a “simular desconectar/reconectar a nivel de enlace”. Puede funcionar cuando FLR no lo hace.
También puede fallar si la plataforma no puede volver a entrenar el enlace correctamente o si el firmware del dispositivo se queda atascado durante el link training.

Reinicio fundamental / ciclo de alimentación

La opción nuclear. Si la GPU no vuelve sin quitarle energía, no tienes un problema de reinicio por software.
Tienes un problema de ciclo de vida de plataforma. En un datacenter lo solucionas con:

  • nodos con control de alimentación de ranura PCIe mediante BMC (raro, pero oro)
  • particiones GPU que toleren reinicios de nodo
  • mantener cargas restartables y diseñar scheduling alrededor de la falla

Por qué las GPU son especiales (y molestas)

Las GPU tienen múltiples “subdispositivos” internos detrás de una sola función PCIe: motores de copia, controladores de memoria, motores de vídeo,
motores de display, procesadores de seguridad y un gran bloque de firmware que arranca todo. Un reinicio que no re-inicialice firmware y el estado del controlador de memoria es un reinicio solo de nombre.

Añade la gestión de energía: las GPU reducen agresivamente potencia cuando están inactivas. Si desvinculas una GPU mientras está entrando
en un estado profundo (o mientras runtime PM está activo), puedes obtener un dispositivo que se enumera pero no responde correctamente.

Modos de fallo que verás en producción

1) “Reset failed” tras apagar la VM; el siguiente attach se cuelga

Síntoma clásico de VFIO: la VM funciona bien. La apagas. Desvinculas la GPU. La vuelves a vincular a otra VM. Libvirt dice que funcionó.
El guest arranca con consola en negro. Los logs del host muestran un reset fallido, o el driver se niega a vincular.

2) GPU atrapada en D3cold (o alternando estados de energía)

El dispositivo aparece en lspci pero no se inicializa. A veces los logs del kernel mencionan “unable to change power state.”
Esto suele ser una interacción con runtime power management: el kernel intenta suspender el dispositivo, luego intentas reiniciarlo y obtienes un lío.

3) Spam AER, resets de enlace y nodos “congelados”

La GPU empieza a producir errores PCIe corregibles/no fatales. AER inunda dmesg. El tiempo CPU se va a manejar interrupciones.
Aunque las cargas continúen, el perfil de latencia del nodo deja de ser fiable.

4) El driver piensa que la GPU está ocupada para siempre

El driver del kernel intenta poner el dispositivo en quietud, pero los motores internos están atascados. Espera por fences que nunca se señalan.
Intentas descargar el módulo y se bloquea. Eso no es “un bug del driver” en sentido moral; es el driver haciendo lo único seguro:
negarse a fingir que el hardware está bien.

5) Sorpresas multi-función: función de audio, controlador USB-C, etc.

Muchas GPU exponen múltiples funciones (gráficos + audio HDMI + controlador USB para VirtualLink/USB-C).
Reiniciar una función sin las otras (o vincular de forma inconsistente) puede dejar el dispositivo en un estado inconsistente.

6) Fallos “funcionó por la mañana”

Bajo cargas ligeras todo se reinicia bien. Bajo cómputo sostenido más ciclos frecuentes de attach/detach, los reinicios se degradan.
Esto es común cuando el firmware entra en un estado menos probado tras tiempo de ejecución prolongado, o cuando la VRAM está muy usada y las rutas de teardown
no son perfectas.

Guía rápida de diagnóstico

Esta es la versión que ejecutas cuando suena el pager y no quieres convertirte en arqueólogo de PCIe.
El objetivo: identificar si tienes un problema de capacidad de reinicio, un problema de gestión de energía,
un problema de vinculación del driver, o un problema de topología/domino de reinicio.

Primero: confirma qué falló—reinicio, bind o enlace

  • Comprueba dmesg en busca de “reset failed”, “AER”, “link down”, “device not ready”.
  • Comprueba la disponibilidad del método de reinicio en sysfs para la función PCIe.
  • Comprueba si el dispositivo está en D3cold/D3hot.

Segundo: valida la topología y riesgos de dominio de reinicio

  • Encuentra el bridge/root port ascendente y mira qué más lo comparte.
  • Confirma la pertenencia al grupo IOMMU, pero no te quedes ahí.
  • Busca un switch/bridge PCIe que podría ser el verdadero objetivo del reinicio.

Tercero: elige la acción de recuperación menos destructiva

  1. Prueba reinicio por función (FLR) si está disponible.
  2. Prueba ciclo unbind/bind (si el driver soporta reinit limpio).
  3. Prueba hot reset o secondary bus reset si la GPU está aislada detrás de su propio bridge/switch.
  4. Si los errores persisten o empiezan tormentas AER: drena el nodo, reinicia el host.

Si no puedes recuperar sin reiniciar más que ocasionalmente, deja de tratarlo como “error de operador.”
Es una limitación arquitectónica. Construye el scheduling y el mantenimiento alrededor de ello.

Tareas prácticas: comandos, salidas, decisiones (12+)

Todos los ejemplos asumen un host Linux con root y una GPU en 0000:65:00.0.
Reemplaza direcciones y nombres de driver según corresponda.

Task 1: Identificar la GPU y funciones (¿te falta la función de audio/USB?)

cr0x@server:~$ lspci -nn | egrep -i 'vga|3d|nvidia|amd|audio|usb'
65:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2231] (rev a1)
65:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:1aef] (rev a1)

Qué significa: Tu “GPU” tiene al menos dos funciones. Los planes de passthrough/reinicio deben tener en cuenta ambas.
Decisión: Si haces passthrough de 65:00.0, considera también 65:00.1 para mantener consistencia, o enlázala explícitamente a un driver seguro.

Task 2: Comprobar que IOMMU está realmente activado (no des por hecho)

cr0x@server:~$ dmesg | egrep -i 'iommu|dmarmr|intel-iommu|amd-vi' | head
[    0.912345] DMAR: IOMMU enabled
[    0.912678] DMAR: Host address width 46

Qué significa: El kernel cree que IOMMU está activado.
Decisión: Si no ves esto, arregla parámetros de arranque/BIOS primero; la estabilidad de VFIO sin IOMMU es fantasía.

Task 3: Inspeccionar pertenencia a grupo IOMMU (necesario, no suficiente)

cr0x@server:~$ gpu=0000:65:00.0; group=$(readlink /sys/bus/pci/devices/$gpu/iommu_group); echo $group; ls -l $group/devices
../../kernel/iommu_groups/42
total 0
lrwxrwxrwx 1 root root 0 Feb  4 10:01 0000:65:00.0 -> ../../../../devices/pci0000:60/0000:60:01.0/0000:65:00.0
lrwxrwxrwx 1 root root 0 Feb  4 10:01 0000:65:00.1 -> ../../../../devices/pci0000:60/0000:60:01.0/0000:65:00.1

Qué significa: Las funciones de GPU comparten el mismo grupo IOMMU, lo cual es normal.
Decisión: Si hay dispositivos no relacionados en el grupo, no puedes hacer passthrough de forma segura sin cambios de plataforma (o aceptando riesgo).

Task 4: Encontrar el bridge/root port ascendente (pista del dominio de reinicio)

cr0x@server:~$ gpu=0000:65:00.0; echo "GPU path:"; readlink -f /sys/bus/pci/devices/$gpu
GPU path:
/sys/devices/pci0000:60/0000:60:01.0/0000:65:00.0

Qué significa: El puerto ascendente es 0000:60:01.0.
Decisión: Comprueba qué más está detrás de 60:01.0. Si es un switch compartido, un bus reset puede tener daño colateral.

Task 5: Listar todo lo que está detrás del mismo puerto ascendente

cr0x@server:~$ upstream=0000:60:01.0; find /sys/bus/pci/devices/$upstream/ -maxdepth 2 -name '0000:*' -printf '%f\n'
0000:65:00.0
0000:65:00.1

Qué significa: Solo las funciones de la GPU viven detrás de este puerto.
Decisión: Un bus reset en el segmento downstream probablemente es seguro (aún valida que no haya un switch oculto con otros puertos).

Task 6: Comprobar si el kernel cree que FLR está disponible

cr0x@server:~$ gpu=0000:65:00.0; lspci -s ${gpu#0000:} -vv | egrep -i 'Capabilities:.*FLR|Reset'
Capabilities: [1b0] Vendor Specific Information: Len=14

Qué significa: Esta salida no prueba soporte FLR; algunos dispositivos no lo anuncian claramente en un grep amistoso.
Decisión: Usa sysfs a continuación; no confíes en listados de capacidades de marketing.

Task 7: Intentar reset por sysfs (lo menos destructivo)

cr0x@server:~$ gpu=0000:65:00.0; sudo sh -c "echo 1 > /sys/bus/pci/devices/$gpu/reset"
sh: 1: cannot create /sys/bus/pci/devices/0000:65:00.0/reset: Permission denied

Qué significa: Olvidaste root (o la redirección de shell no tenía privilegios).
Decisión: Usa un shell root o sudo tee para escribir en sysfs.

cr0x@server:~$ gpu=0000:65:00.0; echo 1 | sudo tee /sys/bus/pci/devices/$gpu/reset
1

Qué significa: El kernel aceptó la petición de reinicio.
Decisión: Comprueba inmediatamente dmesg para ver éxito/fallo; la aceptación no implica finalización.

Task 8: Confirmar resultado del reset en dmesg (éxito vs “reset failed”)

cr0x@server:~$ dmesg -T | tail -n 20
[Sun Feb  4 10:05:01 2026] pci 0000:65:00.0: resetting
[Sun Feb  4 10:05:02 2026] pci 0000:65:00.0: reset failed

Qué significa: La plataforma/dispositivo no pudo completar la ruta de reinicio solicitada.
Decisión: Escala a hot reset / bus reset solo si la GPU está aislada detrás de su propio bridge; de lo contrario drena y reinicia el nodo.

Task 9: Comprobar estado de energía (D0 vs D3) para detectar trampas de runtime PM

cr0x@server:~$ gpu=0000:65:00.0; cat /sys/bus/pci/devices/$gpu/power_state
D3cold

Qué significa: El dispositivo está en apagado profundo.
Decisión: Considera desactivar runtime PM para el dispositivo, o asegúrate de que esté en D0 antes de detach/reset.

Task 10: Desactivar runtime power management para la GPU (cambio de prueba)

cr0x@server:~$ gpu=0000:65:00.0; echo on | sudo tee /sys/bus/pci/devices/$gpu/power/control
on

Qué significa: Runtime PM se fuerza a “on” (sin autosuspend) para esa función.
Decisión: Reprueba ciclos de detach/attach. Si mejora la estabilidad, hazlo persistente vía udev o systemd (con cuidado).

Task 11: Desvincular del driver actual (preparar para re-vincular o VFIO)

cr0x@server:~$ gpu=0000:65:00.0; readlink /sys/bus/pci/devices/$gpu/driver
../../../../bus/pci/drivers/nvidia
cr0x@server:~$ gpu=0000:65:00.0; echo $gpu | sudo tee /sys/bus/pci/drivers/nvidia/unbind
0000:65:00.0

Qué significa: El dispositivo se ha desvinculado del driver nvidia.
Decisión: Si unbind se bloquea o falla, el driver puede estar esperando hardware; drenar y reiniciar suele ser la única escapatoria limpia.

Task 12: Vincular a vfio-pci (para passthrough) y verificar vinculación

cr0x@server:~$ gpu=0000:65:00.0; sudo modprobe vfio-pci
cr0x@server:~$ gpu=0000:65:00.0; vendor=$(cat /sys/bus/pci/devices/$gpu/vendor); device=$(cat /sys/bus/pci/devices/$gpu/device); echo $vendor $device
0x10de 0x2231
cr0x@server:~$ echo 10de 2231 | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
10de 2231
cr0x@server:~$ gpu=0000:65:00.0; readlink /sys/bus/pci/devices/$gpu/driver
../../../../bus/pci/drivers/vfio-pci

Qué significa: vfio-pci ahora posee el dispositivo.
Decisión: Si la vinculación falla o revierte, tienes drivers compitiendo (initramfs, reglas udev o Xorg reclamando la GPU).

Task 13: Buscar errores AER que predigan futuros fallos de reinicio

cr0x@server:~$ dmesg -T | egrep -i 'AER|pcieport|error' | tail -n 15
[Sun Feb  4 10:06:10 2026] pcieport 0000:60:01.0: AER: Corrected error received: 0000:60:01.0
[Sun Feb  4 10:06:10 2026] pcieport 0000:60:01.0: AER: PCIe Bus Error: severity=Corrected, type=Physical Layer

Qué significa: Existen problemas a nivel de enlace aunque la GPU “funcione”.
Decisión: Trata AER persistente como un problema de hardware/plataforma: comprueba asiento, risers, cableado (para PCIe externo), ajustes BIOS o reemplaza el nodo.

Task 14: Verificar velocidad/anchura del enlace (enlaces degradados correlacionan con resets extraños)

cr0x@server:~$ gpu=0000:65:00.0; sudo lspci -s ${gpu#0000:} -vv | egrep -i 'LnkSta:|LnkCap:'
LnkCap: Port #0, Speed 16GT/s, Width x16
LnkSta: Speed 8GT/s (downgraded), Width x8 (downgraded)

Qué significa: Tu GPU está funcionando en un enlace degradado.
Decisión: Arregla primero problemas físicos/topológicos. Depurar resets en un enlace degradado es como depurar almacenamiento en un cable SATA moribundo: no aprenderás nada útil.

Task 15: Intentar un downstream bus reset solo si la topología es segura

cr0x@server:~$ upstream=0000:60:01.0; echo 1 | sudo tee /sys/bus/pci/devices/$upstream/reset
1

Qué significa: Solicitaste un reinicio en el puerto/bridge ascendente, que puede reiniciar el segmento downstream.
Decisión: Si otros dispositivos comparten ese segmento, no lo hagas en un nodo en producción. Si la GPU está aislada, esto puede restaurar un dispositivo “atascado”.

Task 16: Validar que el dispositivo responde tras el reset (señal rápida de salud)

cr0x@server:~$ gpu=0000:65:00.0; lspci -s ${gpu#0000:} -nn
65:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2231] (rev a1)

Qué significa: El dispositivo aún se enumera, que es el mínimo indispensable.
Decisión: Si desaparece por completo, estás en territorio de entrenamiento de enlace/dominios de energía; planea el reinicio del host e investiga firmware de plataforma.

Qué funciona: estrategias de mitigación que resisten cargas reales

1) Prefiere GPUs y plataformas con comportamiento de reinicio probado

Esto no es filosófico. Es operativo. Si necesitas reasignaciones frecuentes (VFIO multiinquilino, granjas CI, VMs GPU efímeras),
tu hardware debe soportar FLR fiable o bus reset predecible sin daño colateral.

Las GPUs y servidores de clase datacenter suelen comportarse mejor porque fueron diseñados para operaciones de flota y recuperación remota.
Las plataformas de consumo pueden funcionar, pero te apuntas a un hobby que implica parámetros del kernel, workarounds ACPI y reinicios ocasionales.

2) Mantén la GPU ligada a un mundo el mayor tiempo posible

Cada detach/attach es una oportunidad para caer en el mal camino. Si puedes programar “la GPU permanece con una VM durante su vida”, hazlo.
Si puedes fijar la GPU a un nodo y mover trabajos en vez de mover GPUs, hazlo. Si puedes evitar VFIO y usar contenedores en el host,
hazlo (si confías en el modelo multiinquilino y tienes controles de aislamiento).

3) Desactiva runtime PM para GPUs en passthrough (selectivamente)

Runtime PM ahorra vatios. También introduce estados que complican reinicio/rebind. Para GPUs en passthrough, la fiabilidad vence a la elegancia.
Fuerza D0 durante transiciones del ciclo de vida, o desactiva runtime PM para el dispositivo por completo.

4) Trata “reset failed” como un fallo de salud del nodo, no como un fallo aislado

Si una GPU no puede reiniciarse una vez, es más probable que falle de nuevo en condiciones similares. Marca el nodo como no saludable, drena cargas
y reinicia en tu ventana de mantenimiento, no en plena producción.

5) Usa una escalera de reinicio controlada

No saltes directamente a bus resets. Usa intentos escalonados:

  1. Asegura que ningún proceso esté usando la GPU (o detén la VM limpiamente).
  2. Desvincula el driver (host) o desadjunta el dispositivo (VFIO).
  3. Intenta FLR vía sysfs.
  4. Intenta hot/bus reset solo si confirmaste aislamiento.
  5. Si sigue roto: reinicia el nodo; si se repite: cambia firmware/plataforma.

6) Alinea firmware/ajustes BIOS con tus expectativas de reinicio

BIOS/UEFI puede sabotearte con gestión de energía y características PCIe. Mejoras comunes (dependen de la plataforma):

  • Desactiva estados PCIe profundos para la ranura si ves problemas D3cold.
  • Mantén Above 4G Decoding activado para BARs grandes y GPUs modernas.
  • Actualiza GPU VBIOS y BIOS del sistema juntos; generaciones mezcladas crean comportamiento “funciona hasta que no funciona”.

7) Para clusters: construye tolerancia a reinicios y aprovéchala

Si tu flota es suficientemente grande, la respuesta económicamente correcta suele ser: aceptar que algunos reinicios de GPU requieren reinicios,
y hacer del reinicio de nodo una remediación normal con reprogramación rápida de trabajos.

Broma #2: El reinicio de GPU más fiable es el que realiza una fuente de alimentación que “olvida” por un instante que estaba suministrando energía.

Tres microhistorias del mundo corporativo

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

Una empresa SaaS mediana montó un servicio de inferencia con GPUs. Querían fuerte aislamiento por tenant, así que usaron VFIO passthrough:
una VM por carga de cliente, GPUs reasignadas conforme las VMs rotaban. El equipo de plataforma activó IOMMU, validó grupos IOMMU y escribió
automatización que desvinculaba y volvía a vincular dispositivos entre VMs.

Pasó staging. Pasó tests de carga. El despliegue empezó silenciosamente y se vio bien durante unos días, exactamente como los bugs de plataforma ganan confianza antes de cobrarla.

El primer incidente empezó como “algunos jobs atascados”. Luego fue “la mitad de las GPUs no programan”. Las VMs estaban saludables.
Libvirt reportaba detach/attach exitosos. Pero los dispositivos GPU no se inicializaban en la siguiente VM tras un detach.
Los operadores encontraron “reset failed” en dmesg y vieron operaciones de unbind colgar. Algunos nodos comenzaron a registrar errores PCIe corregidos
que lentamente se convirtieron en tormentas.

La suposición equivocada fue simple: “Los grupos IOMMU implican reutilización segura.” El aislamiento era correcto. La recuperabilidad no.
Los modelos de GPU en esa flota podían pasarse bien, pero su comportamiento de reinicio era poco fiable bajo churn repetido.
No estaban rotos para uso de escritorio; simplemente no estaban diseñados para ese ciclo de vida.

La solución fue operativa y arquitectónica: dejaron de reutilizar GPUs entre la vida de VMs. Una GPU quedó fijada a una VM hasta
que la VM se destruía, y los nodos se reiniciaban durante una ventana de mantenimiento controlada antes de volver al pool.
La planificación de capacidad se volvió un poco más honesta. Los incidentes cayeron bruscamente.

Microhistoria 2: La optimización que salió mal

Una firma de análisis financiero ejecutaba cargas intensivas de cómputo durante la noche. Querían reducir costes energéticos y activaron
runtime power management agresivo. La idea tenía sentido: las GPUs están inactivas entre ráfagas, autosuspenderlas ahorra vatios.

Dos semanas después, tuvieron una nueva clase de fallo: nodos que parecían saludables pero se negaban a iniciar jobs GPU tras estar inactivos.
El scheduler asignaba un job, el job fallaba al abrir el dispositivo, los reintentos rebotaban entre nodos y eventualmente
el cluster parecía “ocupado” mientras hacía casi nada. Una ilusión clásica de utilización.

La causa raíz fueron GPUs entrando en estados de energía profundos que interactuaban mal con la re-inicialización del driver tras largos inactivos.
La ruta de reinicio a veces funcionaba, a veces no. La tasa de fallo era baja, pero el radio de explosión operativo era alto porque
desencadenaba manadas de reintentos.

Desactivaron runtime PM para las funciones GPU usadas por cómputo. Los costes energéticos aumentaron ligeramente. El throughput subió más.
Lo más importante: el cluster dejó de mentir sobre su disponibilidad.

La lección: optimizar por energía sin un plan de recuperabilidad es como optimizar rendimiento de almacenamiento apagando checksums.
Obtendrás números. No te gustará la factura cuando llegue la realidad.

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

Una organización de investigación operaba un cluster GPU multiinquilino con mezcla de generaciones de hardware. Habían aprendido que
“problemas de reinicio GPU” no están distribuidos uniformemente; siempre hay algunos nodos peores.

Su práctica aburrida: los nodos se etiquetaban con una clase de “fiabilidad de reinicio GPU” basada en comportamiento observado. Los jobs que requerían
reinicios frecuentes o provisiones efímeras se programaban solo en nodos de alta fiabilidad. Los jobs de larga duración podían ejecutarse en cualquier lugar,
pero con checkpointing y plan de preempción.

También tenían un flujo de remediación estricto: un nodo que registraba un fallo de reinicio se drenaba inmediatamente, se reiniciaba y solo
volvía al servicio tras pasar un bucle estandarizado de pruebas de attach/detach. Nada de depuración heroica en horario laboral.

Cuando una nueva versión del driver introdujo más casos límite de reinicio en una familia de GPU, el impacto quedó contenido.
El scheduler evitó los nodos de riesgo, el bucle drenar-reiniciar evitó largas tormentas AER y los usuarios vieron principalmente jobs reiniciarse
en vez de colgar. No fue glamoroso. Fue correcto.

Errores comunes (síntomas → causa raíz → arreglo)

1) Síntoma: “reset failed” tras detach; la GPU no vuelve a adjuntarse

Causa raíz: El dispositivo no soporta FLR fiable; la ruta de reset del driver está incompleta; GPU atascada en estado interno de firmware.
Arreglo: Evita detach/attach frecuentes; fija la GPU a la vida de la VM; usa bus reset solo con puerto downstream aislado; de lo contrario reinicia el nodo.

2) Síntoma: GPU presente en lspci pero bind del driver falla con timeouts

Causa raíz: GPU en D3cold o la plataforma no la despierta; conflicto con runtime PM.
Arreglo: Fuerza /sys/bus/pci/devices/…/power/control a on; ajusta ajustes BIOS PCIe; asegúrate de que el dispositivo esté en D0 antes de rebind.

3) Síntoma: aumentan errores AER corregidos; fallos ocasionales de jobs

Causa raíz: Integridad de señal/problemas de enlace, riser defectuoso, enlace degradado, ranura marginal.
Arreglo: Reseat de GPU, intercambiar riser/cable, comprobar ancho/velocidad del enlace, actualizar firmware; poner el nodo en cuarentena si persiste.

4) Síntoma: descargar driver de GPU cuelga para siempre

Causa raíz: El driver espera a que los motores de hardware queden inactivos; microcontrolador GPU bloqueado.
Arreglo: No luches contra ello. Drena y reinicia. Luego investiga por qué se bloquea (térmico, firmware, carga, overclock, alimentación).

5) Síntoma: VFIO funciona solo una vez por arranque

Causa raíz: El reinicio funciona en cold boot pero no después de que un guest usa la GPU; falta quirk de vendor o requiere bus reset/ciclo de energía.
Arreglo: Valida capacidad de reinicio antes de desplegar; planifica reinicio del host entre asignaciones; prefiere hardware con reinicio comprobado.

6) Síntoma: apagar VM produce inestabilidad del host o reinicia otros dispositivos

Causa raíz: Usaste un bus reset en un bridge compartido con otros endpoints (almacenamiento, NIC).
Arreglo: Mapea la topología; aísla GPUs detrás de root ports dedicados; no hagas bus reset en segmentos compartidos en producción.

7) Síntoma: “Funcionó en staging” pero falla bajo churn

Causa raíz: Los ciclos de prueba no cubrieron tiempo de ejecución largo, uso intensivo de VRAM o detach/attach repetido; los estados de firmware dependen de la carga.
Arreglo: Añade soak tests con bucles detach/attach; clasifica nodos por fiabilidad de reinicio observada; automatiza la remediación.

Listas de comprobación / plan paso a paso

Checklist A: Antes de desplegar VFIO GPU passthrough a escala

  1. Verificar IOMMU activado en BIOS y kernel; confirmar mensajes DMAR/AMD-Vi.
  2. Confirmar funciones GPU y asegurarse de contabilizarlas todas (gráficos/audio/USB).
  3. Mapear grupos IOMMU y topología; identificar puertos ascendentes y segmentos compartidos.
  4. Ejecutar un soak test de detach/attach (docenas a cientos de ciclos) bajo carga real (presión VRAM + cómputo).
  5. Decidir tu contrato de recuperación: “recuperar sin reinicio” o “reinicio aceptable.” Inclúyelo en el runbook.
  6. Implementar cuarentena de nodos: si falla un reinicio una vez, remover el nodo del scheduling hasta remediación.

Checklist B: Escalera de recuperación segura durante un incidente

  1. Parar o migrar la carga; asegurar que ningún proceso use la GPU.
  2. Capturar evidencia: tail de dmesg, lspci -vv estado de enlace, estado de energía, vinculación del driver actual.
  3. Intentar FLR vía sysfs reset en la función.
  4. Si sigue roto, y solo si la topología es segura: resetear el puerto/bridge ascendente.
  5. Si hay tormentas AER o fallos repetidos: drenar nodo, reiniciar, marcar nodo para investigación profunda.

Checklist C: Hacerlo aburrido (el tipo más fiable)

  1. Etiquetar nodos por familia/firmware de GPU y comportamiento de reinicio observado.
  2. Programar cargas con mucho churn solo en nodos con “buen reinicio”.
  3. Desactivar runtime PM para GPUs en passthrough a menos que tengas pruebas de que es seguro.
  4. Mantener versiones de kernel/driver/firmware controladas; desplegar cambios con canarios y planes de rollback.
  5. Automatizar bucles de reinicio + pruebas de salud; trata los reinicios como herramienta de mantenimiento, no como falta de carácter.

Preguntas frecuentes

Q1: Si la GPU está en su propio grupo IOMMU, ¿por qué no siempre puede reiniciarse?

El agrupamiento IOMMU trata límites de aislamiento DMA. La capacidad de reinicio depende del soporte de reinicio PCIe, dominios de energía, estado de firmware
y topología. Están relacionados pero no son equivalentes.

Q2: ¿Esto es solo un problema de AMD?

No. Diferentes vendors muestran patrones distintos, pero las fallas de reinicio existen en familias de GPU de todos. La comunidad VFIO históricamente
destacó casos “reset bug” de AMD, pero NVIDIA y otros también pueden wedgarse según modelo, firmware y ruta de driver.

Q3: ¿SR-IOV o MIG elimina los problemas de reinicio?

Cambia el problema. Las funciones de particionado pueden reducir el churn de dispositivo completo, lo que ayuda. Pero aún tienes la semántica de reinicio
a nivel de función física, y bugs de firmware/driver pueden emerger bajo condiciones multiinquilino intensas.

Q4: ¿Puedo arreglar esto puramente en software con parámetros del kernel?

A veces puedes mejorar el comportamiento (especialmente alrededor de gestión de energía o vinculación de drivers), pero no puedes solucionar por software
un dispositivo que requiere un reinicio fundamental. Trata la selección de hardware y la topología como primera clase.

Q5: ¿Cuál es el reinicio más seguro para intentar primero?

El reinicio por función (FLR) vía sysfs suele ser lo menos disruptivo. Si falla, los siguientes pasos dependen de la topología. Los bus resets pueden funcionar
pero conllevan riesgo colateral.

Q6: ¿Por qué la GPU a veces funciona tras un reinicio del host pero no tras detach/attach de VM?

El arranque en frío establece una línea base limpia: el firmware se inicializa desde cero, los rieles de energía ciclan, el enlace se entrena limpio.
Un ciclo detach/attach a menudo depende de reinicios parciales y rutas de teardown del driver, que pueden no re-inicializar completamente el estado interno de la GPU.

Q7: ¿Debo desactivar AER para evitar spam en los logs?

Por lo general no. AER es un reportero de síntomas. Desactivarlo oculta la evidencia mientras el enlace sigue comportándose mal.
Si las tormentas AER causan problemas operativos, pon el nodo en cuarentena y arregla el enlace/energía/plataforma subyacente.

Q8: ¿Es aceptable planificar reinicios como método de recuperación?

Sí, si lo diseñas así. En clusters, “reiniciar para recuperar una GPU atascada” puede ser perfectamente razonable si los jobs son restartables,
los nodos se drenan de forma segura y la ruta de reinicio es rápida y automatizada.

Q9: ¿Por qué desvincular el driver a veces se queda colgado?

Porque el driver intenta un teardown seguro: espera que DMA pare y que los motores queden en quietud. Si la GPU está wedgada, el driver
no puede fingir responsablemente que está libre. Ese colgado a menudo te protege de corrupción de memoria.

Q10: ¿Cuál es la métrica única mejor para alertar?

Alerta sobre fallos de reinicio y eventos AER recurrentes en los root ports GPU. Eso correlaciona fuertemente con “este nodo te hará perder tiempo después.”
Luego automatiza cuarentena y remediación.

Conclusión: próximos pasos prácticos

Si recuerdas una cosa: IOMMU te da seguridad DMA, no seguridad de reinicio. La clase de errores “GPU reset” ocurre cuando confundimos eso
y construimos automatización que asume que los dispositivos se comportan como periféricos sin estado.

Pasos siguientes que rinden inmediatamente:

  1. Inventario de topología: mapea puertos ascendentes, bridges compartidos y grupos IOMMU para cada nodo GPU.
  2. Implementar una escalera de reinicio: FLR → bus reset cuidadoso (solo si está aislado) → drenar y reiniciar.
  3. Desactivar runtime PM para GPUs en passthrough si ves rarezas D3cold/D3hot.
  4. Adoptar cuarentena de nodos: un fallo de reinicio debe sacar un nodo de programación hasta reinicio + test de salud.
  5. Cambiar criterios de compra: exigir comportamiento de reinicio probado, control de alimentación de ranura si es posible y plataformas diseñadas para virtualización.

Así es como conviertes el “error de reinicio de GPU” de un incidente recurrente en una limitación conocida con una respuesta aburrida y fiable.
Lo aburrido es bueno. Lo aburrido te devuelve los fines de semana.

← Anterior
GPT vs MBR: Si eliges mal romperás el arranque — Elige bien con esta regla
Siguiente →
OpenVPN: Por qué parece lento (y los ajustes que lo hacen volar)

Deja un comentario