1 ポイント 投稿者 GN⁺ 2025-02-18 | 1件のコメント | WhatsAppで共有
  • AMD RX 570搭載のLinuxデスクトップで、RAM使用量が高い状態でサスペンドすると、復帰後に黒画面や入力不能状態が繰り返し発生し、単なる画面の問題を超えてカーネルの電源管理フローまで追跡する必要があった
  • 根本原因は、S3サスペンド前にVRAMをシステムRAMへバックアップする必要があるamdgpuが、空きRAM不足の状況でディスクswapを適切に利用できず、OOMで破綻する流れにあった
  • VRAM evictionをdpm_suspend()からdpm_prepare()へ前倒しする最初のパッチは、SSDの電源断との競合を減らしたが、pm_restrict_gfp_mask()がすでにswapを無効化しているため、連続メモリ不足は依然として発生し得た
  • その後、register_pm_notifier()PM_SUSPEND_PREPARE時点にamdgpu_device_evict_resources()を呼ぶよう変更すると、swapとディスクが生きている間にVRAMをバックアップでき、テスト環境では高RAM・高VRAM使用量でもサスペンドが成功した
  • この変更はamdgpuツリーにマージされたものの、デッドロックの可能性のため2025-06にリバートされ、ユーザープロセスを先にfreezeしないサスペンド経路では、3DアプリがVRAMを再びGPUへ引き戻してevictionを妨げ得る

繰り返されたサスペンド失敗と初期の誤診

  • デスクトップはWindowsとLinuxのデュアルブート構成で、LinuxでRAM使用量が高いときにサスペンドを試みると、システムが頻繁に壊れた
    • 復帰後に黒画面と動くカーソルだけが見える、あるいは画面出力がなくmagic SysRqやハードリセットにしか反応しない
    • 一部のケースではKDEロック画面の時計はリアルタイム更新されるが、ログインや操作を試みると停止する
  • テスト環境はGigabyte B550M DS3H、AMD RX 570 GPU、Kingston A2000 1TB NVMe SSD、Arch Linux、systemd-boot、Linux 6.4だった
  • journalctl --system -b -1で前回起動ログを確認すると、一部のサスペンド試行でamdgpu_device_suspend配下のカーネルコードにOOMエラーが現れた
  • 多くの失敗事例は次のログで終わっており、壊れたシステムが再び起動した記録は残っていなかった
    • systemd-sleep: Entering sleep state 'suspend'...
    • kernel: PM: suspend entry (deep)
  • 当初はNVMe APST省電力モードを疑い、nvme_core.default_ps_max_latency_us=0iommu=soft、SSDファームウェア更新、2TB起動SSDへの交換を試したが、問題は解決しなかった

失敗位置を絞り込んだデバッグツール群

  • systemdが複数のサスペンドモードを連続試行する動作がログノイズやカーネル状態の悪化を招き得るため、/etc/systemd/sleep.confSuspendState=memを追加した
    • デバッグは単純化したが、根本原因はそのままだった
  • echo 1 > /sys/power/pm_traceでサスペンド失敗位置を追跡した
    • pm_traceはサスペンド・復帰の進行状態をシステム時刻に保存する
    • 非同期サスペンドが無効化される副作用のおかげで、amdgpuのsuspend失敗後にシステム全体がハングする代わりに回復するパターンも確認できた
  • systemd.debug_shellカーネルパラメータを追加し、KDEやTTYログインなしでもCtrl-Alt-F9でroot shellを開けるようにした
  • USBコントローラやキーボードが壊れる場合に備えてPS/2キーボードを使い、その後はシリアルコンソールを構成した
    • カーネルパラメータ: no_console_suspend console=tty0 console=ttyS0,115200 loglevel=8
    • ノートPCでsudo minicom --device /dev/ttyUSB0 --baudrate 115200を使ってログを継続捕捉した
    • シリアルコンソールはディスプレイとネットワークが壊れた後でもコマンド実行とログ収集を可能にしたが、転送速度や色・画面サイズ処理には制約があった

