Ubuntu Weekly Recipe

第806回Ubuntu 24.04 LTSの開発版をVisionFive 2のM.2 NVMeストレージにインストールする

VisionFive 2はStarFive Technology製のRISC-Vシングルボードコンピューター(SBC)です。今回はこのVisionFive 2のM.2 NVMeストレージにUbuntuの最新開発版である24.04(noble)をインストールしてみましょう。

2種類存在するUbuntuインストーラー

VisionFive 2については、これまでにも次の回で紹介してきました。

これらの記事が公開された2023年3月時点では、UbuntuはまだVisionFive 2をサポートしていませんでした。しかしながらUbuntu 23.04の時点でプレインストールイメージが用意され、23.10からは普通のサーバー版と同じくLiveイメージが用意されM.2 NVMeにもインストールできるようになっています。24.04ではU-BootとKernelのVisionFive 2対応が進んできたため、Ubuntu固有の修正は少なくなるはずです。

今回はあと一月ほどでリリースされる予定のUbuntu 24.04 LTSの開発版をベースに、VisionFive 2にインストールする方法を紹介します。

さて、現時点でVisionFive 2向けのUbuntu用インストールイメージとしては、次の2種類が存在します。

  • プレインストールイメージ
  • Liveイメージ

プレインストールイメージとは、必要なカーネル・ルートファイルシステム等をひとつのイメージファイルにまとめたものです。ブートデバイスにこのイメージを書き込むだけで、それ以外のインストール手順は必要なくUbuntuが起動します。Raspberry PiやRISC-Vのような、ブート手順が標準化されていないことが多いSBCにおいて使われる手法です。ただし個々のSBCに決め打ちした設定になることが多く、また通常のUbuntuインストーラーほどインストール時の柔軟性はありません。

プレインストールイメージは、起動後にストレージ上のファイルシステムを拡大し、起動後にユーザーアカウントの設定を行うだけでインストールが完了します。それ以降の処理については、必要に応じて手動で設定するか、なにがしかの構成管理ツールを使うことになるでしょう。

Liveイメージは、通常のUbuntuでも採用している起動後にLive環境が立ち上がり、その中でUbuntuインストーラーが起動する方式です。ユーザーはインストーラーの指示に従って必要な設定を行い、インストールを完了します。通常のインストーラーで行えるような、ストレージデバイスの指定・ユーザーアカウントの作成・SSH鍵の設定などが行えます。インストーラーそのものはサーバー版のUbuntuと同じなので、cloud-initを利用した自動設定も可能です。

ただしLiveイメージの場合、⁠インストーラーの起動用」とは別に「インストール先のストレージ」が必要です。つまりVisonFive 2の場合はSDカード等から起動して、M.2 NVMeやUSBストレージにインストールすることになります。ちなみにNVMeやUSBストレージへのインストールは、Ubuntu 23.10からサポートされるようになりました。

実はArmやRISC-Vでは、各種OSのおける組み込みハードウェア対応をより共通化できるよう、Embedded Base Boot Requirements (EBBR) Specificationと呼ばれる起動シーケンスに関する標準インターフェースの定義が進んでいます。このEBBRに準拠したU-Boot等を使えるArmやRISC-Vのボードは、OS側はそのシーケンスの違いを意識することなく起動・インストールできるようになるわけです。Liveインストーラーは、基本的にこのインターフェースを使う形で実装されています。

これはUbuntuに限った話ではなく、U-Bootの最新版でもすでにEBBR対応が進んでおり、VisionFive 2も対応済みです。2024年の1月にはDebianのU-Bootのパッケージが修正され、VisionFive 2の対応が取り込まれましたし、VisionFive 2用のバイナリイメージを提供するu-boot-starfveパッケージが作成されるようになりました。このあたりの対応を取り込みたいために、今回はUbuntu 24.04 LTSの開発版イメージを使うことにします。

実際、UbuntuのLiveイメージもU-Bootから先の起動シーケンスについては、通常のサーバー版と同じくGRUBが起動し、そこからLive環境が起動し、その中でインストーラーが起動しています。インストール後もU-BootからUEFIの手法にしたがってGRUB(EFIアプリ)を起動し、GRUBメニューからカーネルが起動することになります。SBCではたまにめんどくさい手順が必要なカーネルの更新も、普通のUbuntuと同じ手順を踏めます。今後は、組み込みボード向けのLiveイメージ版のインストーラーが増えていくことになるでしょう。

