RISC-V open-source architecture is starting to become more and more interesting thanks to the growing RISC-V hardware & software ecosystem, and with the recent release of HiFive Unleashed, we even have a board capable of running Linux. The only problem: it costs $999.
But luckily, it’s possible to experiment with Linux on RISC-V without extra hardware, just using your current PC. Imperas offers a commercial solution working on both Windows and Linux that relies on busybear-linux RISC-V Linux root filesystem comprised of busybox and dropbear SSH server. The rootfs also works with QEMU, so I tried it in Ubuntu 16.04.
The instructions on Github are quite easy to follow. My computer is powered by an AMD FX8350 processor coupled with 16GB RAM, and the whole process took around 2 hours, so better use the fastest computer possible. It also requires around 26 GB of storage on your build machine.
First, let’s create a working directory, and retrieve the RISC-V toolchain:
1 2 3 |
mkdir riscv-linux cd riscv-linux/ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain |
Now we can now build the RISC-V newlib & Linux toolchains) after installing some dependencies:
1 2 3 4 5 6 7 |
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev cd riscv-gnu-toolchain ./configure --prefix=/opt/riscv --enable-multilib make newlib -j8 make linux -j8 export PATH=$PATH:/opt/riscv/bin export RISCV=/opt/riscv |
We’ll also need to build qemu for RISC-V
1 2 3 4 5 6 |
cd .. git clone https://github.com/riscv/riscv-qemu.git cd riscv-qemu ./configure --target-list=riscv64-softmmu,riscv32-softmmu make -j8 sudo make install |
The next three steps will build the rootfs, Linux 4.14 kernel, and the bootloader, but there are optional since you could just as well as download the binary releases.
- Build busybear-linux
1 2 3 4 |
cd .. git clone https://github.com/michaeljclark/busybear-linux.git cd busybear-linux make -j8 |
- Build RISC-V Linux
1 2 3 4 5 6 7 |
cd.. git clone https://github.com/riscv/riscv-linux.git cd riscv-linux git checkout riscv-linux-4.14 cp ../busybear-linux/conf/linux.config .config make ARCH=riscv olddefconfig make ARCH=riscv vmlinux -j8 |
- Build BBL (Berkeley Boot Loader):
1 2 3 4 5 6 7 |
cd.. git clone https://github.com/riscv/riscv-pk.git cd riscv-pk mkdir build cd build ../configure --enable-logo --host=riscv64-unknown-elf --with-payload=../../riscv-linux/vmlinux make -j8 |
If we’re going to use the release files instead:
1 2 3 4 5 |
mkdir release cd release wget https://github.com/michaeljclark/busybear-linux/releases/download/v1.0/bbl.bz2 wget https://github.com/michaeljclark/busybear-linux/releases/download/v1.0/busybear.bin.bz2 bzip2 -d *.bz2 |
You’d normally want to setup Linux bridged networking, and I tried, but failed and ran out of time. I added the following lines to /etc/network/interfaces in my computer:
1 2 3 4 5 6 |
iface br0 inet static bridge_ports eth0 address 192.168.100.1 netmask 255.255.255.0 network 192.168.100.0 broadcast 192.168.100.255 |
and create two scripts in the current directory
- ifup
1 2 3 4 |
#!/bin/sh brctl addif br0 $1 ifconfig $1 up |
- ifdown
1 2 3 4 |
#!/bin/sh ifconfig $1 down brctl delif br0 $1 |
But I did not get it to work in a reasonable time. Studying QEMU Networking page on Arch Linux in details should help. [Update: See comments’ section for SSH access using the Fedora RISC-V image instead]
Nevertheless I could still run Linux on RISC-V with QEMU using the following command:
1 |
sudo qemu-system-riscv64 -nographic -machine virt -kernel bbl -append "root=/dev/vda ro console=ttyS0" -drive file=busybear.bin,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -netdev type=tap,script=./ifup,downscript=./ifdown,id=net0 -device virtio-net-device,netdev=net0 |
The boot takes just over one second to our minimal rootfs. Here’s the boot log:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv rr vvvvvvvvvvvvvvvvvvvvvv rr vvvvvvvvvvvvvvvvvvvvvvvv rr rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr INSTRUCTION SETS WANT TO BE FREE [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000 [ 0.000000] Linux version 4.14.0-00032-gd10799b22913-dirty (mclark@minty) (gcc version 7.1.1 20170509 (GCC)) #79 Sun Dec 17 10:41:31 NZDT 2017 [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000080200000-0x0000000087ffffff] [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node [ 0.000000] Early memory node ranges [ 0.000000] node 0: [mem 0x0000000080200000-0x0000000087ffffff] [ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x0000000087ffffff] [ 0.000000] elf_hwcap is 0x112d [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 31815 [ 0.000000] Kernel command line: root=/dev/vda ro console=ttyS0 [ 0.000000] PID hash table entries: 512 (order: 0, 4096 bytes) [ 0.000000] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes) [ 0.000000] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes) [ 0.000000] Sorting __ex_table... [ 0.000000] Memory: 122496K/129024K available (2658K kernel code, 216K rwdata, 652K rodata, 96K init, 782K bss, 6528K reserved, 0K cma-reserved) [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] NR_IRQS: 0, nr_irqs: 0, preallocated irqs: 0 [ 0.000000] riscv,cpu_intc,0: 64 local interrupts mapped [ 0.000000] riscv,plic0,c000000: mapped 10 interrupts to 1/2 handlers [ 0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns [ 0.000000] Console: colour dummy device 80x25 [ 0.000000] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=100000) [ 0.000000] pid_max: default: 32768 minimum: 301 [ 0.000000] Mount-cache hash table entries: 512 (order: 0, 4096 bytes) [ 0.000000] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes) [ 0.090000] devtmpfs: initialized [ 0.110000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns [ 0.110000] futex hash table entries: 256 (order: 0, 6144 bytes) [ 0.110000] random: get_random_u32 called from bucket_table_alloc+0x80/0x1f6 with crng_init=0 [ 0.110000] NET: Registered protocol family 16 [ 0.140000] vgaarb: loaded [ 0.150000] clocksource: Switched to clocksource riscv_clocksource [ 0.170000] NET: Registered protocol family 2 [ 0.170000] TCP established hash table entries: 1024 (order: 1, 8192 bytes) [ 0.170000] TCP bind hash table entries: 1024 (order: 1, 8192 bytes) [ 0.170000] TCP: Hash tables configured (established 1024 bind 1024) [ 0.180000] UDP hash table entries: 256 (order: 1, 8192 bytes) [ 0.180000] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes) [ 0.180000] NET: Registered protocol family 1 [ 0.190000] workingset: timestamp_bits=62 max_order=15 bucket_order=0 [ 0.220000] random: fast init done [ 0.270000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254) [ 0.270000] io scheduler noop registered [ 0.270000] io scheduler deadline registered [ 0.270000] io scheduler cfq registered (default) [ 0.270000] io scheduler mq-deadline registered [ 0.270000] io scheduler kyber registered [ 0.380000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.390000] console [ttyS0] disabled [ 0.400000] 10000000.uart: ttyS0 at MMIO 0x10000000 (irq = 1, base_baud = 230400) is a 16550A [ 0.430000] console [ttyS0] enabled [ 0.480000] NET: Registered protocol family 10 [ 0.490000] Segment Routing with IPv6 [ 0.490000] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver [ 0.520000] EXT4-fs (vda): couldn't mount as ext3 due to feature incompatibilities [ 0.520000] EXT4-fs (vda): INFO: recovery required on readonly filesystem [ 0.530000] EXT4-fs (vda): write access will be enabled during recovery [ 0.610000] EXT4-fs (vda): recovery complete [ 0.620000] EXT4-fs (vda): mounted filesystem with ordered data mode. Opts: (null) [ 0.630000] VFS: Mounted root (ext4 filesystem) readonly on device 254:0. [ 0.630000] devtmpfs: mounted [ 0.640000] Freeing unused kernel memory: 96K [ 0.640000] This architecture does not have kernel memory protection. [ 0.970000] EXT4-fs (vda): re-mounted. Opts: data=ordered ucbvax login: |
We can login with root using password “busybear” without quote.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
ucbvax login: root Password: ____ ____ __ _ / __ )__ _________ __/ __ )___ ____ ______ / / (_)___ __ ___ __ / __ / / / / ___/ / / / __ / _ \/ __ `/ ___/ / / / / __ \/ / / / |/_/ / /_/ / /_/ (__ ) /_/ / /_/ / __/ /_/ / / / /___/ / / / / /_/ /> < /_____/\__,_/____/\__, /_____/\___/\__,_/_/ /_____/_/_/ /_/\__,_/_/|_| /____/ root@ucbvax:~# uname -a Linux ucbvax 4.14.0-00032-gd10799b22913-dirty #79 Sun Dec 17 10:41:31 NZDT 2017 riscv64 GNU/Linux root@ucbvax:~# df -h Filesystem Size Used Available Use% Mounted on /dev/root 58.0M 44.9M 8.6M 84% / devtmpfs 59.8M 0 59.8M 0% /dev none 59.9M 0 59.9M 0% /tmp none 59.9M 0 59.9M 0% /var/tmp root@ucbvax:~# cat /proc/cpuinfo hart : 0 isa : rv64imafdcsu mmu : sv48 root@ucbvax:~# busybox BusyBox v1.27.2 (2017-12-15 12:14:50 NZDT) multi-call binary. BusyBox is copyrighted by many authors between 1998-2015. Licensed under GPLv2. See source distribution for detailed copyright notices. Usage: busybox [function [arguments]...] or: busybox --list[-full] or: busybox --install [-s] [DIR] or: function [arguments]... BusyBox is a multi-call binary that combines many common Unix utilities into a single executable. Most people will create a link to busybox for each function they wish to use and BusyBox will act like whatever it was invoked as. Currently defined functions: [, [[, add-shell, addgroup, adduser, ar, arp, arping, ash, awk, base64, basename, blkid, blockdev, brctl, bunzip2, bzcat, bzip2, cal, cat, chattr, chgrp, chmod, chown, chpasswd, chroot, chrt, cksum, clear, comm, cp, cpio, crond, crontab, cut, date, dd, delgroup, deluser, df, diff, dirname, dmesg, dos2unix, dpkg, dpkg-deb, du, echo, ed, egrep, env, expand, expr, factor, fallocate, false, fdisk, fgrep, find, findfs, flock, fold, fsck, fsfreeze, fsync, fuser, getty, grep, groups, gunzip, gzip, halt, head, hostid, hostname, id, ifconfig, ifdown, ifup, inetd, init, install, iostat, ip, ipaddr, iplink, ipneigh, iproute, iprule, iptunnel, kill, killall, klogd, last, less, link, ln, logger, login, logname, logread, losetup, ls, lsattr, lsof, lspci, lsscsi, lsusb, lzcat, lzma, makedevs, man, md5sum, microcom, mkdir, mkdosfs, mke2fs, mkfifo, mkfs.ext2, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, more, mount, mv, nameif, nc, netstat, nice, nl, nohup, nproc, nslookup, ntpd, od, partprobe, passwd, paste, patch, pgrep, pidof, ping, ping6, pipe_progress, pivot_root, pkill, pmap, poweroff, printenv, printf, ps, pstree, pwd, pwdx, rdev, readlink, realpath, reboot, remove-shell, renice, reset, rev, rm, rmdir, route, rpm, rpm2cpio, run-parts, runlevel, script, sed, seq, setpriv, setserial, setsid, sh, sha1sum, sha256sum, sha3sum, sha512sum, shred, shuf, sleep, sort, split, ssl_client, start-stop-daemon, stat, strings, stty, su, sum, swapoff, swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar, taskset, tee, telnet, test, time, timeout, top, touch, tr, traceroute, traceroute6, true, truncate, tty, tunctl, tune2fs, udhcpc, uevent, umount, uname, uncompress, unexpand, uniq, unix2dos, unlink, unlzma, unshare, unxz, unzip, uptime, users, usleep, uudecode, uuencode, vi, w, wall, watch, wc, wget, which, who, whoami, whois, xargs, xxd, xz, xzcat, yes, zcat |
Type halt to turn off Linux and QEMU:
1 2 3 4 5 6 7 8 9 |
root@ucbvax:~# halt root@ucbvax:~# umount: devtmpfs busy - remounted read-only umount: can't remount /dev/root read-only The system is going down NOW! Sent SIGTERM to all processes Sent SIGKILL to all processes Requesting system halt [ 410.790000] reboot: System halted Power off |
Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
Thanks for the very useful article!
You are also welcome to use Fedora RISC-V stage 4 image with thousands of packages compiled natively and available via DNF. Find the latest disk images and instructions (special riscv-qemu package is available via Copr repository): https://fedorapeople.org/groups/risc-v/disk-images/
There is also a 2 part article on LWN. The first part was posted a couple of days ago and Fedora specific one should be posted next week.
“ucbvax” … is that a joke referring to University of California Berkeley VAX?
@davidlt Thanks for letting me know. I did a quick try, and it works fine: wget https://fedorapeople.org/groups/risc-v/disk-images/stage4-disk.img.xz wget https://fedorapeople.org/groups/risc-v/disk-images/bbl wget https://fedorapeople.org/groups/risc-v/disk-images/vmlinux xz -d stage4-disk.img.xz qemu-system-riscv64 \ -nographic \ -machine virt \ -smp 4 \ -m 2G \ -kernel bbl \ -object rng-random,filename=/dev/urandom,id=rng0 \ -device virtio-rng-device,rng=rng0 \ -append "console=ttyS0 ro root=/dev/vda" \ -device virtio-blk-device,drive=hd0 \ -drive file=stage4-disk.img,format=raw,id=hd0 \ -device virtio-net-device,netdev=usernet \ -netdev user,id=usernet,hostfwd=tcp::10000-:22 123456789101112131415161718 wget https://fedorapeople.org/groups/risc-v/disk-images/stage4-disk.img.xzwget https://fedorapeople.org/groups/risc-v/disk-images/bblwget https://fedorapeople.org/groups/risc-v/disk-images/vmlinuxxz -d stage4-disk.img.xz qemu-system-riscv64 \ -nographic \ -machine virt \ -smp 4 \ -m 2G \ -kernel bbl \ -object rng-random,filename=/dev/urandom,id=rng0 \ -device virtio-rng-device,rng=rng0 \ -append "console=ttyS0 ro root=/dev/vda" \ -device virtio-blk-device,drive=hd0 \ -drive file=stage4-disk.img,format=raw,id=hd0 \ -device virtio-net-device,netdev=usernet \ -netdev user,id=usernet,hostfwd=tcp::10000-:22 I could login easily via… Read more »
MTTCG works up to 8 cores (QEMU can utilize 8 cores/threads on your host machine) thus you can speed up compilations of your beloved packages (if missing).
If something is missing or not working properly you can report on IRC #fedora-riscv on FreeNode.
Many thanks for this useful tutorial!
I have faced a minor issue that the kernel can’t finish his boot process because of a problem in mounting the file system, I got the error message:
can’t open /dev/ttyS0: No such file or directory
The solution was to enable the following options in the configuration:
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
To enable these options:
make ARCH=riscv menuconfig
>Device Drivers > Generic Driver Options:
[*] Maintain a devtmpfs filesystem to mount at /dev
[*] Automount devtmpfs at /dev, after the kernel mounted the rootfs
i am facing the same issue, but i didnt understand the solution for this, please help me.
i added CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y these two lines in linux.congif file then also getting same error.
Hi Jean, Thanks for the article, which is very useful for the beginners exploring RISC-V, while following steps above in Ubuntu 16.04 i got following errors, can you please suggest some fix. i gave the following final command sudo qemu-system-riscv64 -nographic -machine virt -kernel bbl -append “root=/dev/vda ro console=ttyS0” -drive file=busybear.bin,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -netdev type=tap,script=./ifup,downscript=./ifdown,id=net0 -device virtio-net-device,netdev=net0 I got the following errors and warnings bridge br0 does not exist! qemu-system-riscv64: warning: No -bios option specified. Not loading a firmware. qemu-system-riscv64: warning: This default will change in a future QEMU release. Please use the -bios option to avoid breakages when this happens. qemu-system-riscv64: warning: See QEMU’s… Read more »
It looks like bbl file is not in your directory
actually bbl directory is there at riscv-pk directory and I am running command at busybear-linux directory, then i copied bbl folder to busybear-linux directory and gave command again at busybear-linux directory again getting error like this
bridge br0 does not exist!
qemu-system-riscv64: warning: No -bios option specified. Not loading a firmware.
qemu-system-riscv64: warning: This default will change in a future QEMU release. Please use the -bios option to avoid breakages when this happens.
qemu-system-riscv64: warning: See QEMU’s deprecation documentation for details.
qemu-system-riscv64: could not load kernel ‘bbl’
bridge br0 does not exist!
busybear-linux qemu release riscv-gnu-toolchain riscv-linux riscv-pk(my folder structure)
If I remember correctly, you need to use bbl file, not a directory
This is the only channel to contact you, Is there any other channel to contact you, to clarify my doubts and bring risc-v up on Linux with QEMU, I would be grateful if you help me.
Thanks in Advance