RISC-V program development using QEMU
RISC-V
- https://en.wikipedia.org/wiki/RISC-V
- https://github.com/riscv/riscv-software-list
- https://riscv.org/specifications/
In a nutshell
RISC-V (pronounced “risk-five”) is an open source instruction set architecture (ISA) based on established reduced instruction set computing (RISC) principles.
The project began in 2010 at the University of California, Berkeley, but many contributors are volunteers not affiliated with the university.
In contrast to most ISAs, RISC-V is freely available for all types of use, permitting anyone to design, manufacture and sell RISC-V chips and software. While not the first open ISA, it is significant because it is designed to be useful in modern computerized devices such as warehouse-scale cloud computers, high-end mobile phones and the smallest embedded systems. Such uses demand that the designers consider both performance and power efficiency. The instruction set also has a substantial body of supporting software, which fixes the usual weakness of new instruction sets.
Hardware baseline and ABI choice
There are different versions of the instruction set for 32, 64 and 128 bits; operating as little-endian by default.
- RV32I, most is microcontroller unit (MCU) class RV32IMC
- RV32E, for embedded systems
- RV64I, most Linux distro use RV64GC as the hardware baseline and the lp64d ABI (little-endian, the default ABI for RV64G systems).
- RV128I, simply not realistic at this time.
The base set of RISC-V is the Base Integer Instruction Set “RV32/64/128I” or “RV32E” (a reduced version of RV32I that supports only 16 registers designed for embedded systems).
A computer with the instruction sets “IMAFD”, is said to be “general-purpose”, summarized as “G”, so it an “RV64IMAFDC” can also be described as an “RV64GC”. Together with the “privileged” instruction set extension an “RVGC” defines all instructions needed to conveniently support a Unix-style operating system.
Extension | Description | Version | Frozen? |
---|---|---|---|
M | Standard Extension for Integer Multiplication and Division | 2.0 | Yes |
A | Standard Extension for Atomic Instructions | 2.0 | Yes |
F | Standard Extension for Single-Precision Floating-Point | 2.0 | Yes |
D | Standard Extension for Double-Precision Floating-Point | 2.0 | Yes |
Q | Standard Extension for Quad-Precision Floating-Point | 2.0 | Yes |
C | Standard Extension for Compressed Instructions | 2.0 | Yes |
L | Standard Extension for Decimal Floating-Point | 0.0 | No |
B | Standard Extension for Bit Manipulation | 0.0 | No |
J | Standard Extension for Dynamically Translated Languages | 0.0 | No |
T | Standard Extension for Transactional Memory | 0.0 | No |
P | Standard Extension for Packed-SIMD Instructions | 0.1 | No |
V | Standard Extension for Vector Operations | 0.2 | No |
N | Standard Extension for User-Level Interrupts | 1.1 | No |
Qemu setup
install packages
sudo apt install qemu-system-misc qemu-user-static binfmt-support u-boot-qemu opensbi libc6-riscv64-cross gcc-riscv64-linux-gnu
sudo ln -s /usr/riscv64-linux-gnu/lib/ld-linux-riscv64-lp64d.so.1 /lib
sudo sh -c "cat >/etc/ld.so.conf.d/riscv64-linux-gnu.conf << EOF
/usr/riscv64-linux-gnu/lib/
EOF
"
LD_LIBRARY_PATH=/usr/riscv64-linux-gnu/lib qemu-riscv64-static a.out
/usr/bin/qemu-system-riscv64
/usr/lib/riscv64-linux-gnu/opensbi/qemu/virt/fw_dynamic.elf
/usr/lib/riscv64-linux-gnu/opensbi/qemu/virt/fw_jump.elf
/usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin
register riscv64 interpreter
sudo update-binfmts --import << EOF
package qemu-user-static
interpreter /usr/bin/qemu-riscv64-static
type magic
offset 0
magic \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
EOF
Setting up a riscv64 virtual machine
debootstrap of riscv64
sudo apt-get install debootstrap qemu-user-static binfmt-support debian-ports-archive-keyring
sudo debootstrap --arch=riscv64 --keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg \
--include=curl,jq,wget,locales,debian-ports-archive-keyring --merged-usr --foreign \
unstable /tmp/riscv64-chroot http://deb.debian.org/debian-ports
sudo chroot /tmp/riscv64-chroot
cat > /debootstrap/mirror << EOF
http://deb.debian.org/debian-ports
EOF
/debootstrap/debootstrap --second-stage
localedef -c -i en_US -f UTF-8 en_US.UTF-8
localedef -c -i zh_CN -f UTF-8 zh_CN.UTF-8
localedef --list-archive
passwd
ln -sf /dev/null /etc/systemd/system/serial-getty@hvc0.service
cat > /etc/resolv.conf << EOF
nameserver 1.1.1.1
nameserver 8.8.8.8
EOF
cat > /etc/apt/apt.conf.d/zz-10-install << EOF
APT::Install-Recommends "0";
APT::Install-Suggests "0";
Acquire::http { Proxy "http://proxy.example.com:8080"; };
EOF
cat > /etc/apt/sources.list << EOF
deb http://ftp.ports.debian.org/debian-ports unstable main
# deb http://ftp.ports.debian.org/debian-ports unreleased main
# deb http://ftp.ports.debian.org/debian-ports experimental main
EOF
apt-get update
apt-get install --no-install-recommends linux-image-riscv64 u-boot-menu openntpd ntpdate
sed -i 's/^DAEMON_OPTS="/DAEMON_OPTS="-s /' /etc/default/openntpd
cat >> /etc/default/u-boot <<EOF
U_BOOT_PARAMETERS="rw noquiet root=/dev/vda1"
EOF
u-boot-update
cat >> /etc/network/interfaces <<EOF
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF
Create rootfs.img
truncate -s 4G rootfs.img
losetup --find rootfs.img
losetup -a
fdisk /dev/loop0
partprobe -s /dev/loop0
mkswap /dev/loop0p2
mkfs.ext4 /dev/loop0p1
mount /dev/loop0p1 riscv64-root/
cp -aP riscv64-chroot/* riscv64-root/
losetup --detach /dev/loop0
Run qemu-system-riscv64
# qemu-system-riscv64 -nographic -machine virt -m 1.9G \
-kernel /usr/lib/riscv64-linux-gnu/opensbi/qemu/virt/fw_jump.elf \
-device loader,file=/usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin,addr=0x80200000 \
-object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-device,rng=rng0 \
-append "console=ttyS0 rw root=/dev/vda1" \
-device virtio-blk-device,drive=hd0 -drive file=rootfs.img,format=raw,id=hd0 \
-device virtio-net-device,netdev=usernet -netdev user,id=usernet,hostfwd=tcp::22222-:22
# qemu-system-riscv64 -nographic -machine virt -m 1.9G \
-kernel /usr/lib/riscv64-linux-gnu/opensbi/qemu/virt/fw_jump.elf \
-object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-device,rng=rng0 \
-append "root=/dev/vda1 ro console=ttyS0" \
-device virtio-blk-device,drive=hd0 -drive file=rootfs.img,format=raw,id=hd0 \
-device virtio-net-device,netdev=net0 -netdev type=tap,id=net0,ifname=tap0,script=no,downscript=no
ip link add br0 type bridge
ip tuntap add dev tap0 mode tap user $(whoami)
ip link set dev tap0 master br0
# ip addr flush dev eth0
# ip link set dev eth0 master br0
ip link set dev br0 up
ip link set dev tap0 up
# ip address delete $PREFIX dev eth0
# ip address add $PREFIX dev br0
# ip route add default via $ROUTE dev br0
qemu-system-riscv64: plic: invalid register write: 000001fc
Platform Name : QEMU Virt Machine
Platform HART Features : RV64ACDFIMSU
Platform Max HARTs : 8
Current Hart : 0
Firmware Base : 0x80000000
Firmware Size : 112 KB
Runtime SBI Version : 0.1
PMP0: 0x0000000080000000-0x000000008001ffff (A)
PMP1: 0x0000000000000000-0xffffffffffffffff (A,R,W,X)
CPU: rv64imafdcsu
Model: riscv-virtio,qemu
DRAM: 1.9 GiB
date -s -d'2018-05-07T21:28:57'
date -u [MMDDhhmm[[CC]YY][.ss]]
date -u 123109322018