【愈发觉得自己成运维了】三张 4090 同时失效:GSP 固件崩溃的排查与在线恢复
环境背景:一台连续运行 25 天的 3×RTX 4090 计算服务器(Ubuntu 22.04,NVIDIA 驱动 595.71.05,CUDA 13.2)。执行
nvidia-smi时,三张 GPU 的风扇、温度、功耗读数全部显示 ERR!,GPU 不可用。本文完整记录故障的排查、定位、在线恢复与后续加固过程。
最重要的话说在前面:不要重启机器!不要重启机器!不要重启机器!
不然你会得到一张返厂维修单。。。
故障现象
三张 GPU 的 nvidia-smi 输出如下:
1 | +-----------------------------------------+------------------------+----------------------+ |
通过 nvidia-smi -q 查询详情,关键状态字段为:
1 | Product Brand : GPU requires reset |
即三张 GPU 均处于挂起状态,必须执行 reset 方可恢复。
根因分析:GSP 固件空指针崩溃
查阅内核日志(journalctl -k 与 /var/log/kern.log),定位到 18 小时前(09-20 22:42:49)的原始事件:
1 | NVRM: GPU1 kgspHealthCheck_TU102: ********* GSP-CrashCat Report ********* |
理解该故障需要先明确几个概念:
| 名词 | 说明 |
|---|---|
| GSP | RTX 4090(Ada 架构)板载的一颗 RISC-V 微控制器。新版 NVIDIA 驱动将资源管理器(显存分配、对象管理、显示配置等)从主机内核迁移至 GSP 固件中运行,称为 GSP-RM |
| Xid 120 | GSP 固件自身抛出异常。本次为 load access page fault,即读取内存时发生页错误 |
| Xid 154 | 驱动将 GPU 的恢复动作置为 Reset Required,即只能通过复位恢复 |
GSP-CrashCat 报告给出了崩溃现场,关键字段:
1 | sepc:0x000000000138f064 stval:0x00000000000001c0 scause:0xd |
scause=0xd(load access page fault)配合 stval=0x1c0,表明固件在执行读指令时访问了地址 0x1c0——这是一个极小的地址,对应空指针的 0x1c0 偏移解引用,属于典型的固件代码缺陷。
三张 GPU 在同一秒内崩溃的原因在于:三张卡的崩溃现场完全一致——相同的 PC(0x138f064)、相同的故障地址(0x1c0)、几乎相同的寄存器状态。硬件不可能以完全相同的方式同时损坏,因此可以判定为确定性的固件代码缺陷:同一客户端在约 100ms 内向三张 GPU 发送了相同的一组请求,每张卡的 GSP 固件均执行到了同一处缺陷代码。
触发路径:显示器信号事件与 Xorg
GSP 固件缺陷是根因,但仍需解释为何该代码路径在此刻被触发。结合崩溃瞬间正在处理的 RPC 序列与 Xorg 日志,可以还原完整链条:
- 该机器采用 3 头 X 显示配置(gdm 登录界面,一个 Xorg 进程同时驱动三张 4090,连接 Dell 显示器);
- 崩溃前最后处理的 RPC 序列为:两组
0x2080a0a8(NV2080 对象中 0xA0xx 段属于显示命令块)控制调用,随后是一条正在处理的 FREE(对象释放) 请求; - Xorg 日志中崩溃前最后一批正常输出为 EDID 读取与 Modeline 转储,属于显示器重探测行为(DP 链路信号重训、热插拔或显示器待机唤醒等事件);
- GSP 崩溃后,X 驱动的首个报错为
Failed to allocate display software resources。
完整因果链:显示器信号事件 → X server 重探测 EDID → 显示对象批量拆解与重建(FREE 请求)→ GSP 固件在对象释放路径上发生空指针解引用(Xid 120)→ GSP 作为 GPU 资源管理器失效,GPU 停止响应(Xid 154)→ 三张 GPU 于同一秒内全部进入 Reset Required 状态。
Xorg 与显示器仅为触发条件,本身无过错。对于不连接显示器、不运行图形栈的纯计算环境,该代码路径不会被触及,此类故障不会发生。
在线恢复:带内复位失效,改用 PCI FLR
GPU 挂死后的标准恢复手段为 nvidia-smi --gpu-reset,但执行后返回:
1 | The following GPUs could not be reset: |
原因:带内(in-band)复位依赖 GPU 侧 GSP 配合响应,而 GSP 已经崩溃,该路径不可用。
需改用硬件级手段:PCI FLR(Function Level Reset)。FLR 是 PCIe 规范定义的硬件复位机制,不依赖 GPU 固件。操作前先确认拓扑:三张 GPU 各独占一条 PCIe 总线(01、41、61),总线上仅有对应 GPU 的音频功能设备,复位不影响其他设备。完整流程如下:
1 | # 1. 释放 GPU 上的全部进程(gdm/Xorg、nvidia-persistenced 及监控进程) |
三张 GPU 复位成功,驱动重新绑定后 GSP 固件重新加载,nvidia-smi 恢复正常:
1 | | 0 NVIDIA GeForce RTX 4090 On | 00000000:01:00.0 N/A | |
恢复过程未重启系统,25 天的连续运行时间得以保留。
后续加固措施
措施一:关闭 GSP 并持久化(可能有性能损失)
GSP 固件缺陷仍然存在,复发风险未消除。查阅驱动源码(/usr/src/nvidia-*/common/inc/nv-firmware-registry.h)确认参数语义后,在 /etc/modprobe.d/nvidia.conf 中写入:
1 | options nvidia NVreg_EnableGpuFirmware=0 |
该参数低 4 位为模式选择:0=禁用、1=启用、2=默认策略。故障时运行值为 18(0x12,默认策略加回退位),即 4090 默认启用 GSP。设为 0 后,资源管理回退至主机侧 RM——NVIDIA 长期维护的成熟代码路径,可彻底绕开出事的固件代码。(注:该配置在驱动升级后撤销,见下文。)
措施二:显示输出迁移至板载显卡
机器配备 ASPEED BMC 板载 VGA(63:00.0,内核 ast 驱动,系统主帧缓冲 fb0)。目标:桌面会话运行于板载显卡,4090 不再承载任何显示进程。实施步骤:
- 编写
/etc/X11/xorg.conf,将 X server 固定绑定至板载显卡:
1 | Section "Device" |
- 在
/etc/modprobe.d/nvidia.conf中屏蔽 nvidia 的 KMS 模块,使 4090 不具备显示接口:
1 | blacklist nvidia_drm |
- 处理两个预期外问题:
- udev 规则绕过黑名单:
/lib/udev/rules.d/71-nvidia.rules中存在RUN+="/sbin/modprobe nvidia-drm",nvidia 驱动绑定时会显式加载 nvidia_drm,modprobe 黑名单无法拦截显式请求。在/etc/udev/rules.d/下覆盖该规则并删除对应行后解决; - 远程桌面软件占用:ToDesk 服务进程持有三张 4090 的 DRM 设备句柄,重启该服务后释放。
- udev 规则绕过黑名单:
措施三:驱动版本升级(595.71.05 → 595.91.07)
595 分支存在安全更新版本 595.91.07,同步完成升级。过程中遇到两个问题:
- 驱动相关包被 dpkg hold 锁定,需先
apt-mark unhold解除; - Ubuntu 驱动包存在命名迁移(如
libnvidia-cfg1→libnvidia-cfg1-595),新旧包声明了同一文件libnvidia-cfg.so.1,dpkg 解包时报文件冲突。先dpkg --remove移除旧包,再执行apt -f install修复完成。
DKMS 编译新内核模块后,在不重启系统的前提下完成模块热替换(复用前述解绑/绑定流程):
1 | for bdf in 0000:01:00.0 0000:41:00.0 0000:61:00.0; do |
热替换完成,三张 GPU 的 driver_version 均为 595.91.07。鉴于新版本的 GSP 固件可能已修复本次 Xid 120 缺陷,撤销了 GSP 关闭配置(GSP 恢复默认启用状态),转入观察期。
衍生问题:nvidia-smi 查询延迟增大
升级完成后发现 nvidia-smi 响应时间从秒级增大至约 3 秒。通过分步定位确认瓶颈所在:
- 最小查询(
--query-gpu=index)同样耗时 2.9s,排除特定查询字段的问题,瓶颈位于 NVML 初始化(设备 attach) 阶段; - 后台维持一个常驻 NVML 连接(
nvidia-smi dmon)后再次测量,耗时降至 0.04s。
结论:每次新建 NVML 连接需支付约 3 秒的 GSP 唤醒握手开销。根本原因是持久模式(persistence mode)处于关闭状态——595.91 版本的 nvidia-persistenced.service 厂商单元文件中带有 --no-persistence-mode 参数。无客户端连接时 GSP 进入低功耗挂起状态,而 nvidia-smi 每次执行均为新进程、新连接,因此每次都需要唤醒 GSP。
此前未暴露该问题,是因为 4090 上长期存在 Xorg、ToDesk 等常驻连接,GPU 未进入完全空闲状态;显示输出迁移至板载显卡后,GPU 进入真正空闲,该问题随之显现。
修复方案:
1 | sudo nvidia-smi -pm 1 # 立即生效 |
为使其在重启后依然有效,通过 systemd drop-in 移除 --no-persistence-mode 参数(/etc/systemd/system/nvidia-persistenced.service.d/override.conf),由守护进程在启动时为全部 GPU 开启持久模式。
修复后实测:GPU 空闲 60 秒后执行 nvidia-smi,耗时 0.09s(修复前 2.9-3.2s)。
总结与经验
| # | 经验 |
|---|---|
| 1 | GSP 是新版 NVIDIA 驱动架构中的单点:资源管理集中于板载固件,固件崩溃将导致整卡不可用。GeForce 显卡支持通过 NVreg_EnableGpuFirmware=0 关闭 GSP,计算集群应评估该配置的稳定性收益 |
| 2 | 多卡同时故障且崩溃现场完全一致(PC、故障地址、寄存器状态)时,应优先判定为软件缺陷而非硬件损坏。GSP-CrashCat 报告是定位此类问题的关键材料 |
| 3 | GSP 失效后带内复位(nvidia-smi --gpu-reset)不可用,返回 Not Supported。此时应走 unbind → /sys/.../reset(FLR)→ bind 的纯硬件复位路径 |
| 4 | 通过 PCI 设备的解绑/绑定操作,可在不重启系统的前提下完成 GPU 复位与内核驱动版本热替换,是保障在线服务可用性的重要手段 |
| 5 | modprobe 黑名单无法拦截 udev 规则中的显式 modprobe 调用,排查模块加载来源时需同时检查 /lib/udev/rules.d/ 下的驱动规则 |
| 6 | 持久模式是低延迟访问的前提:关闭状态下 GSP 会进入挂起,每次新连接产生秒级唤醒延迟。计算服务器建议常驻开启(nvidia-smi -pm 1) |
| 7 | 驱动升级后用户态库与内核模块版本必须一致,否则 NVML 报 Driver/library version mismatch,需重启系统或热替换内核模块 |
| 8 | 向 NVIDIA 报告 GSP 缺陷时,完整的 GSP-CrashCat 报告(含 RISC-V 寄存器状态、堆栈、GSP bin buildId)与触发时的 RPC 历史是必要的复现材料 |






