Build Linux Kernel for XiangShan
1. How to build a minimal Linux Kernel that can run on Xiangshan or NEMU in a simulation environment
Note: Please prepare the riscv64 toolchain in advance, the possible prefixes are
riscv64-linux-gnu-
,riscv64-unknown-linux-gnu-
,riscv64-unknown-elf-
. You may refer to https://github.com/riscv-collab/riscv-gnu-toolchain to setup toolchain needed by Linux.
- Clone riscv-pk, riscv-linux, riscv-rootfs from Xiangshan project, which are Bootloader, Linux kernel and rootfs respectively. Then checkout to target branch. These three repos must be laid in the same directory.
- https://github.com/OpenXiangShan/riscv-pk (noop branch)
- https://github.com/OpenXiangShan/riscv-linux (nanshan branch)
- https://github.com/OpenXiangShan/riscv-rootfs (master branch)
-
Set environment variables
- NEMU_HOME: Path to NEMU (you may
source env.sh
inxs-env
) - NOOP_HOME: Path to XiangShan (you may
source env.sh
inxs-env
) - RISCV_ROOTFS_HOME: path to
riscv-rootfs
- RISCV:Installation path of riscv-gnu-toolchain ( the top directory including bin, inlcude, lib etc.)
You can see riscv-gnu-toolchain official documents to install riscv-gnu-toolchain. You can also see GCB tool chain instructions if you need to compile B extension GNU tool chain for Xiangshan.
- NEMU_HOME: Path to NEMU (you may
-
build rootfs
- Enter
riscv-rootfs
directory - In simulation environment, we let Linux Kernel start on the ramfs, so first prepare the initramfs that you want to run, and you can put the workload you want to run in it. By default we use riscv-rootfs/rootfsimg/initramfs-emu.txt, which runs hello under Linux. Modifications on this are introduced in the following chapter.
- Enter
- Build the Linux Kernel Manually
- Enter
riscv-linux
directory - Use the default emu_defconfig to configure. The command is
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- emu_defconfig
- (Optional) Modify config according to your own needs through menuconfig, the command is
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig
- Compile, the command is
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j
- If succeed, a vmlinux file will be generated in the directory
- ( You may choose to skip the compilation here, since the following BBL Makefile includes this)
- Enter
-
Build BBL and Kernel, then link Kernel
- Enter
riscv-pk
directory - Configure the device tree, let
platform.dtsi
symlink to thenoop.dtsi
inriscv-pk/dts
- Run
make -j
, this command will automatically compile the Linux Kernel, link it to BBL as a payload, and finally package it into a build/bbl.bin binary image. After that, Xiangshan is able to run this image (See Makefile).
- Enter
-
Others
- There is a small problem with Makefile dependency of riscv-pk, so after any modification, please
make clean
first in riscv-pk - Please prepare the riscv64 tool chains in advance, you may use
riscv64-linux-gnu-
,riscv64-unknown-linux-gnu-
andriscv64-unknown-elf-
- There is a small problem with Makefile dependency of riscv-pk, so after any modification, please
2. Run BusyBox and some simple applications in Linux
- Reconfigure the Linux Kernel
- Enter
riscv-linux
directory - Use
fpga_defconfig
to configure, the command ismake ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- fpga_defconfig
- Modify config according to your own needs through menuconfig, the command is
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig
, change the source of initramfs from${RISCV_ROOTFS_HOME}/rootfsimg/initramfs.txt
to${RISCV_ROOTFS_HOME}/rootfsimg/initramfs-autorun.txt
- Enter
- Modify rootfs as appropriate
- Go to
rootfsimg
directory inriscv-rootfs
directory - initramfs defines the content of file system, and inittab will be executed during initialization
- Modify the contents of initramfs-autorun.txt and inittab to run the programs you want after Linux has booted (stream and redis by default)
- Go to
- Reconfigure BBL
- Enter
riscv-pk
directory - Modify the size of address space size in dts, so that programs using larger memory can be supported
# ./riscv-pk/dts/noop.dtsi L11: memory@100000000 { device_type = "memory"; -reg = <0x0 0x80000000 0x0 0x2000000>; +reg = <0x0 0x80000000 0x0 0x80000000>; };
make clean
runmake -j
to generate bbl.bin, which could be run on NEMU or XiangShan
- Enter
3. Based on this, how to run Debian distribution on NEMU
- Reconfigure the Linux Kernel
- to the riscv-linux directory
- Use debian_defconfig to configure, the command is
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- debian_defconfig
- Reconfigure BBL
- Enter
riscv-pk
directory - Modify the bootargs in dts
(Please see https://github.com/OpenXiangShan/NEMU/tree/master/resource/sdcard)
# ./riscv-pk/dts/noop.dtsi chosen { -bootargs = "root=/dev/mmcblk0 rootfstype=ext4 ro rootwait earlycon"; +bootargs = "root=/dev/mmcblk0p1 rootfstype=ext4 ro rootwait earlycon"; };
- After
make clean
runmake -j
to generatebbl.bin
- Enter
- Configure NEMU
- Enter
NEMU
directory - Edit
src/device/sdcard.c
, find the sdimg variable in the init_sdcard() function and assign it to the path of the Debian mirror (for the generation of the Debian mirror, please refer to How to create a Debian image) - Recompile NEMU, and then run build/bbl.bin under the riscv-pk project
- Enter
4. How to run Debian distribution on Xiangshan
- Configure Xiangshan
- Enter
Xiangshan
directory - Edit the
./difftest/config/config.h
file, set the SDCARD_IMAGE macro to the path to the Debian image - Rebuild Xiangshan, then run build/bbl.bin under the riscv-pk project
- Enter
5. Based on this, how to build dualcore Linux kernal
- Reconfigure the Linux Kernel
- Enter riscv-linux directory
make clean
- Use emu_defconfig, fpga_defconfig or debian_defconfig to configure, command is same as above
- Use menuconfig to configure SMP,the command is
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig
, in Platform type submenu, set Symmetric Multi-Processing to Yes, save it and exit
- Reconfigure BBL
- Enter riscv-pk directory
git stash
git checkout dualcore
- Modify the size of address space size in dts
# ./riscv-pk/dts/noop.dtsi L11: memory@100000000 { device_type = "memory"; -reg = <0x0 0x80000000 0x0 0x2000000>; +reg = <0x0 0x80000000 0x0 0x8000000>; };
- When running 16g Debian, modify the bootargs in dts
# ./riscv-pk/dts/noop.dtsi chosen { -bootargs = "root=/dev/mmcblk0 rootfstype=ext4 ro rootwait earlycon"; +bootargs = "root=/dev/mmcblk0p1 rootfstype=ext4 ro rootwait earlycon"; };
- After
make clean
runmake -j
to generatebbl.bin
FAQs
riscv64-unknown-linux-gnu-gcc: command not found
Make sure riscv64-unknown-linux-gnu-gcc is in your PATH
unrecognized opcode: fence.i, extension zifencei required
Change the Makefile of kernel by appending _zicsr_zifencei
to KBUILD_AFLAGS
and KBUILD_CFLAGS
.
-KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD-ARCH_A)fd$(KBUILD_ARCH_C)
+KBUILD AFLAGS-march=$(KBUILD_MARCH)$(KBUILD_ARCH-A)fd$(KBUILD_ARCH_C)_zicsr_zifencei
-KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH-A)$(KBUILD-ARCH_C)
+KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C)_zicsr_zifencei
undefiend symbol MEM_START+0xa0000 referenced in expression
Add spaces around +
: . = MEM_START + 0xa0000
repo/stream.c: No such file or directory
Ignore it
riscv-rootfs/rootfsimg/build/busybox could not be opened for reading
Try to remove riscv-rootfs
directory, reclone it from Github, and rebuild