ファミレスとかで作業をするため、安くて、持ち運びしやすいノートパソコンを買いました。
2022年発売モデルの11.6型の ASUS E210KA です。
CPU は Celeron N4500 、メモリ 4GB でストレージは eMMC 128GB 。希望小売価格5万で現時点の実売価格4万くらいの製品です。
当然、快適な Windows ライフを楽しめるとは思っていませんので、すぐに Linux を入れることにします。
試行錯誤
とりあえずインストール
比較的軽量なディストリビューションであればなんでもよかったのですが、 18.04 の頃に一度使ってみて結構好みだった Voyager をダウンロードしました。
Rufus で Live USB を作成し、 Secure Boot と Fast Boot を無効にしたノートパソコンにインストールを試みます。インストーラの案内に従って進み、パーティションの構成は手動で設定。
さあ、インストール。
と思いきや、 ext4 のフォーマットで失敗。
ここでのエラーはあまりないことだと思うので頭をひねりますが、ファイルシステムを XFS にしてやりなおしてみると問題なくフォーマットは完了しました。よくわからないながらインストールを進めますが、途中でエラーが発生。
インストールメディア、ドライブあるいはハードディスクの不良(と思われる) I/O エラーというメッセージ。
USB のイメージを疑う
Live USB を作成するときに Rufus を使いましたが、ソフト内で推奨とされている iso モードではなく dd モードでないとうまくいかないという記述をみつけたため、設定を変えて作成しなおしたりしてみましたが、相変わらず失敗します。
USB メモリも新しく購入した2つの製品で試してみたけどかわらず。
他のディストリビューションを試してみるも、やはり途中で失敗。オンラインでパッケージをダウンロードする方法、オフラインでイメージからファイルを展開する方法など試してみても失敗。
不良セクタを疑う
ext4 のフォーマットをコマンドで実行した際、 dmesg
には、このようなログが出力されていました。
$ sudo mkfs.ext4 /dev/mmcblk0p3
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 28310267 4k blocks and 7077888 inodes
Filesystem UUID: 56264c09-de04-4108-8579-f20a94120561
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872
Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: mkfs.ext4: Input/output error while writing out and closing file system
$ sudo dmesg | less
# 一部抜粋
[ 189.438279] mmc0: running CQE recovery
[ 189.439200] blk_print_req_error: 2 callbacks suppressed
[ 189.439203] I/O error, dev mmcblk0, sector 17807232 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.439212] buffer_io_error: 2 callbacks suppressed
[ 189.439214] Buffer I/O error on dev mmcblk0p3, logical block 3968, lost async page write
[ 189.439221] Buffer I/O error on dev mmcblk0p3, logical block 3969, lost async page write
[ 189.439224] Buffer I/O error on dev mmcblk0p3, logical block 3970, lost async page write
[ 189.439226] Buffer I/O error on dev mmcblk0p3, logical block 3971, lost async page write
[ 189.439229] Buffer I/O error on dev mmcblk0p3, logical block 3972, lost async page write
[ 189.439231] Buffer I/O error on dev mmcblk0p3, logical block 3973, lost async page write
[ 189.439233] Buffer I/O error on dev mmcblk0p3, logical block 3974, lost async page write
[ 189.439235] Buffer I/O error on dev mmcblk0p3, logical block 3975, lost async page write
[ 189.439242] Buffer I/O error on dev mmcblk0p3, logical block 3976, lost async page write
[ 189.439245] Buffer I/O error on dev mmcblk0p3, logical block 3977, lost async page write
[ 189.439483] mmc0: running CQE recovery
[ 189.440998] mmc0: running CQE recovery
[ 189.442480] mmc0: running CQE recovery
[ 189.443717] I/O error, dev mmcblk0, sector 17804672 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.443966] mmc0: running CQE recovery
[ 189.445121] mmc0: running CQE recovery
[ 189.446200] mmc0: running CQE recovery
[ 189.447339] mmc0: running CQE recovery
[ 189.448480] mmc0: running CQE recovery
[ 189.449580] mmc0: running CQE recovery
[ 189.450737] mmc0: running CQE recovery
[ 189.451908] mmc0: running CQE recovery
[ 189.453120] mmc0: running CQE recovery
[ 189.454307] mmc0: running CQE recovery
[ 189.455672] mmc0: running CQE recovery
[ 189.456834] mmc0: running CQE recovery
[ 189.457942] mmc0: running CQE recovery
[ 189.458864] I/O error, dev mmcblk0, sector 17804032 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.459151] mmc0: running CQE recovery
[ 189.460293] mmc0: running CQE recovery
[ 189.461475] mmc0: running CQE recovery
[ 189.462421] I/O error, dev mmcblk0, sector 17803776 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.462777] mmc0: running CQE recovery
[ 189.464327] mmc0: running CQE recovery
[ 189.465647] mmc0: running CQE recovery
[ 189.466663] mmc0: running CQE recovery
[ 189.467868] mmc0: running CQE recovery
[ 189.468989] mmc0: running CQE recovery
[ 189.470313] I/O error, dev mmcblk0, sector 17805952 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.470556] mmc0: running CQE recovery
[ 189.472022] mmc0: running CQE recovery
[ 189.473273] I/O error, dev mmcblk0, sector 17803520 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.473540] mmc0: running CQE recovery
[ 189.474644] mmc0: running CQE recovery
[ 189.475573] I/O error, dev mmcblk0, sector 17806592 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.475788] mmc0: running CQE recovery
[ 189.476691] I/O error, dev mmcblk0, sector 17806848 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.476924] mmc0: running CQE recovery
[ 189.478066] mmc0: running CQE recovery
[ 189.479010] I/O error, dev mmcblk0, sector 17804416 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.479270] mmc0: running CQE recovery
[ 189.480142] I/O error, dev mmcblk0, sector 17806976 op 0x1:(WRITE) flags 0x4800 phys_seg 128 prio class 2
[ 189.480389] mmc0: running CQE recovery
XFS でフォーマットしたあと、インストールが途中まで進みますがそのあと失敗するため、どこかに不良セクタがあるようにも見えます。
mkfs.ext4
には不良セクタにマークを付け、それを避けて使用することができるオプションがあるため、 badblocks
をかけてチェックしてみましたが不良セクタは検知できず。読み書きモードでも同様に検知できませんでした。
八方塞がりで、これはまな板にしかならないかな、と思い始めました。1
ASUS の eMMC CQE が原因
[ 189.438279] mmc0: running CQE recovery
ログのこっちのほうがキーだったみたいです。
詳しいことはわからないため完全に憶測となりますが、 eMMC のコントローラの Command Queue Engine が正常な動作をしないこと(?)、あるいは Linux の処理を異常と判断し修復しようとすること(?)のような感じで、 CQE を無効にするフラグをセットすることで問題は解消しました。
改めてインストール
ディストリビューションのインストール
まず、インストールしたい Live USB を挿し、起動します。
起動時に Try と Install を選択する必要がある場合は、 Try を選択しインストールが始まらないようにしておきます。
起動したら、下記コマンドを実行し CQE を無効にします。
$ sudo modprobe -r sdhci_pci
$ sudo modprobe -r sdhci
$ sudo modprobe sdhci debug_quriks=0x20000
$ sudo modprobe sdhci_pci
このあとインストーラを立ち上げてインストールを進めます。後述の作業のため、オンラインでアップデートが可能であっても利用しないほうがよいと思います。
インストールが完了しても再起動はしないでください。
永続化の設定
今は USB から起動していたため、 sdhci
モジュールの再読込で対応が可能でした。しかし eMMC 上の OS を起動しようとすると、 CQE 無効化前に eMMC にアクセスする必要があるためカーネルパニックを起こして起動しなかったり、起動してもすぐに使用できなくなります。
起動時のカーネルパラメータで CQE 無効フラグを追加することで一時的に起動することができるため、そのときに永続化の設定を行うこともできますが、せっかくなので USB からブートしている現環境で永続化を試みます。
パーティション構成は下記のとおりとします。
-
/dev/mmcblk0p1
:/boot/efi
-
/dev/mmcblk0p2
: swap -
/dev/mmcblk0p3
:/
chroot
を使用して、 eMMC 上にインストールした環境の initrd を更新し、起動時に CQE 無効の設定が生きるようにします。
$ sudo mount /dev/mmcblk0p3 /mnt
$ sudo mount /dev/mmcblk0p1 /mnt/boot/efi
$ sudo mount --rbind /dev /mnt/dev
$ sudo mount -t proc none /mnt/proc
$ sudo mount --rbind /sys /mnt/sys
$ sudo chroot /mnt
# echo "options sdhci debug_quirks=0x20000" >/etc/modprobe.d/sdhci-disable-cqe.conf
# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.2.0-20-generic
# lsinitramfs /boot/initrd.img-6.2.0-20-generic | grep cqe
etc/modprobe.d/sdhci-disable-cqe.conf
# exit
exit
$ sudo umount -l /mnt/sys
$ sudo umount /mnt/proc
$ sudo umount -l /mnt/dev
$ sudo umount /mnt/boot/efi
$ sudo umount /mnt
ブートパーティションのマウント先は、インストールしたディストリビューション、使用ブートローダなどによって異なる場合があります。
ディストリビューションによって update-initramfs
ではなく mkinitcpio
や dracut
を使うこともあります。 dracut
の場合は
$ sudo dracut -f --hostonly --no-hostonly-cmdline /boot/initramfs-linux.img
インストール時に、オンラインからパッケージのアップデートを有効にすると、 Live USB 上のカーネルバージョンと、 eMMC 上にインストールされたカーネルのバージョンが異なることでエラーが発生することがあります。その場合には /boot
に含まれている initrd の名前や /lib/modules
を参考に、オプションでカーネルバージョンの指定などが必要です。
様子見
ブートまわりの知識が乏しく、ちゃんとあっているかわからないため、再起動やカーネルの更新などを行いながら、問題なく動作するか様子を見ます。カーネル更新時には initrd の更新処理が行われるかも確認しておきます。
とりあえず、よくわからないながら動いています。
ちなみに、当初 Voyager Linux をインストールしてみましたが、どうも動作がもっさりとしているため EndeavourOS にしてみました。 Arch Linux 系はじめてだったので、ちょっと興味あったこともあり。
カーネル開発陣の動き
この件を検索すると Linux カーネルのパッチについてのメーリングリストがみつかりましたが、それが提案なのか、採択されたものかまでは追えていません。少なくとも Linux Kernel 6.3 のインストールイメージでも、この問題は発生しました。
該当する Bugzilla としてはこちらあたり。
-
ところで MyASUS で製品登録をすると「ASUS のあんしん保証」として自損を問わずどんな壊れ方でも“絶対サポート”らしいですが、これも適用範囲内なのでしょうかね? ↩