ただしVisionFive 2が公式に提供しているU-Bootは、まだEBBRに対応していません。もしLiveイメージを使いたい場合は、U-BootオリジナルのコードをビルドするかUbuntuのU-Bootバイナリを使わないといけません。

ここまで説明した2種類のインストールイメージまとめるとそれぞれの違いは次のとおりです。

プレインストールイメージ
  • SDカードだけ用意すれば良いのでお手軽
  • 高速なM.2 NVMeを使うにはひと手間必要になる
  • SBCごとにインストーラーを用意しないといけない
  • VisionFive 2が提供するU-Bootをそのまま使える
Liveイメージ
  • インストール時の設定UIが通常のUbuntuと同じ
  • カーネルが認識できる任意の空のストレージをインストール先に指定できる
  • 対応しているSBCであればインストラーの共通化がかんたん
  • VisionFive 2の場合は、U-Bootの更新が必要

今回はVisionFive 2向けに両方の手順を紹介します。なお、ボードのリビジョンは1.3Bを前提としています[1]。その他の最新の手順はUbuntuの公式Wikiに記載されていますので、そちらも参考にしてください。

シリアルコンソールの接続

今回の手順はどちらもシリアルコンソールが必要になります。これはUbuntuで使っているカーネルが、まだオンボードのGPUに対応していないためです。そこでシリアルコンソールもあらかじめ準備しておいてください。具体的には本体以外に次のデバイスが必要になります。

  • 給電用のUSB-Cケーブル
  • USB-C経由のACアダプター(5V、最低3A以上)
  • 32GB以上のmicroSDカード
  • M.2 NVMe SSD(Liveイメージからインストールする場合)
  • Ethernetケーブル(ネットワーク接続が必要な場合)
  • シリアルコンソールケーブル

シリアルコンソールケーブルはいわゆる「USBシリアル」と呼ばれるもので大丈夫です。ただしVisionFive 2側は、GPIOピンヘッダーに接続しなくてはなりません。最近だとRaspberry Pi Debug Probeなども、Raspberry Pi用のデバッグに使えつつ、汎用のシリアルコンソールケーブルとしても使えるのでおすすめです。

接続方法はVisionFive 2のQuick Start Guide(PDF)「3.4.3 Using a USB to Serial Converter」と、Debug ProbeのドキュメントのThe Debug Probeにある図を参照してください。Debug Probe側のUART端子から出ている「TX」を、VisionFive 2側の「RX」に接続します。

図1 ピンの位置とDebug Probeの結線の色の関係。左上のRGPIO_OなディップスイッチがどちらもL側に設定されてる点にも注意する
図1

Debug ProbeをUSBに接続すると、dmesg上では次のように表示されるはずです。ttyACM0から/dev/ttyACM0を使えば良いことがわかります。

[1898871.717937] usb 1-1: new full-speed USB device number 25 using xhci_hcd
[1898871.868855] usb 1-1: New USB device found, idVendor=2e8a, idProduct=000c, bcdDevice= 1.01
[1898871.868859] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1898871.868861] usb 1-1: Product: Debug Probe (CMSIS-DAP)
[1898871.868863] usb 1-1: Manufacturer: Raspberry Pi
[1898871.868864] usb 1-1: SerialNumber: E6614103E7357C25
[1898871.921246] cdc_acm 1-1:1.1: ttyACM0: USB ACM device
[1898871.921270] usbcore: registered new interface driver cdc_acm
[1898871.921271] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

あとは/dev/ttyACM0に対してボーレート115200で、シリアルコンソールソフトウェアを起動します。このあたりは第684回のUbuntuからRaspberry Pi Picoを使うを参照してください。実はDebug Probeの中身はRaspberry Pi Picoなので、そちらで説明していることと中身はほぼ一緒なのです。Ubuntuでは/dev/ttyACM0のようにデバイスが見えますので、そちらにpicocomなどのソフトウェアからアクセスすることになります。

プレインストールイメージの使い方

