Try   HackMD

Minimal RISC-V core to boot Linux

吳哲郁

Starting point

The codebase is derinved from microxblue/rv32_linux.

Environment Setup

RISC-V GNU Toolchain

You could setup RISCV GNU toolchain by following the instruction in the GitHub repository or as the following.

  1. Get the sources
$ git clone https://github.com/riscv/riscv-gnu-toolchain
  1. Change to the cloned directory
$ cd riscv-bnu-toolchain
  1. Configure the installed path, march and mabi
$ ./configure --prefix=/opt/riscv --with-arch=rv32ima_zicsr --with-abi=ilp32
  1. Install the toolchain
$ make
  1. Add toolchain path to PATH
$ echo `export PATH="/opt/riscv/bin:$PATH"` >> ~/.bashrc
$ source ~/.bashrc

Verilator

Verilator is a software programming tool which converts the hardware description language Verilog to a cycle-accurate behavioral model in the programming languages C++ or SystemC.

Verilator is an open source projects. With it, we can run RTL simulation for this project without needing to use a paid EDA tool.

To install Verilator, please follow the instructions on the official website.

Run Emulation

To boot linux on the emulator, please run the following commands:

  1. Change to to project directory
$ cd rv32_linux
  1. Run emulation
$ make emurun

If the emulation is successfully run, you will see the following boot log on the terminal

[    0.000000] Linux version 6.10.0mini-rv32ima-00001-g9568811284f3-dirty (test@ubuntu) (riscv32-buildroot-linux-uclibc-gcc.br_real (Buildroot -g851edd24) 13.2.0, GNU ld (GNU Binutils) 2.40) #13 Sun Dec 15 11:06:43 PST 2024
[    0.000000] Machine model: riscv-minimal-nommu,qemu
[    0.000000] earlycon: uart8250 at MMIO32 0xffff0400 (options '1000000')
[    0.000000] printk: legacy bootconsole [uart8250] enabled
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000080000000-0x0000000080fbffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080000000-0x0000000080fbffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x0000000080fbffff]
[    0.000000] riscv: base ISA extensions 
[    0.000000] riscv: ELF capabilities 
[    0.000000] Kernel command line: earlycon=uart8250,mmio32,0xffff0400,1000000 console=ttyS0
[    0.000000] Dentry cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[    0.000000] Inode-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] Built 1 zonelists, mobility grouping off.  Total pages: 4032
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 13440K/16128K available (1312K kernel code, 276K rwdata, 143K rodata, 673K init, 92K bss, 2688K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-1, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] riscv-intc: 32 local interrupts mapped
[    0.000000] clint: clint@11000000: timer running at 1000000 Hz
[    0.000000] clocksource: clint_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[    0.000009] sched_clock: 64 bits at 1000kHz, resolution 1000ns, wraps every 2199023255500ns
[    0.002063] Console: colour dummy device 80x25
[    0.002589] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=10000)
[    0.003268] pid_max: default: 32768 minimum: 301
[    0.004069] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.004621] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.016078] devtmpfs: initialized
[    0.024529] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.025213] futex hash table entries: 256 (order: -1, 3072 bytes, linear)
[    0.038745] clocksource: Switched to clocksource clint_clocksource
[    0.109065] workingset: timestamp_bits=30 max_order=12 bucket_order=0
[    0.336988] Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled
[    0.350913] of_serial ffff0400.uart: error -ENXIO: IRQ index 0 not found
[    0.352841] printk: legacy console [ttyS0] disabled
[    0.355949] ffff0400.uart: ttyS0 at MMIO 0xffff0400 (irq = 0, base_baud = 62500) is a 16550
[    0.356768] printk: legacy console [ttyS0] enabled
[    0.356768] printk: legacy console [ttyS0] enabled
[    0.357477] printk: legacy bootconsole [uart8250] disabled
[    0.357477] printk: legacy bootconsole [uart8250] disabled
[    0.387672] clk: Disabling unused clocks
[    0.394137] Freeing unused kernel image (initmem) memory: 668K
[    0.394639] This architecture does not have kernel memory protection.
[    0.395180] Run /init as init process
Welcome to mini-rv32ima Linux
Jan  1 00:00:00 login[21]: root login on 'console'
~ # 

Run RTL Simulation

To boot linux on the RTL simulation, please run the following commands:

  1. Change to the project directory
$ cd rv32_linux
  1. Build simulation firmware
$ make simfw
  1. Change to simulation directory
$ cd Rv32Sim
  1. Run the Verilator compilation process
$ make bld
  1. Change to the project directory and run the simulation
$ cd ..
$ make simrun

Reference