FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages

RISC-V Fedora ディスクイメージを立ち上げるための BBL (Berkeley Boot Loader) をコンパイルする

前回の続き。前回は

  1. QEMU for RISC-V のビルド実行
  2. Fedora の vmlinux, bbl, ディスクイメージをダウンロード (http://msyksphinz.hatenablog.com/entry/2018/05/07/040000)

まで実施した。次に、フルスクラッチからこれらの環境を作るために以下のことをやっていきたい。

  1. vmlinux のフルスクラッチビルド (ソースコードからコンパイルしてvmlinuxを作る)
  2. BBLをフルスクラッチビルド (ソースコードからコンパイルしてBBL)を作る
  3. ディスクイメージの自作 (BusyBoxを使用して基本的なコマンドが実行できるような環境を作る)

  4. と 4. を試行した。

--

RISC-V の vmlinux と BBLを生成する

BBLというのはBerkeley Boot Loaderのことで、Linuxや各種プログラムを起動させるためのブートローダだ。 x86でいうところの GRUB のようなものだろうか。

BBLを作るためには、vmlinux を先にビルドし、--with-payload でvmlinuxを取り込みながらBBLを作る必要があるらしい。 以下のriscv-toolsの資料を参考にした。

rsicv64-unknown-elf では、Linuxを起動するためのBBLは作れない

最初にかなり試行錯誤したのだが、まず気をつけなければならないのは riscv64-unknown-elf-gccコンパイルしても正しく動作する BBL を生成することができない。 専用の riscv64-unknown-linux-gnu-gccコンパイルする必要がある。

riscv64-unknown-linux-gnu-gcc の作り方

riscv64-unknown-elf-gcc の作り方は簡単だ。 riscv-tools をダウンロードし、./build.sh を起動すれば、環境変数 $RISCV で指定される領域にツールチェインがインストールされる。

$ export RISCV=/home/msyksphinz/riscv64
$ MAKEFLAGS="-j4" ./build.sh

一方で、riscv64-unknown-linux-gcc をビルドする場合には別の手法を用いる。riscv-tools の riscv-gnu-toolchain を使うことには変わりないのだが、オプションを指定しなければならない。

$ export RISCV=/home/msyksphinz/riscv64_linux   # 別のRISC-Vツールチェイン用のコンパイルツールをビルドする
$ cd riscv-tools/riscv-gnu-toolchain
$ ./configure --prefix=$RISCV
$ make linux

上記のスクリプトで、${RISCV}/bin/riscv64-unknown-linux-gnu-gcc などのツールチェインが作られる。

vmlinux の作り方

vmlinux も、コンパイルツールチェインとして riscv64-unknown-linux-gnu を使う必要がある。

Linuxリポジトリをダウンロードして、RISC-V用のカーネルを作成しよう。 Linuxソースコードをダウンロードする。v4.15 もしくは v4.16 から、ビルド可能になっている。

$ curl -L http://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.16.tar.xz | tar -xJ
$ cd linux-4.16/

追記: 上記のLinuxソースコードをダウンロードするのではダメだった。riscv-linuxリポジトリからダウンロードしてくる必要があるようだ。

git clone https://github.com/riscv/riscv-linux.git --recurse-submodules -b riscv-linux-4.15 --depth 1

menuconfig を使ってGNUツールチェインとしてriscv64-unknown-linux-gcc を使うように設定する。

$ make ARCH=riscv defconfig
$ make ARCH=riscv menuconfig
f:id:msyksphinz:20180507231639p:plain

[General Setup] → [Cross-compiler tool prefix] を選択し、riscv64-unknown-linux-gnu- を指定する。

f:id:msyksphinz:20180507231801p:plain

これで設定は完了だ。 Save して Exit する。ビルドしよう。数分するとビルドが完了した。vmlinuxが生成できている。

$ make

BBLを生成する

BBLを生成するためには、vmlinux を取り込む必要がある。こちらも、riscv64-unknown-linux-gnu- を使用する。このとき、vmlinuxの位置を--with-payload で指定する。

$ git clone https://github.com/riscv/riscv-pk.git
$ cd riscv-pk
$ mkdir build
$ cd build
$ ../configure --enable-logo --host=riscv64-unknown-linux-gnu --with-payload=../../../linux-4.16/vmlinux  # 修正。以下が正しい。
$ ../configure --enable-logo --host=riscv64-unknown-linux-gnu --with-payload=../../../riscv-linux/vmlinux
$ make

これで bbl が生成できた。念のため1つのディレクトリに、 bbl と vmlinux と Fedora のディスクイメージをシンボリックリンクしておこう。

$ ln -s ./riscv-pk/build/bbl
$ ln -s ./fedora/stage4-disk.img

qemuを立ち上げてみると、起動...しなかった。なんでだ?

$ qemu-system-riscv64 -m 4G \
      -nographic \
      -machine virt \
      -kernel bbl \
      -object rng-random,filename=/dev/urandom,id=rng0     -device virtio-rng-device,rng=rng0 \
      -append "console=ttyS0 ro root=/dev/vda"     -device virtio-blk-device,drive=hd0 \
      -drive file=stage4-disk.img,format=raw,id=hd0     -device virtio-net-device,netdev=usernet \
      -netdev user,id=usernet,hostfwd=tcp::10000-:22

...
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
Key type dns_resolver registered
VFS: Cannot open root device "vda" or unknown-block(0,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.16.0 #1
Call Trace:
[<ffffffe000030efe>] walk_stackframe+0x0/0xa2
[<ffffffe000030ffc>] show_stack+0x26/0x34
[<ffffffe0005558a8>] dump_stack+0x5e/0x7c
[<ffffffe000034458>] panic+0xce/0x1e8
[<ffffffe000000fc6>] mount_block_root+0x182/0x244
[<ffffffe000001194>] mount_root+0x10c/0x128
[<ffffffe0000012c6>] prepare_namespace+0x116/0x160
[<ffffffe000000c40>] kernel_init_freeable+0x17a/0x19e
[<ffffffe00056648a>] kernel_init+0xe/0xf0
[<ffffffe00002ff86>] ret_from_syscall+0xa/0xe