# Run [kbox](https://github.com/sysprog21/kbox/) on riscv64
contributed by < [`rota1001`](https://github.com/rota1001) >
## Run it on AARCH64
I run it on ARCH64 architecture first and then change to riscv64
### Compile Linux Kernel
```shell
$ wget https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.19.9.tar.xz
$ tar Jxvf linux-6.19.9.tar.xz
$ cd linux-6.19.9
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j`nproc`
```
### Build rootfs
```shell
$ wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/aarch64/alpine-minirootfs-3.21.0-aarch64.tar.gz
$ dd if=/dev/zero of=aarch64_alpine_host.ext4 bs=1M count=256
$ mkfs.ext4 aarch64_alpine_host.ext4
$ mkdir rootfs
$ sudo mount aarch64_alpine_host.ext4 rootfs
$ sudo tar -xvf alpine-minirootfs-3.21.0-aarch64.tar.gz -C rootfs
$ sudo umount rootfs
```
### Build kbox
Build it under the `kbox/` directory:
```shell
$ make ARCH=aarch64 CC=aarch64-linux-gnu-gcc BUILD=release
$ make ARCH=aarch64 CC=aarch64-linux-gnu-gcc rootfs
```
Put kbox and alpine.ext4 into rootfs:
```shell
$ sudo mount aarch64_alpine_host.ext4 rootfs
$ sudo cp kbox rootfs
$ sudo cp alpine.ext4 rootfs
```
Since the dynamic link library in alpine is musl rather than glibc but the pre-compiled LKL uses glibc, the glibc dynamic link library has to be copied into the rootfs.
```shell
$ sudo cp -a /usr/aarch64-linux-gnu/lib/* rootfs/lib
$ sudo umount rootfs
```
### Run kbox
Run the Linux kernel in QEMU:
```shell
$ qemu-system-aarch64 \
-machine virt \
-cpu cortex-a53 \
-m 2G \
-nographic \
-kernel linux-6.19.9/arch/arm64/boot/Image \
-append "root=/dev/vda rw console=ttyAMA0 init=/bin/sh" \
-drive file=aarch64_alpine_host.ext4,format=raw,id=hd0,if=none \
-device virtio-blk-device,drive=hd0
```
After successfully boot, mount the procfs, which is needed by kbox:
```shell
$ mount -t proc none /proc
```
Run the kbox:
```shell
~ # ./kbox image -S alpine.ext4 -- /bin/sh
mount(devtmpfs on /dev): No such device
warning: devtmpfs unavailable (CONFIG_DEVTMPFS?)
kbox: probing host features...
kbox: all feature probes passed.
/bin/sh: can't access tty; job control turned off
~ # uname -a
Linux kbox 6.8.0-kbox #1 SMP aarch64 Linux
```
And it works well.
<!--
```shell
$ wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/aarch64/alpine-virt-3.21.0-aarch64.iso
```
創建一個硬碟,裝系統:
```shell
$ qemu-img create -f qcow2 disk.qcow2 10G
$ qemu-system-aarch64 \
-machine virt \
-cpu cortex-a53 \
-m 1G \
-nographic \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-cdrom alpine-virt-3.21.0-aarch64.iso \
-drive file=disk.qcow2,format=qcow2,if=virtio
```
把系統裝到 disk.qcow2 上。
接下來要利用 VirtFS 來達成 qemu 機器與宿主機間的目錄共享:
```shell
$ mkdir share
$ echo "meow" > meow.txt
$ qemu-system-aarch64 \
-machine virt \
-cpu cortex-a53 \
-m 1G \
-nographic \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-drive file=alpine-disk.qcow2,format=qcow2,if=virtio \
-fsdev local,security_model=passthrough,id=fsdev0,path=`pwd`/share \
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=share
...
rota1001:~# mount -t 9p -o trans=virtio,version=9p2000.L share /share
rota1001:~# ls /share
meow.txt
rota1001:~# cat /share/meow.txt
meow
```
手動 mount 成功後,修改 fstab 來達成開機自動掛載:
```shell
$ echo "share /share 9p trans=virtio,version=9p2000.L,rw 0 0" >> /etc/
fstab
```
以上的啟動腳本我寫在 `run.sh` 這個 shellscript 中,以下會直接使用它。
編譯 kbox:
```shell
$ cd kbox/
$ scripts/fetch-lkl.sh aarch64
$ make LKL_DIR=`pwd`/lkl-aarch64 CC=aarch64-linux-gnu-gcc BUILD=release
$ make rootfs ALPINE_ARCH=aarch64
```
把 kbox 與 rootfs 放進 share 中:
```shell
$ cp kbox/kbox kbox/alpine.ext4 share
```
在 alpine 中預設是使用 musl 而非 glibc,但 LKL 與 kbox 使用的都是 glibc,所以要把動態連結庫搬到裡面去,首先把他們放到 share 中:
```shell
$ cp -r /usr/aarch64-linux-gnu/lib share
```
啟動後搬運動態連結庫:
```shell
rota1001:~# cp -a /share/lib/* /lib
```
搬運完後就能啟動了:
```shell
rota1001:~# /share/kbox image -S /share/alpine.ext4 -- /bin/sh -i
kbox: probing host features...
kbox: all feature probes passed.
/bin/sh: can't access tty; job control turned off
/ # uname -a
Linux kbox 6.8.0-kbox #1 SMP aarch64 Linux#
```
-->
## Run it on riscv64
### Compile LKL
In the mainline LKL, it takes big amount of time for link time relaxation while running on the riscv64 architecture, so I used my own patch version (,btw, my [PR](https://github.com/lkl/linux/pull/621) is on the way)
```shell
$ sudo dpkg --add-architecture riscv64
$ sudo apt update
$ sudo apt install -y libfuse3-dev:riscv64 libarchive-dev:riscv64
$ wget https://github.com/rota1001/lkl/archive/refs/heads/rv64.zip
$ unzip rv64.zip
$ mv lkl-rv64 linux && cd linux
$ make ARCH=lkl menuconfig
```
Do the following settings in menuconfig:
- Change the Output format to `elf64-littleriscv`
- Set the Device Drivers -> Generic Driver Options -> Maintain a devtmpfs filesystem to mount at /dev
- Set the Device Drivers -> Generic Driver Options -> Automount devtmpfs at /dev, after the kernel mounted the rootfs
Then compile:
```shell
$ make CROSS_COMPILE=riscv64-linux-gnu- -C tools/lkl -j`nproc`
```
### Compile the Linux Kernel
```shell
$ wget https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.19.9.tar.xz
$ tar Jxvf linux-6.19.9.tar.xz
$ cd linux-6.19.9
$ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
$ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j`nproc`
```
### Build rootfs
```shell
$ wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/riscv64/alpine-minirootfs-3.21.0-riscv64.tar.gz
$ dd if=/dev/zero of=riscv64_alpine_host.ext4 bs=1M count=256
$ mkfs.ext4 riscv64_alpine_host.ext4
$ mkdir rootfs
$ sudo mount riscv64_alpine_host.ext4 rootfs
$ sudo tar -xvf alpine-minirootfs-3.21.0-riscv64.tar.gz -C rootfs
$ sudo umount rootfs
```
### Build kbox
kbox needs some patch here, so I use my own patch:
```shell
$ git clone https://github.com/rota1001/kbox.git
$ cd kbox
$ git checkout rv64
```
Now, we are in `kbox/` directory and the LKL source code is in `kbox/linux`. Let's start building the kbox:
```
$ make LKL_DIR=linux/tools/lkl ARCH=riscv64 CC=riscv64-linux-gnu-gcc BUILD=release
$ make ARCH=riscv64 CC=riscv64-linux-gnu-gcc rootfs
```
Put both kbox and apline.ext4 into the rootfs:
```shell
$ sudo mount riscv64_alpine_host.ext4 rootfs
$ sudo cp kbox rootfs
$ sudo cp alpine.ext4 rootfs
```
Copy the dynamic linked library into it:
```shell
$ sudo cp -a /usr/riscv64-linux-gnu/lib/* rootfs/lib
$ sudo umount rootfs
```
### Run kbox
Run the Linux Kernel in QEMU:
```shell
$ qemu-system-riscv64 \
-machine virt \
-cpu rv64 \
-m 2G \
-nographic \
-kernel linux-6.19.9/arch/riscv/boot/Image \
-append "root=/dev/vda rw console=ttyS0 init=/bin/sh" \
-drive file=riscv64_alpine_host.ext4,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0
```
Mount the procfs:
```shell
$ mount -t proc none /proc
```
Run the kbox:
```shell
~ # ./kbox image -S alpine.ext4 -- /bin/sh
kbox: probing host features...
kbox: all feature probes passed.
/bin/sh: can't access tty; job control turned off
~ # uname -a
Linux kbox 6.8.0-kbox #1 SMP unknown Linux
```
And it works well.