第505回の「オープン規格の新しい命令セットアーキテクチャRISC-V入門 ツールチェインを用意する」ではRISC-Vシミュレーターであるspikeを使ってRISC-Vバイナリを実行しました。今回はRISC-V対応QEMUを使って、RISC-Vの仮想マシン上でDebianを起動してみましょう。
ツールチェインとDebianのRISC-V対応状況
RISC-V対応のLinuxシステムを作るためには、単にコンパイラがRISC-Vに対応しているだけではなく、そのコンパイラを用いてカーネルやユーザーランドの各種ツールのRISC-Vバイナリを作る必要があります。さらに実機がない場合は、QEMUのような仮想マシンエミュレーターも必要です。spikeを使ってカーネルを実行することは可能ではありますが、今回は他のアーキテクチャーと同様にQEMUを使います。
2020年1月時点で、Linuxシステムを構築するために最低限必要なツールのほとんどがRISC-Vに対応しています。少なくとも次のバージョンであればRISC-VベースのLinuxシステムを構築することが可能です。
- binutils:2.28以上
- GCC:7.0以上
- glibc:2.27以上
- Linux:4.19以上
- QEMU:2.12以上
- dpkg:1.19.0.5以上
- U-Boot:2018.11以上
そしてこれらはすべて、最新のDebianにも取り込まれています。よってDebianのルートファイルシステムであれば、比較的簡単に構築できるのです。
もちろん登場したばかりのアーキテクチャーであるため、新しければ新しいほど安定して動く可能性が高くなります。またLinuxシステムとして使うためには当然のことながら上記以外にも必要なソフトウェアがたくさんあります。これらも必要に応じて順次RISC-V対応が行われていくことでしょう。
Debianでは公式でサポートしているCPUアーキテクチャー(やカーネル)以外にもPorts(移植版)と呼ばれる公式ではないサポートアーキテクチャーが存在します。公式リポジトリに存在するパッケージは、Ports向けのアーキテクチャでビルドされ、Debian Ports用のリポジトリで公開されるのです。このため、Portsにあげられているアーキテクチャーであればapt経由でパッケージをインストールできます。
RISC-V向けのアーキテクチャーとしては「riscv64」がPortsに登録されています。これはRISC-Vで言うところの「RV64GCU」であり「RV64IMAFDCU」の省略形です。第505回の「RISC-Vの拡張性」で取り上げたように64ビットアーキテクチャーの基本整数・整数の乗算除算・アトミック・単精度の浮動小数点・倍精度の浮動小数点それぞれの命令と、16ビット幅の命令をサポートしていることがわかります。最後のUは「The RISC-V Instruction Set Manual」の「Volume II: Privileged Architecture」に記載があるように、ユーザーモードをサポートしていることを意味します。
残念ながらUbuntuはRISC-Vをサポートしていません。もし今後サポートすることになるとしても、ricsv64がDebianの公式サポートアーキテクチャーになることが前提となるでしょう。riscv64ではまだビルドできないソフトウェアもそれなりにあることから、何か大きな力が働かない限りは、当面はUbuntuでサポートすることはなさそうです。
ただしUbuntu上でRISC-Vのバイナリをビルドしたり、QEMUでRISC-V版のDebianを動かすことは可能です。そこで今回はUbuntu上で、Debianイメージの作成と起動までを説明します。
構築環境の準備
Ubuntu上でRISC-V環境を構築するためにはUbuntu 19.10以降が必要です。これはQEMU上でRISC-Vを動かすためのファームウェアとして「OpenSBI」を使用しており[1]、このOpenSBIのパッケージが19.10からしか提供されていないためです。またQEMU自身も18.04のバージョンだと少し古いのでRISC-Vのバイナリをうまく動かせません。もちろんOpenSBIやQEMUの最新版を手動でインストールしても良いのですが、それよりはより新しいUbuntuを用意したほうが楽でしょう。
今回はより新しい環境を求めて、2020年4月にリリース予定のUbuntu 20.04 LTSの開発版を使うことにします。ただし今回紹介する手順は19.10でも動くことを確認済みです。
20.04を実機にインストールしても良いのですが、いかんせん開発版であることから、仮想マシン上にインストールしたほうが安心です[2]。そこで第590回の「Windows/macOS/Linuxで使える仮想マシン管理ツール『multipass』」を使用しましょう。multipassならUbuntuだけでなくWindowsやmacOSでも使えますし、すぐに20.04の実行環境を用意できます。
まずはmultipassをインストールします。
ちなみに第590回で紹介したあと、2019年12月に初の正式版である1.0.0がリリースされました。標準で作成されるユーザーが「multipass」から「ubuntu」になるなど、細かいところに変更はありますが、原則として第590回で紹介した使用方法がそのまま使えるはずです。
次に20.04のインスタンスを「riscv」の名前で作成します。
ルートファイルシステムを作る都合上、ストレージのサイズは40GBと多めにとっています。また、仮想マシン上でRISC-VのQEMUイメージを起動することから、メモリーも4GBに設定しておきました。
しばらく時間が必要ですが、無事にインスタンスが起動したらログインしておきましょう。
ここから先の手順はすべて、riscvインスタンス内で実行したものとします。
RISC-Vのルートファイルシステムの作成
まずはルートファイルシステム構築に必要なパッケージをインストールしておきましょう。
debootstrapはDebianのベースシステムを構築するためのツールで[3]、debian-ports-archive-keyringはDebian Ports用のリポジトリを検証するための公開鍵です。
qemu-user-staticとbinfmt-supportは、構築したルートファイルシステムでRISC-Vバイナリを実行するためにインストールしています。
次にルートファイルシステムを作成します。
「--keyring
」では先ほどインストールしたPorts用のリポジトリ鍵を指定しています。さらに「--include
」でルートファイルシステムにPorts用のリポジトリ鍵を含むパッケージをインストールしています。
ちなみに今回はコード名にunstableを指定しています。Ports向けリポジトリで他に指定できるのはexperimentalとPorts固有のテスト環境であるunreleasedのみです。そのためタイミングが悪いと、特にたまたま依存関係を満たせない変更が行われた場合などに、構築に失敗することがあります。たとえば2020年1月18日時点では、isc-dhcp-clientの4.4.1-2がlibdns-export1104とlibisc-export1100に依存しているものの、これらを提供するbind9の最新版である1:9.11.14+dfsg-3までにおいて、それぞれlibdns-export1107とlibisc-export1104になってしまったために、isc-dhcp-clientをインストールできないという問題がありました。
もしうまくルートファイルシステムを作れないようならsnapshot.debian.orgのリポジトリを使うと良いでしょう。RISC-Vだと少なくとも2019年12月19日時点のリポジトリだと問題はありませんでした[4]。
特定の日付のリポジトリを使うなら、次のように最後の引数にあるリポジトリURLを変更します。
ただしこの場合、最新のパッケージを導入できません。ルートファイルシステム構築後に「/etc/sources.list
」に両方のリポジトリを書くなど、なんらかの対応を行っておきましょう。具体的な手順は後ほど説明します。
この時点でルートファイルシステムのサイズは300MiB弱程度のようです。
ルートファイルシステムを構築したら、そのルートファイルシステムにchrootし、追加の設定を行います。
まずはリポジトリデータのアップデートです。特にsnapshot.debian.orgを使用して構築したのなら、Portsのリポジトリも指定してパッケージを更新しておいたほうがいいかもしれません。
ネットワーク設定が空なので、QEMUで動かした時のためにDHCPでアドレスを取得できるようにしておきます。
次にアカウントを作成しておきましょう。
rootアカウントのパスワードはロックされています。管理者権限に昇格できるよう、sudoパッケージをインストールして、先ほど作成したアカウントをsudoグループに追加しておきます。あくまでテスト用と割り切るなら、passwdコマンドでrootアカウントのパスワードを設定して、rootアカウントのまま生活する方法もあります。
QEMU上だとhvc0はttyS0と同じデバイスになるため、hvc0側のgettyの起動を抑制しておきます。
カーネルとブートローダーをインストールして、ブートローダーの設定も行っておきましょう。
カーネルのインストール時に次のようなエラーが大量に表示されるかもしれません。
どうやらこれはinitramfs-toolsの不具合のようです。とりあえずパッケージに組み込まれているinitramfsをそのまま使うのであれば実害はないはずなので、現時点では無視してください[5]。
ブートローダーはU-Bootを使います。そこで次のように設定し、その値を反映しておきます。
「U_BOOT_FDT_DIR="noexist"
」には「存在しないディレクトリ」を指定します。これはDebianのカーネルが5.3.0からRISC-V用のDTBをビルドするようになったことに対する回避策です。通常は適切なディレクトリにSoCごとのDTBをインストールし、起動時にそれを選択することが正しいやりかたです。しかしながらQEMU用のDTBはインストールされていません。そこで「存在しないディレクトリ」を指定することでDTBが見つからないようにしておき、QEMUインスタンスの特定のアドレスにあるDTBデータを使うようにしている、というわけです。このあたりは将来的にもう少しスマートな方法に変わる予定です。
ルートファイルシステム内部の設定が終わったので、chrootから抜けておきましょう。
最後に作成したルートファイルシステムをQEMUイメージに変換します。方法はいくつか存在しますが、ここではvirt-make-fsコマンドを使いましょう。
これでイメージの作成は完了です。
QEMUからRISC-Vイメージを立ち上げる
作成したイメージをQEMUから立ち上げましょう。必要なのはRISC-V用のエミュレーターとファームウェア、それにRISC-V向けのU-Boot本体です。
amd64などのアーキテクチャーと異なり、Portsに所属するようなアーキテクチャー向けのエミューレーターはqemu-system-miscパッケージにひとまとめになっているようです。
RISC-V向けのU-Boot本体は残念ながらUbuntuのリポジトリに存在しません。U-Boot 2019.10あたりのパッケージで導入されたものであり、Ubuntuは20.04でも最新が2019.07であるためです。そこでDebianからパッケージをダウンロードし、それをインストールします。
本パッケージはQEMU上で動かすバイナリの集合体のようなものであり、依存関係もないため、この方法でインストールしても問題ないでしょう。ちなみにU-Boot 2020.01は2020年1月8日にunstable取り込まれましたので、Ubuntuでもうまくいけば20.04で使えるようになるかもしれません。
さて、ようやくRISC-Vの仮想マシンを起動できるところまでたどりつきました。少し長いですが、次のようなコマンドを実行しましょう。
まずはU-Bootが立ち上がります。
「U-Boot menu」のところで起動するイメージを選択してください。基本は「1」を選びます。
カーネルとinitramfsがロードされて起動を開始します。「Starting kernel …」のあとはコンソールデバイスの初期化が完了してログを出力するようになるまで時間がかかるのでしばらく待ちましょう。
systemdも起動したらログインバナーが表示されるので、先ほど作成したアカウントでログインしましょう。
/proc/cpuinfo
を確認するとRISC-VのISAモードが表示されていることがわかります。
もちろん、実行されるバイナリもriscv64向けのバイナリです。
あとは「ごく普通のどこにでも存在するDebian」なので、必要なパッケージをインストールしてエンジョイしましょう。
ちなみに動いているのはQEMUの上なので、「Ctrl-a c」と入力すればQEMUモニターに切り替えられます。レジスタのダンプも可能なので、何か問題になったときもすぐに原因がわかりますね!