Setting up Rust for RISC-V

Setting up Rust for RISC-V

Rust now supports RISC-V out-of-the-box! This makes it much easier for us to build without needing a toolchain. If you still want to build your own toolchain, the old tutorial is at ch0.old.html

Rust will need a few things, which you can add using the rustup command. If you don’t have rustup, you can download it at https://www.rust-lang.org/tools/install.

  • rustup default nightly
  • rustup target add riscv64-unknown-none-elf
  • cargo install cargo-binutils

Since I use language features (denoted by #![features]), we must use the nightly builds even though RISC-V is on the stable build.

Building

Take a look at the blog git repository at: Github. You will see a file called .cargo/config. You can edit this to match your system.

[build]
target = "riscv64gc-unknown-none-elf"
rustflags = ['-Clink-arg=-Tsrc/lds/virt.lds']

[target.riscv64gc-unknown-none-elf]
runner = "qemu-system-riscv64 -machine virt -cpu rv64 -smp 4 -m 128M -drive if=none,format=raw,file=hdd.dsk,id=foo -device virtio-blk-device,scsi=off,drive=foo -nographic -serial mon:stdio -bios none -device virtio-rng-device -device virtio-gpu-device -device virtio-net-device -device virtio-tablet-device -device virtio-keyboard-device -kernel "	

runner = “qemu-system-riscv64 -machine virt -cpu rv64 -smp 4 -m 128M -drive if=none,format=raw,file=hdd.dsk,id=foo -device virtio-blk-device,scsi=off,drive=foo -nographic -serial mon:stdio -bios none -device virtio-rng-device -device virtio-gpu-device -device virtio-net-device -device virtio-tablet-device -device virtio-keyboard-device -kernel “

The configuration file shows what target we’re building for, which is the riscv64gc target. We also need to specify our linker script so that we put things in the right location, which is in src/lds/virt.lds. Finally, a “runner” is invoked when we type cargo run, which will run the riscv64 qemu. Also, notice that there is a space after -kernel. This is because cargo will automatically specify the executable, whose name is configured through Cargo.toml.

Finished!

That’s the boring part, and assuming everything went well (it does on ArchLinux!), now to the fun parts!