はじめに
RISC-Vのエミュレータを作っているのですが、そのうえで小さいLinuxを動かしたくなったのでLinuxカーネル(以下カーネル)をビルドしてみました。今回ビルドするカーネルはRV64Iと、できるだけ拡張機能を削ったもの(rv64imafdc_zicsr_zifencei)です。カーネルだけだと寂しいのでBusyBoxを入れただけのinitramfsも作ります。カーネルビルド初心者なので間違ってるところやもっと小さくできるTipsがあれば教えてください。
環境構築
私のメインの環境はx86_64のArchLinuxです。ほぼDockerで作業しますが一応書いときます。$
はホストOSで>
はDockerの中という意味です。
Dockerfileの作成
上手く動かなかったのでriscv-gnu-toolchainにスクリプトを当てています。-jはCPUに合わせて変更してください。riscv-gnu-toolchain本体や依存関係をインストールする設定です。
1
2
3
4
5
6
7
8
9
10
11
12
FROM ubuntu : latest
RUN apt - get update && \
apt - get install - y autoconf automake autotools - dev curl python3 python3 - pip python3 - tomli libmpc - dev libmpfr - dev libgmp - dev gawk build - essential bison flex texinfo gperf libtool patchutils bc zlib1g - dev libexpat - dev ninja - bu ild git cmake libglib2 . 0 - dev libslirp - dev libncurses - dev vim && \
apt - get clean && \
rm - rf / var / lib / apt / lists /* && \
git clone https : // github . com / riscv / riscv - gnu - toolchain
WORKDIR riscv - gnu - toolchain
RUN git switch - d 2025.01 . 20 && \
sed - i '/shallow = true/d' . gitmodules && \
sed - i 's/--depth 1//g' Makefile . in && \
./ configure -- enable - linux && \
make - j6
Copy ツールチェイン等のビルド
結構時間かかりました。多分ネットワーク的な問題なのでビルド自体は体感だとそんなかかってなかった気がします。
1
$ sudo docker build . -t riscv-env
Copy ダウンロード&展開
gitのサーバからもってくるとめちゃくちゃ遅かったので直接ダウンロードしています。チェックサムを確かめたい方は公式ページから確かめてみてください。
1
2
3
4
5
6
$ mkdir tiny - riscv - linux
$ sudo docker run - ti - v . : / tiny - riscv - linux - ti riscv - env : latest
> curl - O https : // git . kernel . org / torvalds / t / linux - 6.14 - rc1 . tar . gz
> tar xvf linux - 6.14
> curl - O https : // busybox . net / downloads / busybox - 1.37 . 0. tar . bz2
> tar xvf busybox - 1.37 . 0. tar . bz2
Copy カーネルのビルド
Linuxのconfigの調整
tinyconfigを作ってそれをTUIで設定する感じです。
1
2
3
> cd linux-6.14
> CORSS_COMPILE=riscv64-unknown-linux-gnu- make ARCH=riscv tinyconfig
> CORSS_COMPILE=riscv64-unknown-linux-gnu- make ARCH=riscv menuconfig
Copy
menuconfig
以下を設定します。依存関係があるのでこの順序で行ってください。/を押すと検索できたり、光っている文字を押すとその文字の項目に飛ぶことができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
General setup --> Initial RAM filesystem and RAM disk (initramfs/initrd) support y
--> Configure standard kernel features (expert users) ---> Enable support for printk y
Platform type --> Allow configurations that result in non-portable kenels y
--> FPU support y
Boot options --> UEFI runtime support n
Device Drivers --> Character devices --> Enable TTY y
--> Serial drivers --> 8250/16550 and compatiable serial support y
--> Console on 8250/16550 and compatiable serial port y
--> Extended 8250/16550 serial driver options y
--> Support more than 4 legancy serial ports y
--> Devicetree based probing for 8250 ports y
--> Early console using RISC-V SBI y
--> RISC-V SBI console support y
Executable file formats --> Kernel support for ELF binaries y
--> Kernel support for scripts starting with #! y
Copy ビルド
defconfigのときと比べて信じられないくらい早いです。待ち時間にYoutubeはみれないです。 ちなみに今回はBuxyBoxがF拡張とD拡張を使用するので指定していませんがFPU support
をn
にし、CFLAGS="-march=rv64imac_zicsr_zifencei -mabi=lp64"
と指定することでF拡張とD拡張を使用しないカーネルをビルドすることもできます。
1
2
> CORSS_COMPILE=riscv64-unknown-linux-gnu- make ARCH=riscv -j12
> cd ..
Copy BusyBoxのビルドとinitramfsの作成
カーネル単体でもいいのですが寂しいのでinitramfsを作ります。
BusyBoxの設定&ビルド
こちらはdefconfigを使用します。いつかはBusyBoxの方の設定もちゃんとやってみたいです。
1
2
3
4
5
6
7
> cd busybox-1.37.0
> CROSS_COMPILE=$CCPREFIX make ARCH=riscv defconfig
> vim .config
CONFIG_STATIC=y
> CROSS_COMPILE=$CCPREFIX make ARCH=riscv -j12
Copy initramfsの作成
find ..
のコマンドは参考 のBuilding a tiny Linux from scratch
からほぼお借りしました。
1
2
3
4
5
6
7
8
9
10
11
12
13
$ mkdir initramfs
$ cd initramfs
$ mkdir {bin,sbin}
$ cp busybox-1.37.0/busybox bin
$ ln -sf busybox bin/sh
$ nvim sbin/init
#! /bin/busybox sh
busybox --install -s
exec /bin/sh
$ find . -print0 | cpio --null --create --verbose --format=newc | bzip2 -c > ../initrd
Copy QEMUで実行
シェルが出てきたら成功です!!
1
2
$ yay -Syu extra/qemu-system-riscv
$ qemu-system-riscv64 -kernel linux-6.14/arch/riscv/boot/Image -machine virt -initrd initrd -append "init=/sbin/init earlycon=sbi console=ttyS0" -nographic
Copy ちなみに上のコマンドではqemu側でcpuの色々な拡張機能が有効になっている状態で実行されるので以下のように-cpu
を設定することによって使用したい拡張機能を指定することができます。※以下の例では、カーネルのビルド のCFLAGSを設定した状態でビルドしたカーネルを用いています。またF拡張とD拡張は無効になっているのでBusyBoxを実行するときに例外が発生します。
1
$ qemu-system-riscv64 -cpu rv64i,m=true,a=true,c=true,zicsr=true,zifencei=true,u=true,s=true,mmu=on,pmp=on,sv57=true -kernel linux-6.14/arch/riscv/boot/Image -machine virt -initrd initrd -append "init=/sbin/init earlycon=sbi console=ttyS0" -nographic
Copy おわりに
初めてLinuxのビルドオプションを色々いじったのでめちゃくちゃハマりましたが楽しすぎました。 このせいでネスペ勉強できなかった。 いつかは自分だけのinitを書いてディストリ作ってみたいです。次回は自宅サーバ系かOpenSBIで遊んでみた的な記事を書くかもしれないです。
参考