Department of Computer Science and Technology



QEMU-CHERI is an adaptation of the popular QEMU ISA emulator to implement the CHERI-MIPS instruction set. QEMU-CHERI boots CheriBSD and passes all of the CheriBSD MIPS and CheriABI tests. It implements 128-bit compressed capabilities, as well as CHERI-256 capabilities, and "magic" 128-bit capabilities (in which architectural 256-bit capabilities can be compressed to 128 bits without loss when loaded and stored from memory). This latter mode permits easier diagnosis of software bugs associated with 128-bit-sized capabilities vs. those associated specifically with capability compression (e.g., changed alignment requirements). More information on QEMU itself can be found on the QEMU Wiki.

Building and Installing qemu-system-cheri128

On FreeBSD, qemu-system-cheri can be installed using the package command:

# pkg install qemu-cheri128

For 256-bit capabilities use the following instead:

# pkg install qemu-cheri

It can also be installed using FreeBSD ports:

# cd /usr/ports/emulators/qemu-cheri128; make install

For 256-bit capabilities use:

# cd /usr/ports/emulators/qemu-cheri; make install

Building QEMU from git

The latest version can be built from the source in the CTSRD-CHERI Github repository. We strongly recommend that you use the script to build QEMU and a CheriBSD disk image. The simplest way of getting CheriBSD running is by running run --include-dependencies. If you want to build only QEMU (e.g. for bare-metal development) you can use qemu. Further information on how to use cheribuild and configure build paths and options can be found in the GitHub README

Running CheriBSD with QEMU-Cheri

CheriBSD Startup and Regression Testing

Using the kernel and disk image created above you can boot CheriBSD into multiuser and run the CheriBSD regression tests. Use the 'malta' system model (-M malta) with 2G of system memory (-m 2048):

$ run
Copyright (c) 1992-2015 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
	The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 11.0-CURRENT #0 199c896(master)-dirty: Wed Jan  6 16:38:14 UTC 2016
    [Javascript required]:/var/tmp/obj/mips.mips64/home/sson/src/cheribsd/sys/CHERI_MALTA64 mips
gcc version 4.2.1 20070831 patched [FreeBSD]
Preloaded elf kernel "kernel" at 0xffffffff806bbb10.
CHERI: compiled for 256-bit capabilities
real memory  = 2147483648 (2097152K bytes)
FreeBSD/mips (cheri) (ttyu0)

At this point you can login as the root user (no password) and run the CheriBSD regression tests:

login: root
root@:~ # cheritest -a
TEST: test_string_memmove_c: Test explicit capability memmove
PASS: test_string_memmove_c
SUMMARY: passed 142 failed 1 (1 expected)
root@:~ # cheriabitest -a
TEST: test_string_memmove_c: Test explicit capability memmove
PASS: test_string_memmove_c
SUMMARY: passed 142 failed 1 (1 expected)
root@:~ #

Note that QEMU can be exited using the key sequence "control-a x" at any time.

Instruction, Register and Memory Tracing

QEMU-Cheri also has support for simple instruction, register and memory tracing. This is very useful for debugging and can be turned on (and off) by the command-line when QEMU is started or via the QEMU monitor. Note that turning on instruction tracing will add a lot of overhead to the QEMU emulation and can generate very large trace log files.

In addition to the disassembled instructions the trace includes changes to registers and memory. Here is a small sample of what the trace log looks like (e.g. start of an exception handler):

0xffffffff80000194:  csetdefault        c30
    Write C00|v:1 s:0 p:7fffffff b:0000000000000000 l:ffffffffffffffff
             |o:0000000000000000 t:0
0xffffffff8051d0ec:  sd a3,296(k1)
    Memory Write [c000000000143588] = 000000016004f5a0
0xffffffff8051d0f0:  cgetcause  k0
    Write k0 = 00000000000006ff
0xffffffff8051d0f4:  daddiu     t4,k1,608
    Write t4 = c0000000001436c0
0xffffffff8051d0f8:  csc        c28,t4,192(c30)
    Cap Memory Write [c0000000001436c0] = v:1 tps:00000000ffff00fa
    c:0000000000000000 b:0000000000000000 l:0000010000000000

Starting Instruction Tracing on Start Up

To start instruction tracing on start up add "-D <logfile> -d instr" to the QEMU command-line. For example:

$ qemu-system-cheri -M malta -kernel ./kernel -nographic -hda ./disk.img -m 2048 -D /var/tmp/instr.log -d instr

Starting and Stopping Instruction Tracing via CheriBSD command

CheriBSD also has a tool /usr/bin/qtrace that can be used to toggle QEMU tracing. This will log the traces to the file specified using the -D flag on QEMU startup. For example:

$ qtrace -u exec /bin/true  # trace user-space instructions for cat
$ qtrace exec /bin/true     # trace all instructions for true
$ qtrace exec /bin/true     # trace all instructions for true
$ qtrace start              # turn on instruction tracing
$ qtrace stop               # turn off instruction tracing

Starting and Stopping Instruction Tracing via QEMU Monitor

Instruction tracing can also be started and stopped using the QEMU Monitor. To do this toggle into the QEMU Monitor using the "control-a c" key sequence. At the QEMU Monitor prompt, to start instruction tracing, do:

(qemu) logfile /var/tmp/instr.log
(qemu) log instr

Toggle back to the console with another "control-a c" key sequence.

To stop instruction tracing using the QEMU Monitor:

(qemu) log none

QEMU-Cheri can also create instruction traces that are compatible with the libcheritrace format that is used by the tracedump utility and CheriVis. To generate libcheritrace instruction traces use '-d cvtrace' instead of '-d instr'. For example:

$ qemu-system-cheri128 -M malta -kernel ./kernel -nographic -hda ./disk.img -m 2048 -D /var/tmp/cvtrace.bin -d cvtrace
$ tracedump -t /var/tmp/cvtrace.bin