Skip to content

CHERI RISC‑V

James Clarke edited this page Jul 1, 2019 · 4 revisions

Building LLVM

git clone -b cheri-riscv https://github.com/CTSRD-CHERI/llvm-project
cd llvm-project
mkdir build
cd build
cmake ../llvm -G Ninja -DBUILD_SHARED_LIBS=ON -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=RISCV -DLLVM_ENABLE_PROJECTS="llvm;clang;lld"
ninja

Using Clang

RV32I: clang -target riscv32-unknown-freebsd -march=rv32ixcheri (add -mabi=il32pc64 for pure capability)

RV64I: clang -target riscv64-unknown-freebsd -march=rv64ixcheri (add -mabi=l64pc128 for pure capability)

When linking, use -fuse-ld=lld -Wl,-Ttext-segment=0x80001000 (use 0x70001000 instead for Piccolo).

An example command line would be:

clang -target riscv64-unknown-freebsd -march=rv64ixcheri -mabi=l64pc128 -o cap-mode-memcpy cap-mode-memcpy.c -nostdlib -nostartfiles -fno-inline -ffreestanding -fuse-ld=lld -O2 -Wl,-Ttext-segment=0x80001000

Sample Code

#include <cheri_init_globals.h>

#define STACK_SIZE 1048576

#define STR(x) #x
#define XSTR(x) STR(x)

#if __riscv_xlen == 32
typedef unsigned int size_t;
#elif __riscv_xlen == 64
typedef unsigned long size_t;
#else
#error Unknown __riscv_xlen value
#endif

__asm__(
".text\n"
".option push\n"
".option nocapmode\n"
".global _start\n"
"_start:\n"
"       lla     sp, stack\n"
"       cfromptr        csp, ddc, sp\n"
"       li      t0, "XSTR(STACK_SIZE)"\n"
"       csetbounds      csp, csp, t0\n"
"       cincoffset      csp, csp, t0\n"
"       lla     t0, _start_purecap\n"
"       cfromptr        ct0, ddc, t0\n"
"       li      t1, 1\n"
"       csetflags       ct0, ct0, t1\n"
"       cjr     ct0\n"
".option pop\n"
"\n"
".section \".tohost\",\"aw\",@progbits\n"
".align 6\n"
".globl tohost\n"
"tohost:\n"
"       .dword 0\n"
".align 6\n"
".globl fromhost\n"
"fromhost:\n"
"       .dword 0\n"
);

int x;
int y;
int *px;
int *py;
int **ppy = &py;
int **ppy_1 = &py+1;
__uintcap_t cap42 = 42;

__attribute__((aligned(4096))) char stack[STACK_SIZE];

void *memcpy(void *dst, const void *src, size_t len) {
        for (int i = 0; i < len; ++i)
                ((char *)dst)[i] = ((char *)src)[i];
        return dst;
}

void _start_purecap(void) {
        cheri_init_globals_3(__builtin_cheri_global_data_get(),
                __builtin_cheri_program_counter_get(),
                __builtin_cheri_global_data_get());
        x = 42;
        y++;
        px = &x;
        py = &y;
        __asm__ __volatile__("" ::: "memory");
        memcpy(py, px, sizeof(x));
        y++;
        (**ppy)++;
        cap42++;
}