Run CHERI in Simulation

Use simulation to boot a CHERI environment, build capability-aware code, and observe hardware-enforced faults without owning a development board.

You do not need a CHERI board to learn the programming model or begin a port. A simulator can execute CHERI instructions, preserve capability tags, and report faults when code exceeds bounds or permissions.

Choose one of the two routes below. CheriBSD gives you a full operating system. CHERIoT gives you a smaller embedded environment with explicit compartments.

Route A: CheriBSD on CHERI-RISC-V QEMU

cheribuild automates the compiler, emulator, operating-system, and disk-image builds.

Host requirements

Use a supported Unix-like development host with Python 3, Git, CMake, Ninja, and the other packages listed by cheribuild. Linux is the most direct route. macOS can build many targets, while a Linux virtual machine or container may be easier for a complete environment.

Clone the build tool

git clone https://github.com/CTSRD-CHERI/cheribuild.git
cd cheribuild

Build and run the pure-capability system

./cheribuild.py --include-dependencies run-riscv64-purecap

The first build downloads sources and compiles a substantial stack, so it can take time and disk space. Later runs reuse the build outputs.

When QEMU reaches the login prompt, sign in as root. You are now in a CheriBSD user space where ordinary language pointers use capabilities.

Confirm the target

Inside CheriBSD, run:

uname -a
cc --version

Record the architecture, CheriBSD revision, and compiler version with any test result.

The exact target names and prerequisites can change. The cheribuild repository is the source of truth.

Route B: CHERIoT in a simulator

The CHERIoT development container packages the toolchain, real-time operating-system (RTOS) dependencies, and simulator support.

Clone the RTOS and examples

git clone --recursive https://github.com/CHERIoT-Platform/cheriot-rtos.git
cd cheriot-rtos

Open the repository in Visual Studio Code and select Reopen in Container, or use the published development-container image through another compatible editor or container workflow.

Inside the container, choose an example and configure it for a simulator using the board name documented by that example. A typical build follows this pattern:

xmake config --sdk=/cheriot-tools --board=sail
xmake
xmake run

Board identifiers evolve with the platform. If sail is not offered by the current checkout, use the simulator target listed in the CHERIoT getting-started guide.

Prove that capability enforcement is active

A successful hello-world message proves that the build and run path works. It does not prove that your code is using the intended protection mode.

Add a small test that intentionally exceeds an object bound in a controlled development build:

#include <stddef.h>

int main(void) {
    volatile int values[2] = {1, 2};
    volatile int *outside = values + 2;
    return *outside;
}

In a correctly configured pure-capability environment with useful array bounds, the invalid dereference should produce a capability-related fault. The exact diagnostic differs by architecture, compiler optimisation, and operating system. An undefined-behaviour example is not a conformance suite; use the project’s own tests for formal validation.

What simulation can and cannot tell you

Simulation is well suited to:

An instruction-set simulator alone cannot establish:

Move to FPGA or silicon when the question depends on implementation timing or hardware integration.

Troubleshooting checklist

Once the environment runs, continue with Build Your First Application.

Where next

A guide to the main toolchain components used to build CHERI software and where platform-specific setup differs.

Install a Toolchain →