amdgpuのVRAM evictionとOOMのつながり

  • クラッシュログは概ねamdgpuのTTMバッファeviction経路で発生していた
    • amdgpu_device_evict_resources()
    • amdgpu_ttm_evict_resources()
  • 関連バグレポートから、“evict”はVRAMをシステムRAMへコピーしたり、システムRAMをswapへ追い出したりする動作に関係すると分かった
  • デスクトップがS3サスペンドに入るとPCIe GPUの電源が切れ、VRAMチップ上のデータは消える
    • GPUドライバはサスペンド前に使用中のVRAMをシステムRAMへコピーする必要がある
    • 復帰後はRAMに保存したデータを再度復元しなければならない
  • Linuxのamdgpuドライバには、使用中VRAM全体を収める空きRAMがないとき、システムRAMをディスクベースのswapへ逃がす代わりに、メモリ不足でクラッシュする問題があった
  • Linuxがsuspend中にOOMへ遭遇すると、サスペンドを中止してデバイスを再起動しようとするが、すでに中断されたサスペンドのため一部ドライバが壊れたり、suspend/resume中に再度OOMが起きたりする
    • 非同期サスペンドが有効だと危険性はさらに高い
    • サスペンド自体は成功しても、resume中のデバイス起動処理でOOMが発生することもある

最初の解決の試み: VRAMバックアップ時点の前倒し

  • Mario Limoncielloは/sys/power/pm_print_times/sys/power/pm_debug_messagesを有効にしてサスペンドログを確認するよう提案した
  • ログでは、NVMeとamdgpuドライバがサスペンド中にpci_pm_suspend並列に入っていることが分かった
  • 当初はGPUのsuspendをSSDのsuspendより先にする方法を探し、Linuxのdevice suspend orderingメカニズムも調べた
    • このメカニズムは、すべてのGPUをすべてのシステムディスクより先にsuspendする用途というより、密接に接続した周辺機器の同期に近いように見えた
  • MarioはLinux suspendのprepare段階でVRAMをevictする方式を提案し、VRAM evictionをdpm_suspend()からdpm_prepare()へ移すカーネルパッチを書いた
  • 変更前後の流れは次の通り
    • 従来: dpm_suspend()時点でVRAMバックアップが実行され、SSDの電源断の流れと重なり得る
    • 変更後: dpm_prepare()で先にVRAMバックアップを試み、失敗したら他デバイスのsuspend前にサスペンドを中止する
  • この変更は以前より改善したが、pm_restrict_gfp_mask()dpm_prepare()より前にswapを無効化するため、高RAM使用量では依然として失敗した
    • amdgpu_ttm_evict_resources()は連続メモリ不足で失敗し得る
    • VRAMをRAMへすべて入れられても、その後のドライバ割り当てを処理する余裕が足りなければ、sleepまたはwake中にOOMが起きる可能性がある

Ghidraで見つけた別のamdgpuクラッシュ

  • テスト中にBUG: unable to handle page fault for address: fffffffffffffffcエラーが発生し、ほぼnullに近いポインタ参照のように見えた
  • クラッシュログはdm_resume+0x200の位置を指していたが、ソースコードの行番号は示されていなかった
  • amdgpu.koカーネルモジュールを保存・抽出したうえでGhidraで逆コンパイルし、dm_resume内のクラッシュ位置をカーネルソース行へ対応付けた
  • 問題はfor_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i)マクロで発生していた
    • dm->cached_stateは有効なポインタではなくfffffffffffffff4だった
    • その後[RSI + 0x8]フィールドを読もうとしてfffffffffffffffcアドレスでpage faultが発生した
  • 原因は、dm_suspend()drm_atomic_helper_suspend()の戻り値をそのままポインタへ格納していた流れにあった
    • drm_atomic_helper_suspend()は有効ポインタまたはERR_PTR(err)を返し得る
    • OOMにより-ENOMEM (-12)が返され、amdgpuのsuspendコードがそれをポインタとして参照したと判断された
  • Marioは失敗戻り値を検査してsuspendを中止するコードを追加し、この問題を修正した

