SpikeでLinux向けにコンパイルしたバイナリをどうにかして動かすということにあたり、とりあえずまずはSpikeでLinuxを立ち上げる方法を確立するというところから始めることにした。
SpikeでLinuxをブートさせるためには、以下のことが必要となる。
- Spikeをビルドする
- Linuxカーネルをビルドする
- OpenSBIを使って、
fw_jump.elfをビルドする。 rootfs.cpiを作成する- Spikeを立ち上げて、Linuxをブートする。
まず先に断っておくのが、今回作成する rootfs.cpi はかなり適当に作っているので、Linuxのユーザプログラム自体は起動できない。
ユーザプログラムが動くようになるためには、BusyBoxなどを使用して環境を用意する必要があるが、とりあえずその部分は簡単にしている。
これは今後アップデートしていくことにしよう。
Dockerfileにまとめたので、必要な部分を切り出しながら見ていく。
1. Spikeをビルドする
これは通常の方法でSpikeをビルドした。 riscv-isa-sim をダウンロードしてSpikeをビルドする。
# Spikeのビルド
RUN git clone https://github.com/riscv-software-src/riscv-isa-sim.git && \
cd riscv-isa-sim && \
mkdir build && cd build && \
../configure --prefix=$RISCV_PREFIX && \
make -j$(nproc) && make install
2. Linux カーネルをビルドする
Linuxカーネルをダウンロードしてビルドする。ARCHとCROSS_COMPILEを適切に設定する。
# Linuxカーネルのビルド
RUN git clone --depth=1 https://github.com/torvalds/linux.git && \
cd linux && \
make ARCH=riscv defconfig && \
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j$(nproc)
3. OpenSBIを使って、fw_jump.elf を作成する
これは、 OpenSBIを使ってLinuxのブートローダに制御を渡すための仕組み。これもダウンロードしてビルドする。
# OpenSBIのビルド
RUN git clone https://github.com/riscv-software-src/opensbi.git && \
cd opensbi && \
make CROSS_COMPILE=riscv64-linux-gnu- \
PLATFORM=generic FW_PAYLOAD_NONE=1
4. rootfs.cpio の作成
rootfs.cpio はこの場合適当に作る。ディレクトリが存在しているだけで、シェルコマンドとかも全く入っていないので、Linuxがブートしたところで何も動かない。
# rootfs.cpioを作成
RUN mkdir -p rootfs/bin rootfs/sbin rootfs/etc rootfs/proc rootfs/sys rootfs/usr/bin rootfs/usr/sbin rootfs/dev} && \
echo '#!/bin/sh' > rootfs/init && \
echo 'exec /bin/sh' >> rootfs/init && \
chmod +x rootfs/init && \
cd rootfs && \
find . | cpio -o --format=newc > ../rootfs.cpio
rootfs/init を作成して、中身を以下のようにしている。しかしrootfsをさぽっているので、 /bin/sh も動かないことに注意。
#!/bin/sh exec /bin/sh
5. Spikeを起動する。
# 最後にエントリポイント(Spike起動)
CMD spike \
--kernel ./linux/arch/riscv/boot/Image \
--initrd ./rootfs.cpio \
./opensbi/build/platform/generic/firmware/fw_jump.elf
これで、Spike上でLinuxがブートし始める。しかし、上述した通り、 /initの記述が適当なのでそこで止まる。
docker run -it --rm riscv-spike-linux
OpenSBI v1.6-89-g99aabc6
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : ucbbar,spike-bare
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 : htif
Platform Shutdown Device : htif
Platform Suspend Device : ---
Platform CPPC Device : ---
Firmware Base : 0x80000000
Firmware Size : 317 KB
Firmware RW Offset : 0x40000
Firmware RW Size : 61 KB
Firmware Heap Offset : 0x46000
Firmware Heap Size : 37 KB (total), 2 KB (reserved), 11 KB (used), 23 KB (free)
Firmware Scratch Size : 4096 B (total), 392 B (used), 3704 B (free)
Runtime SBI Version : 2.0
Standard SBI Extensions : ipi,pmu,srst,hsm,rfnc,time,base,legacy,dbcn
Experimental SBI Extensions : sse,fwft,dbtr
Domain0 Name : root
Domain0 Boot HART : 0
Domain0 HARTs : 0*
Domain0 Region00 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W)
Domain0 Region01 : 0x0000000080040000-0x000000008004ffff M: (R,W) S/U: ()
Domain0 Region02 : 0x0000000002080000-0x00000000020bffff M: (I,R,W) S/U: ()
Domain0 Region03 : 0x0000000080000000-0x000000008003ffff M: (R,X) S/U: ()
Domain0 Region04 : 0x0000000002000000-0x000000000207ffff M: (I,R,W) S/U: ()
Domain0 Region05 : 0x000000000c000000-0x000000000cffffff M: (I,R,W) S/U: (R,W)
Domain0 Region06 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X)
Domain0 Next Address : 0x0000000080200000
Domain0 Next Arg1 : 0x0000000082200000
Domain0 Next Mode : S-mode
Domain0 SysReset : yes
Domain0 SysSuspend : yes
Boot HART ID : 0
Boot HART Domain : root
Boot HART Priv Version : v1.12
Boot HART Base ISA : rv64imafdc
Boot HART ISA Extensions : zicntr,zihpm,sdtrig
Boot HART PMP Count : 16
Boot HART PMP Granularity : 2 bits
Boot HART PMP Address Bits : 54
Boot HART MHPM Info : 0 (0x00000000)
Boot HART Debug Triggers : 4 triggers
Boot HART MIDELEG : 0x0000000000000222
Boot HART MEDELEG : 0x000000000004b109
[ 0.000000] Booting Linux on hartid 0
[ 0.000000] Linux version 6.15.0-rc4-gca91b9500108 (root@buildkitsandbox) (riscv64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #1 SMP Tue Apr 29 06:18:49 UTC 2025
[ 0.000000] Machine model: ucbbar,spike-bare
[ 0.136395] Freeing unused kernel image (initmem) memory: 2284K [ 0.136430] Run /init as init process [ 0.136525] Failed to execute /init (error -2) [ 0.136535] Run /sbin/init as init process [ 0.136575] Run /etc/init as init process [ 0.136610] Run /bin/init as init process [ 0.136650] Run /bin/sh as init process [ 0.136690] Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. [ 0.136705] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.15.0-rc4-gca91b9500108 #1 NONE [ 0.136720] Hardware name: ucbbar,spike-bare (DT) [ 0.136730] Call Trace: [ 0.136740] [<ffffffff80014f34>] dump_backtrace+0x1c/0x24 [ 0.136760] [<ffffffff80002310>] show_stack+0x28/0x34 [ 0.136775] [<ffffffff8000eff2>] dump_stack_lvl+0x48/0x66 [ 0.136790] [<ffffffff8000f024>] dump_stack+0x14/0x1c [ 0.136805] [<ffffffff80002a52>] panic+0x104/0x2c4 [ 0.136820] [<ffffffff809a571c>] _cpu_down+0x0/0x3e8 [ 0.136835] [<ffffffff809ae8e6>] ret_from_fork+0xe/0x18 [ 0.136855] ---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. ]---
全Dockerfile
# ベースイメージ(UbuntuでOK)
FROM ubuntu:22.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 \
gcc-riscv64-unknown-elf \
gcc-riscv64-linux-gnu \
qemu-user-static \
sudo \
&& apt-get clean
# 環境変数
ENV RISCV_PREFIX=/opt/riscv
ENV PATH=$RISCV_PREFIX/bin:$PATH
# Spikeのビルド
RUN git clone https://github.com/riscv-software-src/riscv-isa-sim.git && \
cd riscv-isa-sim && \
mkdir build && cd build && \
../configure --prefix=$RISCV_PREFIX && \
make -j$(nproc) && make install
# Linuxカーネルのビルド
RUN git clone --depth=1 https://github.com/torvalds/linux.git && \
cd linux && \
make ARCH=riscv defconfig && \
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j$(nproc)
# OpenSBIのビルド
RUN git clone https://github.com/riscv-software-src/opensbi.git && \
cd opensbi && \
make CROSS_COMPILE=riscv64-linux-gnu- \
PLATFORM=generic FW_PAYLOAD_NONE=1
# rootfs.cpioを作成
RUN mkdir -p rootfs/bin rootfs/sbin rootfs/etc rootfs/proc rootfs/sys rootfs/usr/bin rootfs/usr/sbin rootfs/dev} && \
echo '#!/bin/sh' > rootfs/init && \
echo 'exec /bin/sh' >> rootfs/init && \
chmod +x rootfs/init && \
cd rootfs && \
find . | cpio -o --format=newc > ../rootfs.cpio
# 作業ディレクトリを設定
# WORKDIR /
# 最後にエントリポイント(Spike起動)
CMD spike \
--kernel ./linux/arch/riscv/boot/Image \
--initrd ./rootfs.cpio \
./opensbi/build/platform/generic/firmware/fw_jump.elf