スポンサーリンク

Hyper-V Ubuntu で GNOME の freeze を防止する

forest_oil_painting
記事内に広告が含まれています。
スポンサーリンク

はじめに

Hyper-V 仮想マシンで使用している Ubuntu で、GNOME が freeze する現象が起きました。

原因が分からず回り道しましたが、結論としては hyperv_fb を使用せずに hyperv_drm で提供される hyperv_drmdrmfb フレームバッファデバイスを使用する事で解消できました。

以下、経緯について記載します。

スポンサーリンク

私の Hyper-V の使い方 (Path through disk)

私は Windows11 Hyper-V で Ubuntu (22.04 LTS、23.04) を使用しています。SATA 接続の SSD 2基を Path through で Hyper-V に接続し、Hyper-V 仮想マシンとして、また実機として、両方で起動できるようにしています。詳細については、以下の過去記事 (はてなブログ) を参照ください。

古い PC で UEFI ではなく BIOS でしたので上記では Hyper-V 第一世代を使用していますが、今はUEFI ですので第二世代で仮想マシンを作成しています。

仮想マシンとして Windows11 上で動作させると共に、CPU やメモリをフルに使いたい場合には UEFI から実機で起動させて使用しています。

Hyper-V Ubuntu でログイン後に GNOME が freeze

そのような中で、Hyper-V で動作させている Ubuntu で GUI でログインした直後に GNOME が操作不能となる現象が発生しました。再現性ありです。

状況としては、

  • Ubuntu 22.04 LTS と Ubuntu 23.04 の両方で発生
  • kernel のアップデート後に発生し、古い kernel では正常に動作する
  • linux-image-5.19.0-41-generic までは正常に動作
  • Ubuntu 22.04 LTS では linux-image-5.19.0-42-generic 以降、Ubuntu 23.04 では linux-6.2.0-20-generic で発生
  • gdm3 のログイン画面までは正常に動作し、仮想端末への切替 (Ctrl + Alt + F2 等) も可能
  • ログインして GNOME の画面が表示されると、マウスもキーボードも使用できない

という具合でした。

事前に Windows11 から Hyper-V Ubuntu へ ssh でログインした状態で gdm3 でログインすると、GNOME は操作不能ですが、ssh でログインした端末では正常に動作していました。dmesg でも異常を示すログは見当たらず、高負荷なソフトウェアも見当たりませんでした。Hyper-V のメニューからシャットダウンを選択すると停止できるので、kernel はちゃんと動いているようでした。

実機で起動させると linux-image-5.19.0-42-generic 以降の kernel でも問題なく使用する事ができました。また、Virtualbox では GNOME の freeze は発生しませんでした。

とりあえず、linux-image-5.19.0-41-generic を残しておき、grub のメニューからこちらを選択して起動すれば問題なく使えました。とはいえ、不具合を放置したくなかったので、原因と対策を調べてみました。

同様の現象が発生していないか調査

同様の現象がないかをググってみると、以下の二つのページが見つかりました。

とはいえ、回避方法は古い linux-image-5.19.0-41-generic を使って、という事で、原因に繋がるような情報は得られませんでした。

twitter で検索すると、qiita のページが紹介されていました。

Ctrl + Alt + F3 -> Ctrl + Alt + F1 で gdm3 の画面に戻ると一時的に操作できるようになりますが、少し時間が経過するとまた freeze 状態になりますので、こちらも根本的な対策にはなりませんでした。

原因調査

Hyper-V 上で動作する Ubuntu では、hyperv_fb というフレームバッファデバイスを使用して、CUI / GUI が表示されます。また、Wayland ではなく Xorg が使用されています。(Wayland を選択できないようになっています)

画面表示の問題ですので、おそらくフレームバッファ周りの問題かと推測し、原因を調べてみました。

lsmod, dmesg, kernel config

新旧の kernel で起動して ssh でログインし、lsmod (使用されている module)、dmesg (仮想ハードウェアの認識状況)、kernel config (module の作成条件) を比較しましたが、dmesg の表示順が若干ズレている程度で、大きな違いはありませんでした。

linux-source-5.19.0-41 と linux-source-5.19.0-43 の差分

