Goals:
- Compile a simple application for rv64 ( serial port output/echo )
- Run it on QEMU's "virt" platform ( generic platform not matching any real hw)
- compile and run again, but for rv32i
Required files and dependencies:
riscv64-elf-ubuntu-24.04-gcc.tar.xz
riscv32-elf-ubuntu-24.04-gcc.tar.xz
Instructions:
$ mkdir risc64-elf && cd risc64-elf && tar xvf riscv64-elf-ubuntu-24.04-gcc.tar.xz
$ mkdir risc32-elf && cd risc32-elf && tar xvf riscv32-elf-ubuntu-24.04-gcc.tar.xz
- alias required binaries (from toolchains), so that they are easier to use
$ alias riscv64-elf-gcc="./riscv64-elf/riscv/bin/riscv64-unknown-elf-gcc"
$ alias riscv64-elf-as="./riscv64-elf/riscv/bin/riscv64-unknown-elf-as"
$ alias riscv64-elf-ld="./riscv64-elf/riscv/bin/riscv64-unknown-elf-ld"
$ alias riscv32-elf-gcc="./riscv32-elf/riscv/bin/riscv32-unknown-elf-gcc"
$ alias riscv32-elf-as="./riscv32-elf/riscv/bin/riscv32-unknown-elf-as"
$ alias riscv32-elf-ld="./riscv32-elf/riscv/bin/riscv32-unknown-elf-ld"
### FOR RV64 ###
$ riscv64-elf-gcc -Wall -Wextra -c -mcmodel=medany kernel.c -o kernel.o -ffreestanding
$ riscv64-elf-as -c entry.S -o entry.o
$ riscv64-elf-ld -T linker.ld -lgcc -nostdlib kernel.o entry.o -o kernel.elf
# i got "riscv64-unknown-elf-ld: cannot find -lgcc: no error",
# so had to modify the command a bit (to reference it manually):
$ riscv64-elf-ld -T linker.ld -lgcc -nostdlib kernel.o entry.o -o kernel.elf
--static -L riscv64-elf/riscv/lib/gcc/riscv64-unknown-elf/16.1.0/
### FOR RV32 ###
$ riscv32-elf-gcc -Wall -Wextra -c -mcmodel=medany kernel.c -o kernel32.o -ffreestanding
$ riscv32-elf-as -c entry32.S -o entry32.o
# entry32.S is just entry.S with instruction sd changed to sw (no sd in rv32)
$ riscv32-elf-ld -T linker.ld -lgcc -nostdlib kernel32.o entry32.o -o kernel32.elf
--static -L riscv32-elf/riscv/lib/gcc/riscv32-unknown-elf/16.1.0/
### FOR RV64 ###
$ qemu-system-riscv64 -machine virt -bios none -kernel kernel.elf -serial mon:stdio
### FOR RV32 ###
$ qemu-system-riscv32 -machine virt -bios none -kernel kernel32.elf -serial mon:stdio
# both were generated from the same kernel.c, so for both:
# qemu will launch, running kmain()
# void kmain(void) { //
# print("Hello world!\r\n"); // this will print first
# while(1) { //
# putchar(*uart); // then any input in console will echo
# } // inf loop, so last char will print many times
# return; // to exit QEMU: Ctrl+A, X
#} //