プレインストールイメージの場合、VisionFive 2が提供するベンダー公式のU-Bootがそのまま使えます。第752回で一度更新手順を紹介していますが、この時(2023年3月頃)のファームより新しければどれでも問題ありません。購入直後だと古いままかもしれませんので、第752回を参考に更新しておいてください。

プレインストールイメージは次のURLからダウンロードできます。23.10のようなリリース済みのイメージは上のURLから、24.04のようなリリース前の開発版は下のURLからダウンロードしてください。

「RISC-V for StarFive VisionFive 2 preinstalled server image」をクリックすればダウンロードできるはずです。ダウンロードしたら今度はSDカードを用意して、PC側に接続し、次のように書き込みます。ここで/dev/sdXは環境に応じて変更してください

$ xzcat noble-preinstalled-server-riscv64+visionfive2.img.xz | sudo dd bs=1M conv=fsync of=/dev/sdX

書き込みが完了したらSDカードを抜去し、VisionFive 2に接続して電源を入れるだけです。シリアルコンソール上でVisionFive 2が起動し、しばらくしたら次のようなメッセージが表示されます。

ubuntu login: ubuntu
password: 「ubuntu」と入力
you are required to change your password immediately (administrator enforced).
changing password for ubuntu.
current password: 「ubuntu」と入力
new password: 新しいパスワードを入力
retype new password: 新しいパスワードを再入力

初期アカウントとパスワードはともに「ubuntu」となっています。初回ログイン時にパスワードの変更が求められるのでそれに従って対応してください。この操作を行うために、シリアルコンソールが必要となっています。

あとはごくごく普通のUbuntuサーバーですので、いつものようにパッケージをインストールしたりサービスを立ち上げると良いでしょう。前述のとおりGPUは未対応なので、HDMIディスプレイには何も表示されません。こちらは今後の課題です。

Liveイメージの使い方

Liveイメージの場合は、まずU-BootをU-Bootの最新版かもしくはUbuntuがビルドしたものに差し替えなくてはなりません。まずはその方法を説明しましょう。U-Bootの更新にはLinux環境が必要です。先ほどのプレインストールイメージでも良いですし、第752回のようにVisionFive 2が提供するsdcard.imgでも良いでしょう。

もしプレインストールイメージを使うなら、/usr/lib/u-boot/starfive_visionfive2/以下に書き込むためのイメージが用意されているのでそれをそのまま使います。それ以外の環境ではリポジトリからバイナリが含まれるファイルをダウンロードすることになるでしょう。ここでは後者を採用します。

$ wget -r -nd --no-parent -A 'u-boot-starfive_*_riscv64.deb' \
  http://ports.ubuntu.com/ubuntu-ports/pool/universe/u/u-boot/
$ mkdir uboot
$ dpkg-deb -x $(ls -1 u-boot-starfive_*_riscv64.deb | tail -n1) uboot/
$ ls uboot/usr/lib/u-boot/starfive_visionfive2/
u-boot-spl.bin.normal.out  u-boot.bin  u-boot.itb  uboot.elf

リポジトリからu-boot-starfiveで始まるパッケージを取得し、そこからdpkg-debコマンドでパッケージの中身を展開します。今回使用するのはSPLu-boot-spl.bin.normal.outとU-Boot本体u-boot.itbの2ファイルです[2]。それをVisionFive 2側にコピーしておいてください。

次にVisionFive 2側で書き込むパーティションを確認します。

$ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00001000 "spl"
mtd1: 00010000 00001000 "uboot-env"
mtd2: 00400000 00001000 "uboot"
mtd3: 00a00000 00001000 "reserved-data"

ここでsplとなっているところにSPLを、ubootとなっているところにU-Boot本体を書き込みます。今回のケースだと次のように書き込むことになるでしょう。sdcard.imgの場合は「sudo」は不要です。

SPLの書き込み:
$ sudo flashcp -v uboot/usr/lib/u-boot/starfive_visionfive2/u-boot-spl.bin.normal.out /dev/mtd0
Erasing blocks: 35/35 (100%)
Writing data: 137k/137k (100%)
Verifying data: 137k/137k (100%)