linux-source-5.19.0-43 の changelog から Hyper-V 周りの変更点を抜き出してみました。

$ cat changelog | grep -e ^linux -e hyperv -e hv_
linux-hwe-5.19 (5.19.0-43.44~22.04.1) jammy; urgency=medium
linux-hwe-5.19 (5.19.0-42.43~22.04.1) jammy; urgency=medium
    - hv_netvsc: Fix missed pagebuf entries in netvsc_dma_map/unmap()
    - hv_netvsc: Allocate memory in netvsc_dma_map() with GFP_ATOMIC
linux-hwe-5.19 (5.19.0-41.42~22.04.1) jammy; urgency=medium
linux-hwe-5.19 (5.19.0-40.41~22.04.1) jammy; urgency=medium
    - powerpc/hv-gpci: Fix hv_gpci event list
    - video: hyperv_fb: Avoid taking busy spinlock on panic path
    - x86/hyperv: Remove unregister syscore call from Hyper-V cleanup
(...snip...)

5.19.0-40 で変更はありましたが、5.19.0-41 と 5.19.0-42、5.19.0-43 の間では hyperv_fb に変更はありませんでした。hv_netvsc の変更箇所はありますが、Network 周りの変更で、画面表示には直接関係ありませんので影響はないかと思います。

kernel source を diff で差分を取っても、hv_netvsc 以外に Hyper-V 周りの違いはありませんでした。

hyperv_fb を blacklist に追加して使用しないようにする -> 解消

hyperv_fb の修正もなく、module も同じように読み込まれているので、原因が分からず手詰まりとなりました。

Virtualbox の Ubuntu 22.04 LTS では linux-image-5.19.0-42-generic 以降でも問題なく起動できていた事もあり、hyperv_fb にトラブルの原因があるのではないかと考えて、これを使用しないで起動できるか試してみました。ArchWiki に設定例が載っていました。

linux kernel の 起動オプションに module_blacklist を追加します。grub の GRUB_CMDLINE_LINUX_DEFAULT に設定します。

$ cat /etc/default/grub | grep -e module_blacklist
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash module_blacklist=hyperv_fb"
$ sudo update-grub

この条件で起動すると、linux-image-5.19.0-42-generic 以降の kernel でも正常に GNOME を動作させる事ができました。

$ cat /proc/fb
0 hyperv_drmdrmfb
$ sudo dmesg -t | lv
(...snip...)
hv_vmbus: registering driver hyperv_drm
hyperv_drm 5620e0c7-8062-4dce-aeb7-520c7ef76171: [drm] Synthvid Version major 3, minor 5
Console: switching to colour dummy device 80x25
[drm] Initialized hyperv_drm 1.0.0 2020 for 5620e0c7-8062-4dce-aeb7-520c7ef76171 on minor 0
Console: switching to colour frame buffer device 128x48
hyperv_drm 5620e0c7-8062-4dce-aeb7-520c7ef76171: [drm] fb0: hyperv_drmdrmfb frame buffer device
(...snip...)

hyperv_fb の代わりに hyperv_drm モジュールが使用されて、hyperv_drmdrmfb というフレームバッファデバイスが有効になります。

Ubuntu 23.04 では、Wayland も選択・使用できるようになりました。

Hyper-V Ubuntu 23.04 Wayland で起動

hyperv_drm の提供する hyperv_drmdrmfb フレームバッファデバイスは、linux-image-5.19.0-16 で追加されたようです。

$ cat changelog | grep -e ^linux -e hyperv-drm | lv
(...snip...)
linux (5.19.0-16.16) kinetic; urgency=medium
    - drm/hyperv-drm: Include framebuffer and EDID headers
(...snip...)

linux の fbdev は obsolete?

古い情報ですが、linux の fbdev はメンテナンスされていない状態との記事を見つけました。

fbdevフレームワークは保守のみ行われている状態であり、すべての新しいディスプレイドライバーはDRMフレームワークで作成するよう促しています。

ここ数年DRMインターフェースは改良が施され、小型デバイスでもfbdevドライバーの代わりにDRMドライバーを利用できるようヘルパーインターフェースの追加も行われています。
またDRMは、完全なfbdevエミュレーション機能の提供も提案しています。