断念した方向: prepare()中にswapを許可する

  • 高RAM使用量でサスペンド失敗が続いた理由は、amdgpuがdpm_prepare()でVRAMをバックアップしても、この時点ではすでにpm_restrict_gfp_mask()がディスクswapを無効化しているためだった
  • ひとつの試みは、dpm_prepare()ではswapを許可し、dpm_suspend()がディスクを止める直前にswapを無効化する構成だった
  • そのために、pm_restrict_gfp_mask()呼び出しをenter_state()からより深いdpm_suspend_start()内へ移す実験を行った
  • 実務上の制約は大きかった
    • pm_restrict_gfp_mask()kernel/power/power.hで宣言され、kernel/power/suspend.cで呼ばれている
    • 呼び出したかった場所はdrivers/base/power/main.cで、このファイルは通常kernel/power/ヘッダをインクルードしない
    • 一時的なハックとして#include <../kernel/power/power.h>を追加したが、upstreamへ持ち込むには説得が必要な構造だった
  • ハイブリッドサスペンドでも正しさの問題があった
    • ハイブリッドサスペンドはシステムイメージを保存し、pm_restrict_gfp_mask()を呼んだ後、swapが無効化された状態でsuspend_devices_and_enter()を呼ぶ
    • 同じ関数を再度呼ぶと警告が発生し、pm_restore_gfp_mask()がswapを再有効化できない可能性がある
  • テストでは失敗やクラッシュの頻度は減ったが完全には解決せず、core power managementに手を入れる脆い変更だったためupstream化は試みなかった

ユーザースペースの回避策: amdgpu-sleep

  • 2024-10にSuperTuxKart終了後サスペンドし、復帰時に黒画面が発生した
    • ログ上では最初のサスペンド試行がdpm_prepare()でOOMになり、次の試行はresume中のamdgpuのbw_calcs()メモリ割り当てクラッシュへつながった
  • NVIDIAのユーザースペースVRAMバックアップ方式を参考にした
    • NVIDIAはsystemdがkernel suspendを呼ぶ前後に実行されるサービスから/proc/driver/nvidia/suspendへ書き込み、VRAMバックアップ・復元を行う
  • これをもとにArch Linux向けのamdgpu-sleepパッケージを作成した
    • サスペンド前に/sys/kernel/debug/dri/1/amdgpu_evict_vramを読み出す
    • このdebugエンドポイントはamdgpuに全VRAMをシステムRAMへ保存するよう指示する
    • systemdはGPUのVRAM eviction完了まで待ってからkernel suspendを開始する
  • デスクトップでサスペンドすると、VRAMを素早くメモリへコピーし、必要ならRAMをswapへ押し出して成功した
  • 複数の3Dアプリが動作中だと、アプリが継続してフレームを描画し、VRAMを再びGPUへ引き戻してamdgpu_evict_vram綱引きのようなライブロックが発生した
    • この状態は70秒以上続いた後、amdgpu_evict_vramが断念した
    • その後systemdがkernel suspendを開始してuserspaceをfreezeすると、kernel段階ではVRAM evictionが成功した
  • このスクリプトは、ライブロック発生頻度よりも、スクリプトを無効にしたときのkernelレベルクラッシュ発生頻度のほうが低くなかったため、使い続けられた

最終パッチ: power management notifier

  • 2024-11、Marioはswapがまだ有効な間にevictionを許可するパッチのテストを依頼した
  • パッチはregister_pm_notifier()を呼ぶ構造で、Linuxのpower management notifier APIを使っていた
  • コールバックはPM_HIBERNATION_PREPAREPM_SUSPEND_PREPAREメッセージを受け取り、amdgpu_device_evict_resources()を呼ぶ
  • PM_SUSPEND_PREPAREenter_state() → suspend_prepare()pm_notifier_call_chain_robust(PM_SUSPEND_PREPARE, PM_POST_SUSPEND)を通じて発行される
    • notifierコールバックを持つドライバへPM_SUSPEND_PREPAREが渡される
    • 失敗が起きると、すでに準備済みのドライバへPM_POST_SUSPENDが渡され、サスペンドは中止される
  • この位置でVRAMをevictすると、pm_restrict_gfp_mask()がswapを無効化する前であり、ディスクもまだfreezeされていない
  • 修正後のフローは次の通り
    • suspend_prepare()
    • PM_SUSPEND_PREPARE
    • amdgpu_device_pm_notifier() → amdgpu_device_evict_resources()
    • pm_restrict_gfp_mask()
    • dpm_prepare()
    • dpm_suspend()
  • 修正済みamdgpuドライバを含むカスタムカーネルをビルドしてテストした結果、高RAM・高VRAM使用量で何度サスペンドしてもエラーは発生しなかった
  • ただし、amdgpuがPipeWireやkernelがスピーカーをミュートする前にVRAMをバックアップするため、数秒間オーディオがループ再生される現象が見られた
  • 数回のコードレビューを経て、この変更はamdgpuツリーへマージされ、1年以上にわたる試行の末、このバグを解決する段階へ進んだ