U-BOot本体の書き込み:
$ sudo flashcp -v uboot/usr/lib/u-boot/starfive_visionfive2/u-boot.itb /dev/mtd2
Erasing blocks: 255/255 (100%)
Writing data: 1016k/1016k (100%)
Verifying data: 1016k/1016k (100%)

一度sudo reboot等で再起動して、U-bootが問題なく起動することを確認してください。ちなみにUbuntu側の手順としてはSPL/U-Bootの起動ログが出たあたりでEnterキーを連打し、起動を中断して次のように環境変数領域をリセットすることが求められています。

Hit any key to stop autoboot:  0

StarFive # env default -f -a
## Resetting to default environment
StarFive # env save
Saving Environment to nowhere... not possible

しかしながら上記の最後のメッセージあるように、環境変数をうまく保存できませんでした。一応、この対応がなくても問題なく起動できているようです。もしうまくUbuntuを起動できないようなら、env saveがうまく動くように既存の環境変数等の調査を行ってみてください。

いずれにせよこれでVisionFive 2側の準備は完了です。次にLiveイメージ用のSDカードとそのイメージを準備します。こちらもリリース版と開発版でURLが異なります。

Liveイメージ版は「RISC-V server install image」をクリックするとダウンロードできます。ただし開発版はたまにビルドに失敗しているようなので、もし存在しなければひとつ上のディレクトリに移動して、いくつかのサブディレクトリを確認すると良いでしょう。

ダウンロードしたファイルは次のようにSDカードに書き込みます。ここで/dev/sdXは環境に応じて変更してください

$ xzcat noble-preinstalled-server-riscv64+visionfive2.img.xz | sudo dd bs=1M conv=fsync of=/dev/sdX

書き込みが完了したらSDカードを抜去し、VisionFive 2に接続して電源を入れるだけです。シリアルコンソール上でVisionFive 2が起動し、少し待つとGRUB画面が表示されるはずです。そのまま放置するとUbuntuの起動ログが表示されます。

もし起動時に次のようなログが出て停止する場合は、U-Bootが古いままです。Ubuntu版のU-Bootへの差し替えをもう一度実施してみてください。

EFI stub: Booting Linux Kernel...
Unhandled exception: Store/AMO access fault
EPC: 00000000fff47a98 RA: 00000000fff8684a TVAL: 0000000040000000
EPC: 0000000040201a98 RA: 000000004024084a reloc adjusted

SP:  00000000ff733910 GP:  00000000ff735e00 TP:  0000000000000001
T0:  0000000042263381 T1:  0000005643534952 T2:  0000004005435352
S0:  0000000040000000 S1:  0000000040000000 A0:  0000000040000000
A1:  00000000f7e76000 A2:  00010d60106f5a4d A3:  0000000000200000
A4:  000000000236e000 A5:  0000000000000000 A6:  0000000000000002
A7:  0000000000000000 S2:  000000000236e000 S3:  00000000ff733ad8
S4:  0000000002263400 S5:  0000000000200000 S6:  00000000f7e76000
S7:  0000000000000000 S8:  000000000000001f S9:  00000000fe4603f8
S10: 0000000000000000 S11: 00000000fe2f72d8 T3:  0002506400004550
T4:  0000000000000000 T5:  020600a000000000 T6:  0000000040000000

Code: b383 0385 be03 0405 be83 0485 bf03 0505 (e110)
UEFI image [0x00000000fe450000:0x00000000fe714fff] '/efi\boot\bootriscv64.efi'
UEFI image [0x00000000f7e76000:0x00000000fa1e3fff]

無事に起動が開始するといつものカーネル起動ログのメッセージが表示されます。ただし一度以下のタイミングで停止するようです。

[   15.493002]  mmcblk1: p1 p2 p3 p4 p5
48+0 records in
48+0 records out

ここで止まっても再起動せず辛抱強く待ち続けましょう。数分すると何事もなかったかのように起動を続けます。最終的には次のようにインストーラーの画面が起動します。

図2 シリアルコンソールの場合、どの方法でインストールを続けるかが問われる。ネットワークに繋がっているなら「View SSH instructions」がおすすめ
図2

