# Build Linux Kernel with RISC-V Arch ###### tags: `RISC-V`, `64 bits`, `riscv64-linux-gnu-`, `Linux kernel`, `QEMU` I use [Arch Linux](https://archlinux.org/) as my working environment. ## Build the [Linux kernel](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/) ```shell $ sudo pacman -S riscv64-linux-gnu-gcc $ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig $ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j32 ``` Tune the build config, if it is needed. The option `CONFIG_SOC_VIRT` is for QEMU virtual machine. ## Quick test for the kernel with QEMU ```shell $ sudo pacman -S qemu-system-riscv qemu-system-riscv-firmware $ qemu-system-riscv64 -M virt -smp 4 -m 2G -display none -serial stdio -kernel arch/riscv/boot/Image -append "root=/dev/ram" OpenSBI v1.2 ____ _____ ____ _____ / __ \ / ____| _ \_ _| | | | |_ __ ___ _ __ | (___ | |_) || | | | | | '_ \ / _ \ '_ \ \___ \| _ < | | | |__| | |_) | __/ | | |____) | |_) || |_ \____/| .__/ \___|_| |_|_____/|____/_____| | | |_| Platform Name : riscv-virtio,qemu Platform Features : medeleg Platform HART Count : 4 Platform IPI Device : aclint-mswi Platform Timer Device : aclint-mtimer @ 10000000Hz Platform Console Device : uart8250 Platform HSM Device : --- Platform PMU Device : --- Platform Reboot Device : sifive_test Platform Shutdown Device : sifive_test Firmware Base : 0x80000000 Firmware Size : 236 KB Runtime SBI Version : 1.0 Domain0 Name : root Domain0 Boot HART : 2 Domain0 HARTs : 0*,1*,2*,3* Domain0 Region00 : 0x0000000002000000-0x000000000200ffff (I) Domain0 Region01 : 0x0000000080000000-0x000000008003ffff () Domain0 Region02 : 0x0000000000000000-0xffffffffffffffff (R,W,X) Domain0 Next Address : 0x0000000080200000 Domain0 Next Arg1 : 0x00000000bfe00000 Domain0 Next Mode : S-mode Domain0 SysReset : yes Boot HART ID : 2 Boot HART Domain : root Boot HART Priv Version : v1.12 Boot HART Base ISA : rv64imafdch Boot HART ISA Extensions : time,sstc Boot HART PMP Count : 16 Boot HART PMP Granularity : 4 Boot HART PMP Address Bits: 54 Boot HART MHPM Count : 16 Boot HART MIDELEG : 0x0000000000001666 Boot HART MEDELEG : 0x0000000000f0b509 [ 0.000000] Linux version 6.3.1 (zack@starnight) (riscv64-linux-gnu-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.39) #16 SMP Sun May 7 18:03:42 CST 2023 [ 0.000000] random: crng init done [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000 [ 0.000000] Machine model: riscv-virtio,qemu [ 0.000000] efi: UEFI not found. [ 0.000000] OF: reserved mem: 0x0000000080000000..0x000000008003ffff (256 KiB) map non-reusable mmode_resv0@80000000 [ 0.000000] Zone ranges: [ 0.000000] DMA32 [mem 0x0000000080200000-0x00000000ffffffff] [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node [ 0.000000] Early memory node ranges [ 0.000000] node 0: [mem 0x0000000080200000-0x00000000ffffffff] [ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x00000000ffffffff] [ 0.000000] On node 0, zone DMA32: 512 pages in unavailable ranges ... ``` ## Boot the kernel with Root Filesystem The root filesystem can be downloaded from [starnight/build-image's Releases](https://github.com/starnight/build-image/releases). ```shell $ qemu-system-riscv64 -M virt -smp 4 -m 2G -display none -serial stdio -kernel ~/linux-stable/arch/riscv/boot/Image -append "console=ttyS0 root=/dev/vda2 rw rootfstype=ext4" -drive file=/tmp/simple-alpine-qemu_riscv64.img,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 ``` ## Boot the system for online debug 1. Config and build the kernel with: * `CONFIG_DEBUG_INFO=y` * `# CONFIG_DEBUG_INFO_REDUCED is not set` * `CONFIG_GDB_SCRIPTS=y` * `CONFIG_FRAME_POINTER=y` 2. Boot the QEMU virtual machine with debug feature Append `-S` and `-s` to **QEMU** command: ``` $ qemu-system-riscv64 -h ... -S freeze CPU at startup (use 'c' to start execution) -overcommit [mem-lock=on|off][cpu-pm=on|off] run qemu with overcommit hints mem-lock=on|off controls memory lock support (default: off) cpu-pm=on|off controls cpu power management (default: off) -gdb dev accept gdb connection on 'dev'. (QEMU defaults to starting the guest without waiting for gdb to connect; use -S too if you want it to not start execution.) -s shorthand for -gdb tcp::1234 ``` The overall command to boot the QEMU virtual machine including a virtual network device: ```shell $ qemu-system-riscv64 -M virt -smp 4 -m 2G -display none -serial stdio -kernel ~/linux-stable/arch/riscv/boot/Image -append "console=ttyS0 root=/dev/vda2 rw rootfstype=ext4" -drive file=/tmp/simple-alpine-qemu_riscv64.img,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -netdev user,id=usernet -device virtio-net-device,netdev=usernet -s -S ``` Note: It freezes CPU at startup 3. Start **RISC-V 64's GDB** in the linux project folder, then debug ``` $ sudo pacman -S riscv64-linux-gnu-gdb $ cd ~/linux-stable && riscv64-linux-gnu-gdb vmlinux GNU gdb (GDB) 13.1 Copyright (C) 2023 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> ... Reading symbols from vmlinux... (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x0000000000001000 in ?? () (gdb) break virtnet_probe Breakpoint 1 at 0xffffffff806b87dc: file drivers/net/virtio_net.c, line 3879. (gdb) continue Continuing. [Switching to Thread 1.2] Thread 2 hit Breakpoint 1, virtnet_probe (vdev=0xff60000001e6b040) at drivers/net/virtio_net.c:3879 3879 { (gdb) list 3874 vi->big_packets_num_skbfrags = guest_gso ? MAX_SKB_FRAGS : DIV_ROUND_UP(mtu, PAGE_SIZE); 3875 } 3876 } 3877 3878 static int virtnet_probe(struct virtio_device *vdev) 3879 { 3880 int i, err = -ENOMEM; 3881 struct net_device *dev; 3882 struct virtnet_info *vi; 3883 u16 max_queue_pairs; (gdb) ``` The QEMU virtual machine stops at the break point `virtnet_probe at drivers/net/virtio_net.c:3879` ![](https://hackmd.io/_uploads/rJIIfzLHn.png) ## Reference * QEMU: [‘virt’ Generic Virtual Platform (virt)](https://www.qemu.org/docs/master/system/riscv/virt.html) * QEMU: [Documentation/Platforms/RISCV](https://wiki.qemu.org/Documentation/Platforms/RISCV) * [Let's trace Linux Lernel with KGDB @ COSCUP 2021](https://www.slideshare.net/chienhungpan/lets-trace-linux-kernel-with-kgdb-coscup-2021) * [OpenSBI](https://github.com/riscv-software-src/opensbi) * [OpenSBI Deep Dive](https://riscv.org/wp-content/uploads/2019/06/13.30-RISCV_OpenSBI_Deep_Dive_v5.pdf)