technology 8 min de lectura

El discreto arreglo de Linux 7.3 para firmware que se lleva por delante sistemas enteros

Linux 7.3 ahora cancela tras 120 segundos las llamadas a firmware EFI colgadas en lugar de esperar indefinidamente. El cambio, surgido de un crash en un servidor NVIDIA Grace, evita que una rutina de firmware defectuosa se lleve por delante todo el espacio de usuario y proporciona una señal inequívoca a los ingenieros cuando el problema es el firmware, no el código.

  • Linux 7.3
  • firmware EFI
  • timeout del kernel
  • Breno Leitao
  • EFI Runtime Services

Una única llamada a firmware atascada solía dejarlo todo fuera de línea

Un nuevo mecanismo de protección en Linux 7.3 evita una clase de errores que podía dejar las cargas de trabajo empresariales paralizadas en silencio: una sola llamada a un servicio de tiempo de ejecución EFI que se queda colgada ya no necesita esperarse para siempre.

Antes de este cambio, el núcleo permanecía dentro de una llamada al firmware sin regresar nunca. El llamador mantenía el efi_runtime_lock durante toda la ejecución. Cada proceso posterior que necesitaba comunicarse con EFI — escrituras en NVRAM, almacenamiento de variables a través de efivarfs, manejadores ACPI PRM, incluso la tarea sencilla de configurar el tiempo de reanudación — quedaba bloqueado tras ese mismo lock. Los procesos en espacio de usuario se acumulaban de forma no interrumpible en el semáforo. El único síntoma visible externamente era un mensaje de bloqueo del workqueue, repetido a los 127 segundos, 157 segundos, 188 segundos y más allá, hasta que algún sistema de monitoreo externo finalmente reiniciaba el servidor.

El firmware nunca iba a responder. Pero el núcleo no tenía forma de saberlo.

El efi_runtime_lock no es una preocupación marginal. Serializa cada llamada de tiempo de ejecución EFI en todo el sistema. Cuando una llamada se atasca dentro del firmware, el lock nunca se libera, y todo lo que depende de EFI — el TPM, la NVRAM, la vía de gestión de energía, la infraestructura de variables de arranque — se acumula detrás de él. Los contenedores, los scripts initramfs, logrotate, los timers de systemd y cualquier herramienta de espacio de usuario que lea o escriba variables EFI queda bloqueado. El sistema parece sano a la mayoría de los agentes de monitoreo porque la CPU no está consumiendo ciclos; simplemente está trabada. Un tablero muestra luces verdes mientras la máquina ya está muerta.

El error se detectó en un servidor NVIDIA Grace

Breno Leitao, desarrollador de Debian e ingeniero de kernel en Meta, encontró el problema ejecutando hardware NVIDIA Grace. Envió parches para imponer un tiempo de espera en la finalización de servicios de tiempo de ejecución EFI, y los cambios se integraron en la fusión de características EFI para Linux 7.3.

En la carta descriptiva de la serie de parches, Leitao explicó exactamente qué estaba sucediendo. El registro PC y el registro de enlace permanecían atrapados dentro de la memoria del firmware EFI — el firmware simplemente nunca regresaba. El worker permanecía atascado a través de múltiples reportes de bloqueo de workqueue hasta que un sistema externo forzaba un reinicio. El propio núcleo no podía recuperarse.

Este no es un caso borde poco común. Los servicios de tiempo de ejecución EFI se invocan constantemente durante la operación normal. Cualquier fabricante con firmware descuidado — y hay muchos — puede desencadenar una condición en la que una llamada se trabe. Antes de esta corrección, la única opción era reiniciar y esperar que la próxima llamada tuviera éxito por casualidad. En un entorno de flota, esto significaba decenas de servidores potencialmente trabados en el mismo estado sin ninguna señal diagnóstica clara.

La plataforma NVIDIA Grace complica aún más el problema porque ejecuta una arquitectura no x86 utilizando superchips basados en ARM. La madurez del firmware en silicio de servidor más nuevo sigue siendo desigual, y la arquitectura Grace introduce su propia vía de inicialización a través de llamadas de tiempo de ejecución EFI que difieren de los despliegues x86 tradicionales. Un error que podría aparecer como una nota al pie en hardware x86 genérico se convierte en una falla que impacta toda una flota en una plataforma donde el uptime se mide en impacto de ingresos y no en molestias.

El umbral de tiempo de espera es de 120 segundos. Eso es intencional.

El límite de tiempo de espera está fijado en 120 segundos. Leitao lo describió como mayor que cualquier llamada legítima plausible a los servicios de tiempo de ejecución EFI. Ninguna rutina de firmware normal debería tardar dos minutos en completarse. Si lo hace, algo está mal, y el núcleo debería dejar de fingir lo contrario.

Cuando se dispara el tiempo de espera, el firmware se declara trabado. El núcleo sale de la llamada atascada, libera el efi_runtime_lock y devuelve un error a quien realizara la solicitud original. Las operaciones EFI subsiguientes ya no quedan bloqueadas detrás del worker colgado original. El espacio de usuario se reanuda. El sistema permanece activo.

