RISC-Vアーキテクチャ向けのLinuxカーネルをQEMU上で動作させる環境を構築する。 この環境では、Dockerを使用してビルド環境を統一し、BusyBoxベースのルートファイルシステムとLinuxカーネル、OpenSBI、QEMUを組み合わせてRISC-V Linuxのブート環境を構築する。
この環境では以下のコンポーネントをビルド・実行する:
- RISC-V GNU Toolchain: RISC-V向けのクロスコンパイラ
- BusyBox: 軽量なルートファイルシステム
- Linux Kernel (v6.9): RISC-V向けLinuxカーネル
- OpenSBI (v1.6): RISC-V向けのファームウェア
- QEMU (v9.2.4 / v10.1.0): エミュレータ
Dockerfileによるビルド環境の構築
まず、Dockerfileを使用してビルド環境を構築する。 このDockerfileは、Ubuntu 24.04ベースのイメージに必要なビルドツールとRISC-Vツールチェーンをインストールし、各コンポーネントを順次ビルドしていく。
必要なパッケージのインストール
FROM ubuntu:24.04 RUN apt-get update && apt-get install -y \ git \ make \ autoconf \ automake \ libtool \ build-essential \ device-tree-compiler \ cpio \ libssl-dev \ wget \ bc \ flex \ bison \ python3 \ curl \ autotools-dev \ python3-pip \ python3-tomli \ libmpc-dev \ libmpfr-dev \ libgmp-dev \ gawk \ texinfo \ gperf \ patchutils \ bc \ zlib1g-dev \ libexpat-dev \ ninja-build \ cmake \ libglib2.0-dev \ libslirp-dev \ sudo \ && apt-get clean
RISC-Vツールチェーンのセットアップ
環境変数を設定し、RISC-Vツールチェーンをダウンロードする:
ENV RISCV=/opt/riscv ENV PATH=$RISCV/bin:$PATH ENV LD_LIBRARY_PATH=$RISCV/lib RUN cd $RISCV/../ && \ curl -L https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2025.05.10/riscv64-glibc-ubuntu-24.04-gcc-nightly-2025.05.10-nightly.tar.xz | tar Jx
BusyBoxのビルドとルートファイルシステムの作成
BusyBoxをクロスコンパイルし、静的リンクでビルドする。その後、initスクリプトを作成してルートファイルシステムをcpioアーカイブとして作成する:
# Download BusyBox and create rootfs.cpio (v1.36.0) RUN git clone https://git.busybox.net/busybox --depth=1 -b 1_36_0 && \ cd busybox && \ CROSS_COMPILE=riscv64-unknown-linux-gnu- make defconfig && \ sed -i 's|# CONFIG_STATIC is not set|CONFIG_STATIC=y|g' .config && \ CROSS_COMPILE=riscv64-unknown-linux-gnu- make -j$(nproc) && \ CROSS_COMPILE=riscv64-unknown-linux-gnu- make install -j$(nproc) CONFIG_PREFIX=/linux_riscv/rootfs
initスクリプトでは、proc、sys、devなどのファイルシステムをマウントし、シェルを起動する:
RUN mkdir -p /linux_riscv/rootfs && cd /linux_riscv/rootfs && \ mkdir -p dev proc sys &&\ echo "#!/bin/sh\n\ echo "[init] start" > /dev/console 2>&1\n\ mount -t proc proc /proc\n\ mount -t sysfs sys /sys\n\ mount -t devtmpfs dev /dev 2>/dev/null || mount -t tmpfs tmp /dev\n\ mknod /dev/console c 5 1 2>/dev/null || true\n\ mknod /dev/ttyS0 c 4 64 2>/dev/null || true\n\ mknod /dev/null c 1 3 2>/dev/null || true\n\ chmod 600 /dev/console 2>/dev/null || true\n\ chmod 666 /dev/null 2>/dev/null || true\n\ mkdir -p /dev/pts\n\ mount -t devpts devpts /dev/pts 2>/dev/null || true\n\ exec /bin/sh" > /linux_riscv/rootfs/init && chmod +x /linux_riscv/rootfs/init RUN cd /linux_riscv/rootfs && \ find . -print0 | cpio --null -ov --format=newc > /linux_riscv/rootfs.cpio
Linuxカーネルのビルド
Linuxカーネルv6.9をビルドし、作成したrootfs.cpioをinitramfsとして組み込む:
# Build Linux (v6.9) RUN git clone --depth=1 https://github.com/torvalds/linux.git -b v6.9 && \ cd linux && \ make ARCH=riscv defconfig && \ sed -i 's|CONFIG_INITRAMFS_SOURCE=""|CONFIG_INITRAMFS_SOURCE="/linux_riscv/rootfs.cpio"|g' .config && \ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc)
OpenSBIのビルド
OpenSBI v1.6をビルドし、Linuxカーネルイメージをペイロードとして組み込む:
# Build OpenSBI (v1.6) RUN git clone https://github.com/riscv-software-src/opensbi.git --depth 1 -b v1.6 && \ cd opensbi && \ make CROSS_COMPILE=riscv64-unknown-linux-gnu- \ PLATFORM=generic FW_PAYLOAD_PATH=/linux_riscv/linux/arch/riscv/boot/Image
QEMUのビルド
最後に、QEMU v9.2.4をビルドする:
# Build QEMU (v9.2.4) RUN git clone https://github.com/qemu/qemu.git --depth=1 -b v9.2.4 && \ cd qemu && \ mkdir -p build && cd build && \ ../configure --target-list=riscv64-softmmu --prefix=$RISCV && \ make -j$(nproc) && make install && \ cd ../ && rm -rf build
QEMUでの起動
ビルドが完了したら、以下のコマンドでQEMUを起動する。
qemu-system-riscv64 -nographic -machine virt \
-kernel /linux_riscv/linux/arch/riscv/boot/Image \
-initrd /linux_riscv/rootfs.cpio \
-append "console=ttyS0 rdinit=/init"
実行結果は以下となっている:
./qemu_riscv_boot.sh
OpenSBI v1.5.1
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : riscv-virtio,qemu
Platform Features : medeleg
Platform HART Count : 1
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 10000000Hz
Platform Console Device : uart8250
Platform HSM Device : ---
Platform PMU Device : ---
Platform Reboot Device : syscon-reboot
Platform Shutdown Device : syscon-poweroff
Platform Suspend Device : ---
Platform CPPC Device : ---
Firmware Base : 0x80000000
....
[ 0.815524] debug_vm_pgtable: [debug_vm_pgtable ]: Validating architecture page table helpers
[ 0.825344] clk: Disabling unused clocks
[ 0.825870] PM: genpd: Disabling unused power domains
[ 0.826365] ALSA device list:
[ 0.826634] No soundcards found.
[ 0.827353] Warning: unable to open an initial console.
[ 0.889221] Freeing unused kernel image (initmem) memory: 3400K
[ 0.890313] Run /init as init process
/bin/sh: can't access tty; job control turned off
~ # ls -ltr
total 4
lrwxrwxrwx 1 0 0 11 Nov 14 15:32 linuxrc -> bin/busybox
drwxr-xr-x 2 0 0 1900 Nov 14 15:32 bin
drwxr-xr-x 2 0 0 1480 Nov 14 15:32 sbin
drwxr-xr-x 4 0 0 80 Nov 14 15:32 usr
-rwxr-xr-x 1 0 0 537 Nov 14 16:41 init
dr-xr-xr-x 12 0 0 0 Nov 14 16:45 sys
dr-xr-xr-x 93 0 0 0 Nov 14 16:45 proc
drwxr-xr-x 5 0 0 12320 Nov 14 16:45 dev
実際のソースコード: riscv_linux/linux_on_qemu at main · msyksphinz-self/riscv_linux · GitHub