The RISC-V Files - Part 1: Dipping a Toe

The RISC-V Files - Part 1: Dipping a Toe

An old fart documents his exploration of a new technology


11 min read

Free and open-source software is now a core part of how technology moves forward. Even if you actively avoid using it, you’re still using it; try to create the most proprietary system you can envisage, and under the hood, it is held together with open-source glue.

Hardware is another matter: until recently even if you used exclusively open-source applications, with an open-source operating system, running on a machine you made yourself, you’re likely still depending on big chunks of proprietary hardware. Go further, and even if you manage to get hold of a machine that uses a FOSS BIOS, and has the insidious hidden system management OSs disabled, it’s almost certainly running a proprietary processor — that includes Intel, AMD and ARM.

Why does it matter? Well, there are many reasons to be concerned about this, but probably the most significant is that you can never be sure what is going on inside the box. That means you can never be sure of your security and privacy when using the device. So, when the Internet started talking about creating an open-source CPU, it was quite an exciting prospect. If it ever happened.

Well, a decade or so later, it has happened, and without a huge fanfare it’s widely available. It’s called RISC-V (pronounced “risk five”) and whether it becomes any more than a niche oddity we can’t say, but the take-up from the chip producers suggests it’s already making a considerable impact.

So, as a strong FOSS supporter, I wanted a piece of the action. This series of posts attempts to document my experiences of exploring RISC-V.

What does an Open-Source Processor even mean?

Full disclosure: I know next to nothing about processor design but have been coding for decades, ranging from desktop apps to firmware and embedded systems. This whole thing is a learning experience for me, but I thought other people may get something from it. By all means, contact me with corrections.

One of the main benefits of Open-Source software is that, if you are so inclined, you can examine and even modify the code yourself. Even if you’re not interested in or capable of that, the knowledge that there will be plenty of other people who actively do examine the code should give you some confidence that the code is probably safe. But how can you do that with a processor? Rent an electron microscope? This is a good point, and it’s fair to admit that just because a chip is open-source, it isn't necessarily free from back doors or trojans. However, having the source for the chip is a good start, and if you’re really worried you can take the source and make your own chip. But what do we mean by the “source” for the chip?

Nowadays, processors are essentially designed in software. Rather than have people laying out transistors on huge sheets of photographic paper, computers worry about the layouts and humans just need a way to explain to the computer what they want the chip to do. The way they do that is by using a “Hardware Definition Language” which is like a regular programming language but designed for describing parts of chip hardware.

Once the design is completed, the HDL can be turned into a real, tangible processor either by being used to configure an FPGA or by being sent to a manufacturing company that can turn the design into custom silicon.

Intel and AMD design and make their own chips, but keep the HDL source code proprietary and therefore not available for examination or modification by us ordinary folk. ARM is slightly different, they don’t actually make chips, they just produce designs and then chip manufacturers pay them fees to license the design for use in their own products. We mere mortals can't get our hands on that source code either.

That's where RISC-V comes in. It's a completely open-source specification for a RISC-based processor or, more correctly, an Instruction Set Architecture (ISA). Using this specification, people are free to implement and produce their own RISC-V processors.

Obviously, this still requires someone to sit down and design the actual processor, so you may be wondering why anyone would bother using the specification rather than just invent their own. There are many reasons for this, but here are a few key points.

Firstly, designing your own ISA is hard, and full of pitfalls. The RISC-V specification was designed in public by a large group of experts who have learned from experience what works and what doesn't.

Secondly, other people won't want to target a new one-off platform for their applications unless there's a chance that it'll be used elsewhere and continue to be developed.

Thirdly, the RISC-V specification is really quite good! We'll cover the design aspects in a later post. For now, let's get some practical experience...

OpenBSD on RISC-V: a practical example

In an attempt to demonstrate how widespread and well-supported RISC-V is already, here's an example you can run right now, and all you need is Docker. If you have it installed then try running:

docker run -it dreadtech/qmu-riscv-openbsd

This should pull down, and run, a docker image that fires-up a virtual RISC-V machine which, in turn, boots a fully-fledged installation of OpenBSD.

Here is an example session:

OpenSBI v0.9
   ____                    _____ ____ _____
  / __ \                  / ____|  _ \_   _|
 | |  | |_ __   ___ _ __ | (___ | |_) || |
 | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
 | |__| | |_) |  __/ | | |____) | |_) || |_
  \____/| .__/ \___|_| |_|_____/|____/_____|
        | |

Platform Name             : riscv-virtio,qemu
Platform Features         : timer,mfdeleg
Platform HART Count       : 1
Firmware Base             : 0x80000000
Firmware Size             : 100 KB
Runtime SBI Version       : 0.2

Domain0 Name              : root
Domain0 Boot HART         : 0
Domain0 HARTs             : 0*
Domain0 Region00          : 0x0000000080000000-0x000000008001ffff ()
Domain0 Region01          : 0x0000000000000000-0xffffffffffffffff (R,W,X)
Domain0 Next Address      : 0x0000000080200000
Domain0 Next Arg1         : 0x0000000082200000
Domain0 Next Mode         : S-mode
Domain0 SysReset          : yes