La implementación funciona envolviendo la llamada EFI en una espera con temporizador. El núcleo inicia un timer antes de invocar la rutina del firmware. Si la rutina no ha terminado cuando el temporizador expira, el núcleo la trata como atascada y la aborta. El mecanismo exacto no desvincula forzosamente el firmware — el firmware sigue ejecutándose, posiblemente en un estado incorrecto — pero el núcleo corta su propia dependencia del resultado y continúa. Esta es una estrategia de contención, no una reparación.

Esa distinción importa. El tiempo de espera no evita que el error del firmware vuelva a ocurrir. Una llamada EFI posterior por la misma vía de código también podría trabarse. Lo que el tiempo de espera sí previene es que una sola llamada atascada se propague y congele el sistema completo. Convierte un bloqueo total en un error recuperable con una ventana de tiempo definida.

La verdadera ventaja es la claridad diagnóstica

El resultado más importante puede no ser la recuperación en sí, sino la señal que proporciona a los ingenieros. Antes de este cambio, un bloqueo del workqueue podía significar cualquier cosa. Una fuga de memoria. Un deadlock en el código del núcleo. Una inanición del planificador. Un fallo de hardware. A escala de flota, el mismo síntoma podía atribuirse a decenas de causas raíz no relacionadas.

Ahora, cuando un sistema alcanza este tiempo de espera, dmesg produce un mensaje inequívoco de falla del firmware EFI. Los operadores saben exactamente dónde buscar. Los fabricantes obtienen reportes de error más claros. Y el ingeniero de guardia a las 3 a. m. no necesita pasar una hora descartando la mitad de los subsistemas del núcleo antes de decidir reiniciar.

Este tipo de precisión diagnóstica importa sobre todo a escala. Un servidor que se traba es una molestia. Cien servidores trabados silenciosamente por el mismo error de firmware en un centro de datos es un incidente. Con el tiempo de espera implementado, el evento detonante se registra con suficiente especificidad para que el análisis posterior comience de inmediato en lugar de después de un día cavando entre pilas de llamadas del núcleo. El propio mensaje de error se convierte en evidencia.

El efecto secundario se extiende a las herramientas de observabilidad. Los exporters de Prometheus, las comprobaciones de Datadog y los pipelines de alerta interna que ya monitorean bloqueos de workqueue ahora pueden correlacionar el evento de tiempo de espera con el error de firmware EFI y clasificar automáticamente el incidente. Esa clasificación, a su vez, enruta el ticket al fabricante del firmware en lugar de consumir el tiempo del ingeniero de guardia.

Por qué esto importa más allá de los entusiastas de Linux

Los errores de firmware EFI no son un problema teórico. Son un riesgo operativo para cualquier organización que ejecute Linux en hardware heterogéneo. Los fabricantes de servidores publican actualizaciones de firmware a su propio ritmo. Algunas plataformas cargan implementaciones defectuosas que solo se manifiestan bajo condiciones específicas. El núcleo tradicionalmente ha absorbido estas fallas de forma elegante, lo cual suena a característica hasta que significa que tu carga de trabajo está muerta en silencio y no puedes saber por qué.

La participación de Meta en esto es notable. Leitao trabaja en la intersección entre el desarrollo del kernel upstream y la infraestructura de producción a escala. El servidor NVIDIA Grace que expuso el error no es un dispositivo de consumo: es hardware de grado de infraestructura donde el uptime importa y el tiempo de recuperación se mide en ingresos perdidos, no en molestias. El hecho de que el parche provenga de alguien que trabaja dentro del equipo de kernel de un proveedor de nube, en lugar de un fabricante de firmware, subraya un patrón más amplio: el núcleo está absorbiendo errores que nunca deberían haber llegado al firmware de producción en primer lugar, y los mecanismos de tiempo de espera son un parche pragmático.

El tiempo de espera de 120 segundos es conservador por diseño. Rara vez se activará en sistemas sanos. Pero cuando lo hace, convierte un estancamiento misterioso en un modo de falla conocido con un origen claro. Ese es el tipo de cambio que no hace titulares pero que mejora silenciosamente la confiabilidad de cada despliegue empresarial de Linux que ejecute 7.3 o posterior.

Los fabricantes de firmware tienen una larga historia de publicar servicios de tiempo de ejecución que asumen que el núcleo esperará indefinidamente. Este tiempo de espera obliga a una rendición de cuentas. Hace que el costo de una llamada a firmware trabada sea medible en lugar de invisible. Con el tiempo, esa visibilidad debería empujar a los fabricantes a corregir la causa raíz en lugar de depender de que el núcleo absorba la falla. Mientras tanto, el filtro de 120 segundos mantiene los sistemas funcionando lo suficiente para que los ingenieros puedan notar, diagnosticar y actuar — en lugar de descubrir un servidor muerto solo cuando el cliente se queja.

El firmware sigue estropeado. El núcleo simplemente es más inteligente fingiendo que no lo está.