https://kledgeb.blogspot.com/2016/12/linux-kernel-3-fbdevlinux-kernel.html

また、blacklist には vesafb 以外は使用されないような記述もありました。

$ cat /etc/modprobe.d/blacklist-framebuffer.conf
# Framebuffer drivers are generally buggy and poorly-supported, and cause
# suspend failures, kernel panics and general mayhem.  For this reason we
# never load them automatically.
(...snip...)
blacklist sstfb
blacklist tdfxfb
blacklist tridentfb
#blacklist vesafb
blacklist vfb
blacklist viafb
blacklist vt8623fb
blacklist udlfb

Framebuffer drivers are generally buggy and poorly-supported, and cause suspend failures, kernel panics and general mayhem. For this reason we never load them automatically.

フレームバッファ ドライバは一般にバグが多く、サポートが不十分であり、サスペンドの失敗、カーネル パニック、および一般的な混乱を引き起こします。このため、それらを自動的にロードすることはありません。

/etc/modprobe.d/blacklist-framebuffer.conf

ここからは推測になりますが、linux-image-5.19.0-41-generic と 42-generic の間で、fbdev の 修正がありました。

diff -ur linux-source-5.19.0-41/drivers/video/fbdev/core/fb_defio.c linux-source-5.19.0-43/drivers/video/fbdev/core/fb_defio.c
--- linux-source-5.19.0-41/drivers/video/fbdev/core/fb_defio.c  2022-08-01 06:03:01.000000000 +0900
+++ linux-source-5.19.0-43/drivers/video/fbdev/core/fb_defio.c  2023-05-22 22:39:09.000000000 +0900
@@ -313,7 +313,7 @@
 }
 EXPORT_SYMBOL_GPL(fb_deferred_io_open);

-void fb_deferred_io_cleanup(struct fb_info *info)
+void fb_deferred_io_release(struct fb_info *info)
 {
        struct fb_deferred_io *fbdefio = info->fbdefio;
        struct page *page;
@@ -327,6 +327,14 @@
                page = fb_deferred_io_page(info, i);
                page->mapping = NULL;
        }
+}
+EXPORT_SYMBOL_GPL(fb_deferred_io_release);
+
+void fb_deferred_io_cleanup(struct fb_info *info)
+{
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
+       fb_deferred_io_release(info);

        kvfree(info->pagerefs);
        mutex_destroy(&fbdefio->lock);
diff -ur linux-source-5.19.0-41/drivers/video/fbdev/core/fbmem.c linux-source-5.19.0-43/drivers/video/fbdev/core/fbmem.c

--- linux-source-5.19.0-41/drivers/video/fbdev/core/fbmem.c     2023-04-19 02:39:34.000000000 +0900
+++ linux-source-5.19.0-43/drivers/video/fbdev/core/fbmem.c     2023-05-22 22:39:09.000000000 +0900
@@ -1451,6 +1451,10 @@
        struct fb_info * const info = file->private_data;

        lock_fb_info(info);
+#if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
+       if (info->fbdefio)
+               fb_deferred_io_release(info);
+#endif
        if (info->fbops->fb_release)
                info->fbops->fb_release(info,1);
        module_put(info->fbops->owner);

この変更により、hyperv_fb が正常に動作しなくなったのではないでしょうか。

どちらにしても、hyperv_drm モジュールでもフレームバッファデバイスの機能が提供されますので、今後は hyperv_fb を使用せず、hyperv_drm モジュールを使用した方が良いかと思います。

まとめ

Hyper-V 仮想マシンの Ubuntu で GNOME が freeze する現象が発生しました。フレームバッファデバイスとして hyperv_fb ではなく hyperv_drm を使用する事で、freeze せずに正常に動作するようになりました。

今回のトラブルは、再現性はあったものの dmesg や kernel source から原因を見つける事が出来ず、かなり回り道して原因に辿り着きました。

同様のトラブルに遭った方の参考になれば幸いです。

今回のアイキャッチ画像

林の中を油絵調で生成しました。自然の多い環境で幼少期を過ごしたので、今の住まいの近くは便利であるものの、少々息苦しく感じる事が多いです。

コメント

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