Boot HART ID              : 0
Boot HART Domain          : root
Boot HART ISA             : rv64imafdcsuh
Boot HART Features        : scounteren,mcounteren,time
Boot HART PMP Count       : 16
Boot HART PMP Granularity : 4
Boot HART PMP Address Bits: 54
Boot HART MHPM Count      : 0
Boot HART MHPM Count      : 0
Boot HART MIDELEG         : 0x0000000000001666
Boot HART MEDELEG         : 0x0000000000f0b509

U-Boot 2022.01+dfsg-2ubuntu2.3 (Nov 24 2022 - 19:40:06 +0000)

CPU:   rv64imafdch_zicsr_zifencei_zba_zbb_zbc_zbs
Model: riscv-virtio,qemu
DRAM:  1 GiB
Flash: 32 MiB
Loading Environment from nowhere... OK
In:    uart@10000000
Out:   uart@10000000
Err:   uart@10000000
Net:   eth0: virtio-net#0
Hit any key to stop autoboot:  0

Device 0: QEMU VirtIO Block Device
            Type: Hard Disk
            Capacity: 81920.0 MB = 80.0 GB (167772160 x 512)
... is now current device
Scanning virtio 0:1...
** Unable to read file / **
Failed to load '/'
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Scanning disk virtio-blk#1...
Found 3 disks
No EFI system partition
BootOrder not defined
EFI boot manager: Cannot load any image
Found EFI removable media binary efi/boot/bootriscv64.efi
152938 bytes read in 3 ms (48.6 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootriscv64.efi
disks: sd0*
>> OpenBSD/riscv64 BOOTRISCV64 1.4
booting sd0a:/bsd: 5245444+1304392+203824+698664 [345786+122+473256+339178]=0x9f75f0
all mapped
type 0x4 pa 0x80000000 va 0x80000000 pages 0x20 attr 0x8
type 0x7 pa 0x80020000 va 0x80020000 pages 0x1e0 attr 0x8
type 0x2 pa 0x80200000 va 0x80200000 pages 0x4000 attr 0x8
type 0x7 pa 0x84200000 va 0x84200000 pages 0x3cfb attr 0x8
type 0x9 pa 0x87efb000 va 0x87efb000 pages 0xa attr 0x8
type 0x7 pa 0x87f05000 va 0x87f05000 pages 0x366ed attr 0x8
type 0x2 pa 0xbe5f2000 va 0xbe5f2000 pages 0x3 attr 0x8
type 0x4 pa 0xbe5f5000 va 0xbe5f5000 pages 0x1 attr 0x8
type 0x7 pa 0xbe5f6000 va 0xbe5f6000 pages 0x1 attr 0x8
type 0x2 pa 0xbe5f7000 va 0xbe5f7000 pages 0x100 attr 0x8
type 0x1 pa 0xbe6f7000 va 0xbe6f7000 pages 0x26 attr 0x8
type 0x4 pa 0xbe71d000 va 0xbe71d000 pages 0x8 attr 0x8
type 0x6 pa 0xbe725000 va 0xbe725000 pages 0x1 attr 0x8000000000000008
type 0x4 pa 0xbe726000 va 0xbe726000 pages 0x3 attr 0x8
type 0x6 pa 0xbe729000 va 0xbe729000 pages 0x3 attr 0x8000000000000008
type 0x4 pa 0xbe72c000 va 0xbe72c000 pages 0x1 attr 0x8
type 0x6 pa 0xbe72d000 va 0xbe72d000 pages 0x4 attr 0x8000000000000008
type 0x4 pa 0xbe731000 va 0xbe731000 pages 0x8 attr 0x8
type 0x2 pa 0xbe739000 va 0xbe739000 pages 0x1822 attr 0x8
type 0x5 pa 0xbff5b000 va 0xbff5b000 pages 0x1 attr 0x8000000000000008
type 0x2 pa 0xbff5c000 va 0xbff5c000 pages 0xa4 attr 0x8
[ using 1159320 bytes of bsd ELF symbol table ]
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.
Copyright (c) 1995-2022 OpenBSD. All rights reserved.

OpenBSD 7.2-current (GENERIC) #237: Thu Dec 29 02:02:55 MST 2022
real mem  = 1073741824 (1024MB)
avail mem = 987426816 (941MB)
SBI: OpenSBI v0.9, SBI Specification Version 0.2
random: good seed from bootblocks
mainbus0 at root: riscv-virtio,qemu
cpu0 at mainbus0: vendor 0 arch 70100 imp 70100 rv64imafdch_zicsr_zifencei_zba_z�O��� �$3�����
intc0 at cpu0
"fw-cfg" at mainbus0 not configured
"flash" at mainbus0 not configured
simplebus0 at mainbus0: "platform"
simplebus1 at mainbus0: "soc"
syscon0 at simplebus1: "poweroff"
syscon1 at simplebus1: "reboot"
syscon2 at simplebus1: "test"
plic0 at simplebus1
gfrtc0 at simplebus1
com0 at simplebus1: ns16550, no working fifo
com0: console
pciecam0 at simplebus1
pci0 at pciecam0
"Red Hat Host" rev 0x00 at pci0 dev 0 function 0 not configured
virtio0 at simplebus1: Virtio Network Device
vio0 at virtio0: address 52:54:00:12:34:56
virtio1 at simplebus1: Virtio Block Device
vioblk0 at virtio1
scsibus0 at vioblk0: 1 targets
sd0 at scsibus0 targ 0 lun 0: <VirtIO, Block Device, >
sd0: 81920MB, 512 bytes/sector, 167772160 sectors
virtio2 at simplebus1: Virtio Unknown (0) Device
virtio3 at simplebus1: Virtio Unknown (0) Device
virtio4 at simplebus1: Virtio Unknown (0) Device
virtio5 at simplebus1: Virtio Unknown (0) Device
virtio6 at simplebus1: Virtio Unknown (0) Device
virtio7 at simplebus1: Virtio Unknown (0) Device
"clint" at simplebus1 not configured
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
scsibus2 at softraid0: 256 targets
root on sd0a (26f0a6f34eeb4711.a) swap on sd0b dump on sd0b
Automatic boot in progress: starting file system checks.
/dev/sd0a (26f0a6f34eeb4711.a): file system is clean; not checking
/dev/sd0l (26f0a6f34eeb4711.l): file system is clean; not checking
/dev/sd0d (26f0a6f34eeb4711.d): file system is clean; not checking
/dev/sd0f (26f0a6f34eeb4711.f): file system is clean; not checking
/dev/sd0g (26f0a6f34eeb4711.g): file system is clean; not checking
/dev/sd0h (26f0a6f34eeb4711.h): file system is clean; not checking
/dev/sd0k (26f0a6f34eeb4711.k): file system is clean; not checking
/dev/sd0j (26f0a6f34eeb4711.j): file system is clean; not checking
/dev/sd0e (26f0a6f34eeb4711.e): file system is clean; not checking
pf enabled
starting network
reordering libraries: libc libcrypto.
starting early daemons: syslogd pflogd ntpd.
starting RPC daemons:.
savecore: no core dump
checking quotas: done.
clearing /tmp
kern.securelevel: 0 -> 1
creating runtime link editor directory cache.
preserving editor files.
starting network daemons: smtpd sndiod.
starting local daemons: cron.
Sat Dec 31 17:40:30 EST 2022

OpenBSD/riscv64 ( (console)

login: openbsd
Last login: Sat Dec 31 17:31:24 on console
OpenBSD 7.2-current (GENERIC) #237: Thu Dec 29 02:02:55 MST 2022

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code.  With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

You have new mail.
openbsd$ uname -a
OpenBSD 7.2 GENERIC#237 riscv64

Yeah, it won't be speedy, but it is real OpenBSD, running on an emulated RISC-V system. You can compile and run code in there and generally mess around with RISC-V machine code.

People who've grown up with VMs, docker, and all of that kind of thing [I'm talking about you Gen-Z], will probably be completely unimpressed with this, but it should be an adequate demonstration of how RISC-V is no longer a theoretical idea. The fact that QEMU and OpenBSD both already support this architecture strikes me as significant, anyway.

Obviously, there are plenty of other operating systems that support RISC-V too, including several distributions of Linux. Give them a go.

But what about hard, tangible, corporeal hardware?

Linux on RISC-V hardware

Raspberry Pi changed the landscape so significantly that despite being designed as a product for introducing people -- especially children -- to coding, it now frequently ends up being the core of commercial hardware devices. Testament to that, at the time of writing, it's currently harder to get hold of a Raspberry Pi than a jar of unicorn droppings. Meanwhile, for less than $30 you can get one of these cute little things :

Lichee RV Linux cutey

It's called a Lichee RV; think of this as a baby RPi, but based on a RISC-V core, complete with HDMI, GPIOs, microphones, wireless, and a load of other goodies. The manufacturers also support two versions of Linux: Debian and "Tina"; the latter being a small distribution based on OpenWRT.

Admittedly, the barrier for entry is a little higher than with the RPi; for a start, the documentation is in Chinese. But once translated it's dead easy to get up and running. We'll deal with the details in a later post.

The simplest way to start is to download a specially prepared Debian image, and then copy it to a TF/micro-SD card using your favourite tool. After that, plug the card into the slot on the Lichee. In the photo above it's the little metal thing on the right of the USB socket. In case you are as dim as I, it's worth pointing out that the card goes in, the way this picture is orientated, right-to-left. You do not need to unscrew the module to get it in.

Hook up the HDMI, plug in a USB keyboard, and then connect the USB-C port. At this point, it should boot into Linux like a good little computer.

If you're not interested in the desktop experience, you can hook up a UART cable (e.g. a standard FTDI UART job), as in the photo. Open up a terminal on the machine the cable's plugged into, and plug the USB-C. Hey presto, you're talking to a Debian console.

In case you're interested, I'll go into greater detail about all of these things in future posts. Thanks for reading this far.