Ubuntuサーバーのインストーラーは、エスケープシーケンスなどを駆使して画面を装飾しています。これは普通のディスプレイなら問題ないのですが、シリアルコンソールのような制限された端末だとうまく表示されないことがあります。そこで上記の図では「従来の表示(rich mode)で続けるか」⁠シンプルな表示(basic mode)で続けるか」⁠SSH経由で操作するか」を選択しているのです。

もしそのデバイスにネットワーク到達可能な別のマシンがあるなら、SSH経由の操作がおすすめです。もしないなら「basic mode」を選ぶと良いでしょう。

図3 SSHを選ぶとログイン方法が表示される
図3
図4 SSHでログインしたあとはいつものサーバーのインストール画面だ
図4

SSH経由のインストールの場合、最初の言語選択で「日本語」を選べます。これは2024年3月末時点では、インストーラーのUIが日本語になるわけではなく、日本語キーボード・日本語ロケール・日本のミラーサーバーを選択できるという意味での日本語です。サーバー用途なら「English」を選択しておくのもありでしょう。

図5 インストール先の選択でM.2 NVMe SSDが表示される
図5

インストール先の選択では、M.2 NVMe SSDが認識されたら、上記のようにインストール先の候補に登場します。あとは普通にUbuntuをインストールするだけです。インストールにはそこそこの時間がかかりますが、最後に「Reboot Now」を選択して準備完了です。

再起動したら、一般的なUbuntu環境が立ち上がることでしょう。ちなみに再起動後はSDカードは取り外してもOKです。

なおVisionFive 2では、2個のLANコネクタがともにDHCPを使う形で有効化されており、起動時に両方のアドレスがアサインされるまで2分ほど待ってしまいます。片方しか使わないなら、次のようにもう片方をオプション扱いにしてしまいましょう。

$ cat<<'EOF' | sudo tee /etc/netplan/90-disable-lan.yaml
network:
    ethernets:
        end1:
            dhcp4: true
            optional: true
    version: 2

どちらもオプション扱いにするでもOKですし、もし「どちらか片方がDHCPでアドレスを割り当てられるまで待ちたい」のであれば、次のようにsystemd-networkdの設定を変えると良いでしょう。

$ cat<<'EOF' | sudo tee /etc/systemd/system/systemd-networkd-wait-online.service.d/override.conf
[Service]
ExecStart=
ExecStart=/lib/systemd/systemd-networkd-wait-online --any

Ubuntuでのパフォーマンス

試しに第752回/第753回と同じように性能を評価してみましょう。ちなみに3月25日時点で、RISC-Vカーネルのバージョンは6.5です。riscv64アーキテクチャー以外は6.8カーネルに移行済みなので、RISC-Vも24.04のリリースまでには6.8になるのではないかと予想されます。ただ、すでにKernel Freezeを迎えており、また6.5にとどまっている理由が不明であるため、まだ余談を許さないところです。

さて、まずはfioによるストレージアクセスの結果から見ていきましょう。手順は上記記事を参考にしてもらうとして、今回は結果だけ並べていきます。

$ jq -r '.jobs[] | [.jobname, if .read.bw > 0 then .read.bw, .read.iops | round
    else .write.bw, .write.iops | round end] | @tsv' \
    results.json | column -t --table-columns JOB,KB/s,IOPS --table-right KB/s,IOPS
JOB                   KB/s   IOPS
SEQ1MQ8T1-Read      294958    288
SEQ1MQ8T1-Write     323674    316
SEQ128KQ32T1-Read    57427    449
SEQ128KQ32T1-Write  345585   2700
RND4KQ32T16-Read    322216  80554
RND4KQ32T16-Write   166059  41515
RND4KQ1T11-Read      37843   9461
RND4KQ1T1-Write      47014  11754

SDカードで計測したときと10倍以上性能が違いますね。使用したSSDはCrucial P3 Plus 1TB(PCIe Gen 4 x4)です。ただカタログスペックよりはだいぶ遅く、特に読み込みが極度に悪いところも見受けられます。今回、CPU/SSDともにヒートシンクなしで使っているので、そのあたりも影響しているかもしれません。

次にsbc-bench.shの結果です。

$ sudo ./sbc-bench.sh -c
(略)