2025-06アップデートとリバート

  • 当初、この変更はstable Linux kernel 6.14に含まれると予想されていたが、その後デッドロックの可能性によりリバートされた
  • 新たに持ち込まれた問題は、systemdがすべてのユーザースペースプロセスを先にfreezeせずにsystem suspendを呼ぶ場合に発生する
    • kernelが自前でプロセスをfreezeする前にVRAMをシステムRAMへevictしようとする
    • 同時に3DプログラムがVRAMを再びGPUへ戻すと、サスペンド時のeviction処理がデッドロックする可能性がある
  • これはユーザースペースのamdgpu_evict_vram回避策で経験したライブロックに似ている
  • Linux PMメンテナは、pm_restrict_gfp_mask()呼び出しをsuspend_devices_and_enter()の内側へ移す案を提案した
    • これは先に試していたprepare()中にswapを許可する方向とつながっている
  • 自分で実装・投稿する予定はない
    • AMD GPUを、より遅いCPUと8GBメモリを持つ古いPCへ移したため、その環境でカーネルビルドを回したくないからだ
  • メインPCはIntel Arc B570へアップグレードしたが、10GB VRAMでも同種の問題が発生した
    • この問題はdrm/xe kernel bug trackerへ報告された

1件のコメント

 
GN⁺ 2025-02-18
Hacker Newsのコメント
  • デスクトップがS3スリープに入るとPCIe GPUの電源が切れる、という前提は確実ではない
    S3はRAMを除くすべての電源を切るのが本来だが、たとえばGigabyte AorusのマザーボードはNVMe SSDのスリープバグで、システムが正常にスリープしたり復帰したりできないことで悪名高い
    たいていは、すべてのPCIeポートのウェイクアップを無効にするudevルールで回避できる: ACTION=="offline", SUBSYSTEM=="pci", DRIVER=="pcieport", ATTR{power/wakeup}="disabled"
    さらに絞るなら、問題のあるPCIeポートだけを ATTR{vendor}=="0x8086", ATTR{device}=="0x43bc" のように指定でき、/proc/acpi/wakeup/sys/class/pci_bus/*/*/yourWakeupDevicePci/uevent | grep PCI_IDudevadm info --attribute-walk /dev/whatever で原因を探せる
    udevの代わりにsystemdサービスや自動化スクリプトで /proc/acpi/wakeup をトグルすることもできるが、安定性は低く、こうしたLinuxのスリープ問題には本当にうんざりする

    • 私のマザーボードでは、/etc/udev/rules.d/ACTION=="add", KERNELS=="0000:00:01.1", ATTR{power/wakeup}="disabled" を入れて自発的なウェイクアップを防ぐ必要があった
      Logitech Boltレシーバーも複数のLinuxマシンを即座に起こしてしまうのに、Windowsではそうならない理由が分からないし、USBキャプチャを試すにはロジックアナライザやGlasgowのような機材が必要なのかも微妙
      当面は ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c548", ATTR{power/wakeup}="disabled" というルールを追加して防いでいる
    • Aorusのマザーボードでこの問題により数kWhは無駄にした気がするので解決策を期待したが、私の場合は効果がなかった
    • X570 Aorus Masterでもスリープ問題に悩まされていたが、起動時にsystemdユニットで echo GPP0 >> /proc/acpi/wakeup を実行すると解決した
      ただし起動後最初のスリープは必ず即座に復帰していたが、上のudevルールを適用したところ、その問題も解決したようだ
    • ハードウェアが実際にスリープしたか検出できるか、あるいはスリープしなかったハードウェアを再度起こしても問題がないようになっていることを期待してしまう
      PCIeデバイスにスリープ命令を送った後でバス自体をスリープさせ、復帰時にはまずバスを戻してからデバイスを起こす、という形が可能であるべきだと思う
    • この問題でしばらく苦労したが、この方法もうまくいかず、まとめた内容は https://bbs.archlinux.org/viewtopic.php?id=302440 にある
      私の場合、ウェイクアップの原因は .../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:45/wakeup/wakeup6 から来ているようだが、このパスが何を意味するのかよく分からない
  • 言及されているユーザー空間での回避策の一つであるmemreserverの作者として、数年前にこの問題をデバッグした
    すぐ見つかる公開コメントは https://gitlab.freedesktop.org/drm/amd/-/issues/2125#note_17... で、メーリングリストでの議論もあったと記憶している
    要点は、Linuxにはディスクとメモリサブシステムの一部が凍結される前に安定して実行される段階的なsuspendフックがなかったことだったが、今では可能になっているようだ
    残念ながらFreedesktop Gitlabはインデックスされにくいようで、この知見は埋もれてしまったようだ

  • 本当に素晴らしい仕事
    Linuxでスリープへの移行をきちんと動かすのがなぜ難しく、デバッグも難しいのか気になっていたなら、この記事だけでも壊れ得る箇所がどれほど多いかがよく分かる
    今でもThinkPad P1G4では、スリープ前にファンを手動で止めないと自動で止まらず、最近はスリープ復帰後にBluetoothヘッドフォンでノイズが出るようになり、PipeWireのノードスリープも無効にする必要があった: https://wiki.archlinux.org/title/PipeWire#Noticeable_audio_d...

    • 2025年になってもLinuxノートPCのsleep/suspendがまだまともに動かないというのは驚き
      初めてこういう問題に遭遇したのは、たぶん15年ほど前だった
    • スリープは本当に当たり外れが大きく、記事に出てくるようなエラーはデバッグも非常に難しい
      さまざまな問題に対して提案される回避策の中には省電力モードをオフにするものがあるが、スリープを使う目的は普通バッテリー駆動時間を延ばすことなので、この方法は実使用時間が大きく短くなりかねず、あまり現実的ではない
      それでもS0ixスリープを動かすのが不可能というわけではない
      AMD 7840UとAMD 8840Uベースの携帯型デバイス、つまりGPD Win Max 2、GPD Win Mini、GPD Win 4、Minisforum V3、OneXPlayer X1 RyzenにArch Linuxをインストールしたが、これらの会社がLinuxサポートを念頭に置いて設計したりテストしたりした可能性は低そうに見える
      ところが、/proc/acpi/wakeup/sys/devices/*/*/*/power/wakeupで偽のウェイクアップソースを少し調整する程度で、最新のOneXPlayer X1 Ryzenを除けば、ほぼ完璧なS0ixサポートが得られた
      標準のLinuxカーネルサポートも優秀で、タッチスクリーン、ペン入力、Wi-Fi、Bluetoothはうまく動き、見かけた唯一の穴は指紋リーダーのサポートだった
      こうした小規模メーカーは部品の極端なカスタマイズや緻密な統合が少なく、実際にデバイスが数mmずつ厚い形で表れている
      そのため、より保守的な部品選定になり、その結果Linuxサポートが意外に良いのかもしれない
    • エンドユーザーがスリープを簡単かつ確実に使いたいなら、検証済みの互換ハードウェアを買うのが答え
      自分の経験では、ビジネス向けThinkPadではかなり前から非常に安定しており、同じモデルのWindowsユーザーのほうがむしろスリープ問題に頻繁に遭っているように見える
  • 個人的に本当にありがたい
    メインのノートPCがLinuxを動かしているRyzenベースのThinkPadで、スリープとハイバネーションをよく使うのだが、この問題には断続的に遭遇してきた
    Linux 6.14が楽しみ

  • dm->cached_stateがポインタではなく-12を保存していた理由は、おそらくsuspend中にdm_suspend()dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev))をそのまま代入したためである可能性が高い
    呼び出されたdrm_atomic_helper_suspend()は、有効なポインタか、エラーを負のポインタとしてエンコードしたERR_PTR(err)を返すことがあり、呼び出し側がエラーを検査せずにそのままポインタへ入れ、resume時に逆参照したということ
    カーネルにRustを入れるべき理由がまた一つ増えたし、Result型の処理が強制されれば、こういうことは起きにくい

    • Cプリプロセッサでも代数的和型は作れる: https://github.com/Hirrolot/datatype99
      しかしデフォルトが重要で、カーネルがコーディング慣行の近代化を長く先送りしてきた歴史は、C側の改善には不利に働く
      皮肉なことに、同じ抵抗のせいでRust開発者たちも挫折している。各サブシステムを整理したり、動作方式を文書として残したりすることすら、なかなか受け入れられないからだ
      https://github.com/llvm/llvm-project/issues/74205のようなものがカーネルまで降りてくれば助けになるかもしれないが、それでも型で安全性を確保するより、ポインタを手動でオーバーロードする方法を選び続けそうだ
  • GPU拡張モジュールを付けたFramework AMDノートPCでLinux/Windowsのデュアルブートを使っているので、この作業は役に立ちそう
    直接支援するか、希望する慈善団体に寄付したい。連絡先はプロフィールにある

  • 命名、キャッシュ無効化、off-by-oneエラーがコンピュータサイエンスにおける最大の2つの問題だと思っていたが、sleep/wake問題を知ってからは、これはNP完全に見える

    • sleep/wakeはキャッシュ無効化の部分集合だと思う
      すべての周辺機器が状態を持たないなら、おそらく問題ではなかったはず
    • Linuxだけそうで、WindowsではO(n²)、macOSではO(log n)
  • Linuxにおけるメモリ管理、特にOOM状況は、いまだに信じがたいほど苦痛な悪夢である
    こうした問題を常に経験しているわけではないが、似たような問題をデバッグしようとして失敗したことは確かにあり、結局OOMになるとたいていRAMを増設することになる
    無駄で高くつくが、OOM状況を優雅に処理することは、今後もLinuxにとって解決の難しい問題であり続けそうだ
    今回の作業は素晴らしく、今後似たような問題をデバッグするときの基準点になるだろう
    systemdのdebug-shell機能もありがたいし、そんな機能があるとは知らなかった
    ただ、自分のX670E Steel Legendマザーボードにはシリアルヘッダーがないようなのだが、最近のオンボードシリアルポートはどう動作しているのか気になる
    チップセットのPCIeレーンにぶら下がっているのだろうか
    Linuxカーネルを深く掘るときは、FOSDEMやLinux Plumbers Conferenceのような場でのカーネルサブシステム発表の録画が大いに役立つ。たとえば、ほとんどのデスクトップGPU DRMドライバーが使うTTMメモリサブシステムの動画はこちら: https://www.youtube.com/watch?v=MG7_tUNKSt0

    • Windowsでは、自分のマザーボードのシリアルポートはPci Bus → PCI standard ISA bridgeに接続されていると表示される
      DOS万歳
      TTMの動画は時間があるときに見るつもり
    • OOMをcgroupsで閉じ込めるのはかなりうまくいった
      Linuxがやっていることより優れた最新のOOM処理方式があるのかはよく分からないので、関連して読む価値のある資料があれば知りたい
    • その通りで、控えめに言ってもひどい
      LinuxはOOM状況をまともに処理できない
      cgroupsでガードレールを設けられるし、earlyoomをインストールすることもできるし、swapを増やしたりzramを使ったりできることは知っている
      だが結局どれも、たまに一度救ってくれるかもしれない汚いハックにすぎず、こうした状況の処理のされ方そのものは直せない
      こういうものを解決策として提示しないでほしい
      カーネルがdm_cryptでメモリを割り当てられず、LUKSボリュームが自分で読み取り専用としてマウントされるのを見たことがあるが、頼むからユーザー空間プロセスを1つ殺してくれればいい
      現状は到底受け入れられないし、言い訳にも疲れた
    • zswap/zramを試したことがあるのか気になる
      zstdを使えば、8GB RAMを大きな問題なく20GBの「RAM」のように、16GBを40GBのように使える
      さらに踏み込めばメモリを100%超でオーバーコミットすることもできるし、Androidもこうしているので、かなり安定した方式だ
  • 朗報だ
    AMDのLinuxグラフィックドライバーはおおむねよく動作していたが、この問題だけは何度も遭遇した例外だった

    • 自分はもう少し運が悪かった
      最近遭遇している問題は、サスペンドから復帰した後、ドライバーがWARNING: CPU: 12 PID: 11871 at drivers/gpu/drm/amd/amdgpu/../display/dc/dc_helper.c:100 generic_reg_update_ex+0x1d2/0x290 [amdgpu]の後に"[drm] scheduler comp_1.0.n is not ready, skipping"をログへ延々と吐き続けるというものだ
      https://gitlab.freedesktop.org/drm/amd/-/issues/3911
    • 自分も全体的には良い経験だが、デバイスがスリープしている状態で、モニターが接続されたThunderboltを外すと似た問題が起きる
      ただしノートPCなのでドライバー構成はかなり違い、PCIe GPUもない
  • amdgpu.koカーネルモジュールを保存して取り出し、Ghidraでデコンパイルしたうえで、dm_resumeのクラッシュ位置をカーネルソースの該当行にマッピングしたという部分は、デバッグの中でいつも一番好きな場面だ