再起動したらカーネルパニック。原因はNVIDIAドライバのビルド失敗でした…

Ubuntu

ある日、いつものように再起動したら起動しませんでした。カーネルパニックです… (数年ぶり)

そのまま固まってしまったので、電源を落として GRUB のメニューから一つ前の 6.17 系カーネルを選んだところ、あっさり起動しました。パニックしたのはたぶん 7.0.0-28 だったと思うのですが、慌てていたので画面を控えておらず、ここは記憶が曖昧です。

何度か試してみましたが、7.0系を選ぶと毎回パニック、6.17を選ぶと毎回ちゃんと起動する、という具合にきれいに再現しました。たまたま一度コケただけならまだしも、これでは新しいカーネルが完全に使い物になりません。逆に言えば、まぐれや気まぐれな不具合ではなく、原因がはっきり存在するということでもあります。

とりあえず生きているカーネルで起動できたので、腰を据えて原因を追うことにしました。結論から言うと、NVIDIAドライバのカーネルモジュールがビルドできず、その巻き添えでカーネルのインストールが中途半端なまま放置されていたのが原因でした。

環境は Ubuntu 24.04、GPUはRTX 2060とRTX 3060の2枚挿しです。

aptが壊れていた

6.17で起動して apt を叩いたら、見慣れないエラーが流れてきました。

Error! Bad return status for module build on kernel: 7.0.0-30-generic (x86_64)
dkms autoinstall on 7.0.0-30/x86_64 failed for nvidia(10)
dpkg: パッケージ linux-image-7.0.0-30-generic の処理中にエラーが発生しました (--configure):
E: Sub-process /usr/bin/dpkg returned an error code (1)

これ以降、何をインストールしようとしても同じところで止まります。しかも処理中にエラーが出ていたパッケージの一覧に、パニックした 7.0.0-28 と、その次の 7.0.0-30 が両方並んでいました。

つまり僕が気づいていなかっただけで、カーネルのインストールはずっと前から失敗し続けていたわけです。エラーは apt upgrade の出力の中を流れていったはずなんですが、完全に見逃していました。再起動して初めて気づいたという。

パニックの直接の原因は、たぶんカーネルの設定が完了しなかったせいで initramfs やモジュール周りが不完全なまま残っていたことだと思います。ここは画面を控えていないので断定はできませんが、少なくとも「起動に必要な処理が最後まで終わっていないカーネル」で起動しようとしていたのは確かです。

先に結論

同じところで詰まった人向けに、直し方を先に書いておきます。

# 1. 詰まりの原因になっているDKMSを外す
sudo apt purge nvidia-dkms-590

# 2. 保留されていた設定を完了させる
sudo dpkg --configure -a
sudo apt --fix-broken install

# 3. 新しいドライバを入れる
sudo ubuntu-drivers install nvidia:610

apt purge が処理の冒頭で同じエラーを出して止まる場合は、dpkgで直接引き剥がします。

sudo dpkg --purge --force-depends nvidia-dkms-590
sudo dpkg --configure -a

ポイントは、ドライバのバージョンを上げるしかないということです。設定をいじって直る類のものではありませんでした。理由は以下。

何が起きていたのか

まず make.log を見ました。DKMSは失敗の詳細をここにしか書いてくれません。

sudo tail -n 50 /var/lib/dkms/nvidia/590.48.01/build/make.log

決定的だったのがこの行です。

nvidia/nv-mmap.c:928:42: error: ‘VMA_LOCK_OFFSET’ undeclared (first use in this function);
                          did you mean ‘VGA_CRTC_OFFSET’?
  928 |  detached = refcount_sub_and_test(VMA_LOCK_OFFSET, &vma->vm_refcnt);

カーネル7.0でper-VMAロックまわりの実装が変わり、VMA_LOCK_OFFSET が廃止されていました。NVIDIAドライバ側は古い前提のままなので、コンパイルが通らないというわけです。ヘッダもgccも揃っているし、Secure Bootも無関係。純粋にバージョンの非互換でした。

連鎖を整理するとこうなります。

  1. HWEカーネルが6.17系から7.0系に切り替わった
  2. 新カーネルのpostinstがDKMSを呼び、NVIDIAモジュールをビルドしようとする
  3. API変更でビルドが落ちる
  4. linux-image-7.0.0-XX-generic の設定が失敗する
  5. dpkgが中途半端な状態で止まり、以降のaptが全部巻き添えになる
  6. その状態で7.0系を選んで起動 → 毎回カーネルパニック ← イマココ

設定が完了していないカーネルは、何度起動し直したところで完了しません。毎回同じところでコケていたのはそういうことでした。

590は既に終わっていた

じゃあどのバージョンに上げればいいのか。ここで apt-cache policy が効きました。

$ apt-cache policy nvidia-dkms-590
nvidia-dkms-590:
  インストールされているバージョン: 590.48.01-0ubuntu0.24.04.4
  候補:               590.48.01-0ubuntu0.24.04.5

新しい .5 があるじゃないか、と思って中身を調べたら、変更内容がこれでした。

Transition the 590 driver to 595 (LP: #2146602)

.5 は中身のあるアップデートではなく、595へ移行させるためのパッケージでした。590はUbuntu側で既に終息扱いだったんですね。だから ubuntu-drivers list の選択肢にも590は出てきませんし、カーネル7.0対応のパッチも当たらない。590を直す道はそもそも存在しなかった、というオチです。

移行先を決めるときは、ビルド済みモジュールの有無を見ると確実です。

$ apt-cache policy linux-modules-nvidia-610-generic-hwe-24.04
  候補:               7.0.0-30.30~24.04.1

候補のバージョンが 7.0.0-30 になっています。これは「カーネル7.0.0-30用にビルド済み・署名済みのモジュールが実在する」という直接の証拠なので、対応状況を推測しなくて済みます。

僕の場合は最終的に595.84に着地しましたが、両方のカーネル向けにビルドが通ったので問題なしとしました。

$ dkms status
nvidia/595.84, 6.17.0-35-generic, x86_64: installed
nvidia/595.84, 7.0.0-30-generic, x86_64: installed

この状態で再起動したら、あれだけ毎回パニックしていた7.0系が何事もなかったように立ち上がりました。nvidia-smi もGPU2枚をきちんと認識してくれています。

次に同じことを起こさないために

今回の構成はDKMS方式なので、次にカーネルが上がるときも同じようにビルドが走ります。595系が終息扱いになった頃に、また同じことが起きる可能性があるわけです。

予防したいなら、linux-modules-nvidia-610-generic-hwe-24.04 形式のビルド済みモジュールに移しておく手があります。Canonicalがカーネルに合わせてビルドしたものが降ってくるので、手元でのビルド失敗という事故が構造的になくなります。Secure Boot環境でも署名済みなのでMOK登録が要らないのも地味に嬉しいところ。

とはいえ今は安定して動いているので、僕は次のカーネル更新のタイミングで移そうと思っています。

まとめ

  • カーネルパニックの原因が、実は数日前の apt upgrade の失敗だったというパターンがある
  • DKMSのビルド失敗は /var/lib/dkms/<name>/<version>/build/make.log を見ないと原因が分からない
  • VMA_LOCK_OFFSET のエラーはカーネル7.0のAPI変更が原因。設定では直らないのでドライバを上げるしかない
  • 移行先を選ぶときは apt-cache policy linux-modules-nvidia-XXX-generic-hwe-24.04 の候補バージョンを見ると確実

HWEカーネルはこれからも上がっていくので、同じ踏み方をする人はぼちぼち出てくる気がします。誰かの役に立てば嬉しいです!

コメント

タイトルとURLをコピーしました