Results validation:

  * Measured clockspeed not lower than advertised max CPU clockspeed
  * No swapping
  * Background activity (%system) OK
  * No throttling

Memory performance
memcpy: 789.1 MB/s
memset: 752.5 MB/s

7-zip total scores (3 consecutive runs): 3934,3937,3929, single-threaded: 1119

OpenSSL results:
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-128-cbc      22559.47k    28150.08k    30010.03k    30549.67k    30703.62k    30681.77k
aes-128-cbc      22546.85k    27754.82k    29997.06k    30187.86k    30689.96k    30670.85k
aes-192-cbc      20592.16k    24927.94k    26438.49k    26852.01k    26962.60k    26951.68k
aes-192-cbc      20308.36k    24940.46k    26119.77k    26529.11k    26662.23k    26629.46k
aes-256-cbc      18831.56k    22421.14k    23615.06k    23942.83k    24040.79k    24018.94k
aes-256-cbc      18754.43k    22439.06k    23625.47k    23947.26k    23759.53k    24018.94k

Full results uploaded to https://sprunge.us/p0XxJY


Results validation:

  * No mismatch between advertised and measured max CPU clockspeed
  * Background activity (%system) OK
  * No throttling

Memory performance
memcpy: 861.3 MB/s
memset: 758.3 MB/s

7-zip total scores (3 consecutive runs): 4028,4127,4016, single-threaded: 1179

OpenSSL results:
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-128-cbc      23357.03k    29324.50k    31249.32k    31819.78k    31976.11k    31943.34k
aes-128-cbc      23628.61k    29400.47k    31308.12k    31830.70k    31973.38k    31954.26k
aes-192-cbc      20945.81k    25931.18k    27408.04k    27808.43k    27915.61k    27885.57k
aes-192-cbc      21130.03k    25807.42k    27401.56k    27799.55k    27918.34k    27891.03k
aes-256-cbc      19514.63k    23093.23k    24370.09k    24687.62k    24775.34k    24767.15k
aes-256-cbc      19514.07k    23201.19k    24367.02k    24687.96k    24775.34k    24767.15k

Full results uploaded to http://ix.io/4q00

前回の比較表にUbuntuを加えると次のようになります。こちらはほぼ一緒です。

Device Clock Kernel 7-zip
multi/single
AES memcpy memset
RasPi 3B+ 1.4GHz 4.14 3240/914 36600 1130 1530
RasPi 4 1.8GHz 5.10 5790/1769 36260 2330 3120
VF2 Debian 1.5GHz 5.15 4090/1194 6820 860 760
VF2 Ubuntu 1.5GHz 5.15 4060/1179 24770 860 760
VF2 noble 1.5GHz 6.5 3930/1119 24020 790 750

上記の数字は結果の一番最後にあるURLの、末尾に書かれている表を参考にしています。

これまでと比べると性能が若干落ちているようにも見受けられます。これはベンダーがVisionFive 2用に作り込んでいるカーネルから、Ubuntuの一般的なカーネルに変更したことが影響しているかもしれません。また一般的なUbuntuでは、裏で様々なサービスが動いているのも一因でしょう。

ちなみにUbuntuはMOTDでいろいろな情報を表示しています。このためSSHログイン時にキャッシュが効いていないと必要以上に時間がかかるようです。気になるようなら第755回のUbuntuにおけるMOTDの仕組みのすべてを参考に、各種情報表示をオフにしておくと良いでしょう。それでも起動後の初回ログインで時間がかかる場合は、ssh.socketによるSSHサーバーの起動時間が問題かもしれません。もしその場合は、次のように常時起動するようにしておくことで改善します。

$ sudo systemctl disable --now ssh.socket
$ sudo rm -f /etc/systemd/system/ssh.service.d/00-socket.conf
$ sudo rm -f /etc/systemd/system/ssh.socket.d/addresses.conf
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now ssh.service

残念ながらGPU未対応であるため、Ubuntuデスクトップを使うことはできませんし、性能的にもギリギリ動くかどうかといったところです。しかしながらちょっとしたサーバー用途であれば十分な性能を持っています。ぜひおうちに一台ぐらいRISC-Vサーバーを用意してみてはいかがでしょうか。

おすすめ記事

記事・ニュース一覧