← Volver al blog · Publicado · Read in English · Fuente: Artefacto interactivo «Evitar el Xid 109» (Claude)

Evitar el Xid 109 en NVIDIA bajo Linux sin recompilar el driver

Cuando un juego bajo Proton muere con «Xid 109 CTX SWITCH TIMEOUT» tras unos mapas o al precachear shaders: cómo reconocerlo, la línea de DXVK que lo evita, cómo comprobarlo y qué datos servirían a NVIDIA.

NVIDIALinuxProtonDXVKSteamOverwatch 2

Cuando un juego bajo Proton muere con NVRM: Xid 109 … CTX SWITCH TIMEOUT tras unos mapas o al precachear shaders, y el driver son los módulos abiertos de NVIDIA, esto es lo esencial: cómo reconocerlo, la línea que lo evita, cómo comprobarlo y qué datos servirían a NVIDIA. No hace falta compilar el driver, no se toca Secure Boot, y vale para Steam, Lutris, Heroic, Bottles y Wine a mano. Es una mitigación, no una reparación.

Resultado de una investigación independiente (agosto–septiembre de 2026) en un Lenovo LOQ 15ARP9 con RTX 3050 6 GB, módulos abiertos 615.71.09, Proton 11.0-100 (DXVK a6764047). Sin inspección de binarios propietarios; toda afirmación es trazable a fuente público o a registros del equipo. No afiliado a NVIDIA.

1. Reconocerlo: ¿es este fallo?

Sí, si se cumplen estas tres cosas. Comprobación en una terminal mientras el juego está abierto:

journalctl -kf | grep -E 'Xid|vaddr < \(baseVirtAddr'
  • Antes de morir aparece una ráfaga (decenas por segundo) de NVRM: nvAssertFailedNoLog: Assertion failed: vaddr < (baseVirtAddr + virtSize) @ dma.c:159 (dma.c:159)
  • Segundos después: NVRM: Xid (PCI:…): 109, pid=…, name=<juego>.exe, Ch 0000000x, … CTX SWITCH TIMEOUT. La GPU sigue funcionando; sólo el juego pierde el contexto.
  • Ocurre siempre en el mismo punto de carga: tras ~3 mapas, al precachear shaders, o cuando el contador de VRAM del juego llega a un valor fijo (en la RTX 3050 6 GB, ~4,8 GB). Da igual bajar texturas.

Qué es. El driver de usuario de NVIDIA (propietario) guarda el código de los shaders en una zona virtual fija de 1,5 GiB por proceso Vulkan; cuando se llena, sigue pidiendo mapear más allá del final, el módulo del kernel rechaza cada petición (esa es la aserción) y el motor gráfico se atasca hasta que el firmware GSP declara el Xid 109. Con los módulos abiertos no se puede desactivar la GSP (NVreg_EnableGpuFirmware=0 no aplica).

2. Evitarlo: la línea

dxvk.enableGraphicsPipelineLibrary = True

Con el valor por defecto (Auto) DXVK ya usa Graphics Pipeline Library, pero además compila en segundo plano una variante optimizada de cada pipeline; ese código extra es lo que llena la zona de 1,5 GiB. Con True no se compilan las variantes y la zona no se llena.

Steam (Proton)

Opción A — en las opciones de lanzamiento del juego (independiente del directorio de trabajo, la forma más fiable):

DXVK_CONFIG="dxvk.enableGraphicsPipelineLibrary=True" %command%

Si ya tienes otras opciones en DXVK_CONFIG, sepáralas con ;: DXVK_CONFIG="dxgi.maxFrameRate=141;dxvk.enableGraphicsPipelineLibrary=True".

Opción B — un fichero dxvk.conf en el directorio desde el que arranca el ejecutable (para Steam, el directorio de instalación del juego) con esa única línea.

Lutris, Heroic, Bottles, Wine a mano

  • Lutris: Configurar → Variables de entorno → DXVK_CONFIG = dxvk.enableGraphicsPipelineLibrary=True.
  • Heroic: Ajustes del juego → Variables de entorno → misma clave y valor.
  • Bottles: Preferencias del bottle → Variables de entorno → misma clave y valor.
  • Wine directo: DXVK_CONFIG="dxvk.enableGraphicsPipelineLibrary=True" wine juego.exe, o DXVK_CONFIG_FILE=/ruta/dxvk.conf.

Alcance

  • Vale para juegos D3D8/9/10/11 traducidos por DXVK (la mayoría bajo Proton). Para D3D12 (vkd3d-proton) y Vulkan nativo no existe esta opción; si ves la misma aserción con ellos, es el mismo fallo del driver pero sin este atajo.
  • Coste: los pipelines enlazados no llevan optimización entre etapas; algo menos de rendimiento por shader. En la sesión de prueba la GPU siguió al 100 % de uso y a su tope de potencia; el efecto en fps no se midió.
  • Deshacer: quitar la línea. No toca nada del sistema.

3. Comprobarlo

# 1) que DXVK leyó la opción (una vez; luego quítalo, escribe logs en el directorio del juego)
DXVK_LOG_LEVEL=info DXVK_CONFIG="dxvk.enableGraphicsPipelineLibrary=True" %command%
#    en <juego>_d3d11.log o _dxgi.log:  info:  Found config env: dxvk.enableGraphicsPipelineLibrary=True

# 2) que no hay ráfaga ni Xid durante la carga que antes fallaba
journalctl -kf | grep -E 'Xid|vaddr < \(baseVirtAddr'      # debe quedarse vacío

