ある日、いつものように再起動したら起動しませんでした。カーネルパニックです… (数年ぶり)
そのまま固まってしまったので、電源を落として 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も無関係。純粋にバージョンの非互換でした。
連鎖を整理するとこうなります。
- HWEカーネルが6.17系から7.0系に切り替わった
- 新カーネルのpostinstがDKMSを呼び、NVIDIAモジュールをビルドしようとする
- API変更でビルドが落ちる
linux-image-7.0.0-XX-genericの設定が失敗する- dpkgが中途半端な状態で止まり、以降のaptが全部巻き添えになる
- その状態で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カーネルはこれからも上がっていくので、同じ踏み方をする人はぼちぼち出てくる気がします。誰かの役に立てば嬉しいです!


コメント