Referencia medida (RTX 3050 6 GB Laptop, módulos abiertos 615.71.09, Proton 11.0-100, Overwatch 2): antes, fallo a los 6–9 min de precacheo en 4 de 4 sesiones; con la línea, 52 min 49 s de rotación continua de mapas (≈15 mapas) sin una sola aserción ni Xid, con la VRAM al mismo nivel al que antes moría.

4. Lo que se probó y no cambia nada

IntentoResultado medido
Limitar la VRAM que ve el juego (dxgi.maxDeviceMemory)fallo idéntico a los 7 min
Bajar texturas / calidad para alejar la VRAM del topeel tope no es la VRAM: es la zona de 1,5 GiB de código de shader
Más swap, quitar OOM, perfil de energía, potencia, temperaturadescartados con datos: el fallo ocurre con 0 OOM, GPU a 90 W y 70 °C sin estrangulamiento
clearcpuid=umip (anticheat que ejecuta SIDT)quita una tormenta de emulación en la CPU, pero el Xid 109 sigue
Desactivar la GSP (NVreg_EnableGpuFirmware=0)imposible con módulos abiertos; exigiría el módulo propietario
Parchear el módulo del kernel abierto (MIT)puede diagnosticar, no reparar: el kernel acepta toda reserva que el driver pide, y cuando el kernel mapea por él y le devuelve la dirección, el driver de usuario la ignora (Xid 13 inmediato)

5. Si el juego muestra 0 °C de GPU (opcional)

Bajo Wine/Proton la telemetría del juego llega por NvAPI (dxvk-nvapi) → nvml.dll. Proton no trae nvml.dll; se compila wine-nvml y se copia al prefijo. Regla que evita el susto: cada cambio de versión de Proton puede recrear el prefijo y borrar la copia; no es el driver. Un envoltorio en las opciones de lanzamiento la repone sola:

#!/usr/bin/env bash   # ~/.local/bin/ow-pre — antes de %command% en las opciones de lanzamiento
SRC="$HOME/.local/share/wine-nvml/usr/lib64/wine/x86_64-windows/nvml.dll"
PFX="$STEAM_COMPAT_DATA_PATH/pfx/drive_c/windows/system32"
[[ -f $SRC && -d $PFX ]] && ! cmp -s "$SRC" "$PFX/nvml.dll" && cp "$SRC" "$PFX/nvml.dll"
exec "$@"
WINEDLLPATH=$HOME/.local/share/wine-nvml/usr/lib64/wine DXVK_CONFIG="dxvk.enableGraphicsPipelineLibrary=True" ~/.local/bin/ow-pre %command%

Verificar: PROTON_LOG=1 y grep -i thermal ~/steam-<appid>.log → NvAPI_GPU_GetThermalSettings: OK.

6. Para NVIDIA: qué datos sirven para corregirlo

El usuario no puede arreglar el driver propietario, pero sí darle a NVIDIA lo que hoy no ve en release (la aserción es anónima). Lo que esta investigación ya establece, con logs saneados y fuente citado:

  • Una única reserva NV50_MEMORY_VIRTUAL de 0x60000000 bytes por instancia Vulkan (flags 0x40ac10d, VIRTUAL|SPARSE|USE_BEGIN_END|…), nunca una segunda; el kernel no negó ninguna reserva.
  • Al llenarse, peticiones de mapeo en DmaOffset = size, size+0x10000… (asignador bump) desde el hilo de compilación de pipelines; el kernel las rechaza con NV_ERR_INVALID_OFFSET; Xid 109 entre 17 y 206 s después.
  • Si el kernel mapea en otra VA y la devuelve en dmaOffset, el driver usa base+offset igualmente → Xid 13 Shader Program Header Error: los objetos son programas de shader.
  • Con sólo bibliotecas GPL (sin variantes optimizadas) la zona no se llena en ≥ 53 min: el volumen que desborda es el de los pipelines optimizados.
  • Observación secundaria: mapeo sobre una VA ya mapeada (gpu_vaspace.c:4502, NV_ERR_INVALID_ARGUMENT), no fatal.

Corrección esperable en el driver de usuario: reservar otra zona al llenarse, o fallar la creación del pipeline con VK_ERROR_OUT_OF_DEVICE_MEMORY. Referencias: NVIDIA bug 5052028 (hilo 283722 del foro); issues #1140, #1187, #1282, #1364 de NVIDIA/open-gpu-kernel-modules.

Si quieres aportar tu propio caso

nvidia-smi --query-gpu=name,driver_version --format=csv,noheader; uname -r; grep EnableGpuFirmware /proc/driver/nvidia/params
journalctl -k -b -o short-iso-precise | grep -E 'Xid|dma.c:159' | sed 's/ [a-z0-9-]* kernel:/ host kernel:/' > xid109-journal.txt
nvidia-smi --query-gpu=timestamp,memory.used,power.draw,temperature.gpu,clocks.sm --format=csv -l 1 > xid109-smi.csv   # durante la carga

Con la versión de Proton/DXVK, el juego y cuánto tarda en fallar. Sin nombre de máquina ni UUID de GPU.


Fuente de esta entrada: artefacto interactivo «Evitar el Xid 109» · versión en inglés. Los parches de diagnóstico, la evidencia saneada y el informe completo se publican en el repositorio del proyecto.

← Volver al blog · Read in English · Fuente: Artefacto interactivo «Evitar el Xid 109» (Claude)