This document describes the workflow for the CHERI-BGAS project.
Run the following commands to boot a CHERI-BGAS system (assuming all tools are installed, disk images and filenames match, etc…)
Read the later sections for more details
# host machine
quartus_pgm -m jtag -o P\;cheri-bgas-socfpga-25012022-12_02.hps.rbf@2 && picocom -b 115200 /dev/ttyUSB0
# DE10Pro's ARM HPS ...
# u-boot
fatload mmc 0:1 1000 cheri-bgas-socfpga-25012022-12_02.core.rbf
fpga load 0 1000 ${filesize}
bridge enable
fatload mmc 0:1 0x2000000 efi/boot/bootaa64.efi
fatload mmc 0:1 0x8000000 socfpga_stratix10_de10_pro2.dtb
bootefi 0x2000000 0x8000000
# FreeBSD loader
set currdev=disk0s2:
load /boot/kernel/kernel
include /boot/lua/loader.lua
# FreeBSD prompt...
# ARM HPS FreeBSD prompt
setenv RISCV_GDB_STUB_FMEM_DEV /dev/fmem_sys0_debug_unit
setenv RISCV_GDB_STUB_PORT 81
RISCV_gdbstub/src/main
# ARM HPS FreeBSD prompt
cu -l /dev/ttyu0
# enter when the gdb commands are sent in the third terminal
# ... RISCV FreeBSD prompt
# ARM HPS FreeBSD prompt
cd /root/riscv-freebsd-boot
gdb bbl-riscv64
# gdb prompt
target remote localhost:81
load devicetree.wrapped.elf
load kernel-riscv64.GFE-NODEBUG
load
set $a0 = 0
set $a1 = 0x80000000
continue
# see output of second terminal
On a DE10Pro CHERI-BGAS system, we want a FreeBSD kernel to run on the ARM HPS system, and a CheriBSD kernel for the RISCV FPGA soft-core. As a first step to booting a software ecosystem on the DE10Pro CHERI-BGAS setup, we prepare a disk image to put on an SD card.
We will use cheribuild to prepare our environment. Start by cloning cheribuild and run it with the llvm
target to prepare the compiler needed for later builds:
./cheribuild.py llvm
(At the time of writing) Booting CheriBSD on our RISCV soft-core requires:
-
a device tree binary for the RISCV soft-core system
-
a build of BBL
-
a build of CheriBSD with an embedded rootfs
Follow the instructions over here to obtain a devicetree.wrapped.elf
.
Run the following cheribuild command:
./cheribuild.py bbl-gfe-baremetal-riscv64-purecap
A bbl image is created cheri/output/sdk/bbl-gfe/riscv64-purecap/bbl
.
Run the following cheribuild commands:
./cheribuild.py cheribsd-riscv64-purecap
./cheribuild.py disk-image-mfs-root-riscv64-purecap
./cheribuild.py --cheribsd-mfs-root-kernel/build-fpga-kernels cheribsd-mfs-root-kernel-riscv64-purecap
A riscv CheriBSD kernel with embedded rootfs is created cheri/output/kernel-riscv64-purecap.CHERI-PURECAP-GFE
.
(At the time of writing) We want to boot a FreeBSD "host" setup on the ARM HPS system that will drive the RISCV soft-core. On this ARM host system, we will want to have all the necessary files to simply boot FreeBSD correctly, and the necessary tools to properly interact with the soft-core system. Here, we first go through files to be embedded in the final rootfs, and we then use cheribuild to create both the ARM FreeBSD kernel and the disk image with the files of interest.
To allow the ARM HPS system to communicate with the RISCV soft-core on the FPGA, we need to expose the various RISCV debug unit, uart, interrupts… to HPS. To do this, we build a device tree overlay as follows:
>>TODO<<
The instructions described here are currently relying on having build a FreeBSD ARM kernel generated using cheribuild. Ideally, we could amend these with a way to build dtbo
s which would only rely on dtc
.
>>TODO<<
Create the following files:
-
build.sh
:
WORKDIR=<path to your cheri build source root>
$WORKDIR/build/freebsd-aarch64-build/bmake-install/bin/bmake -m $WORKDIR/freebsd/share/mk/ SYSDIR=$WORKDIR/freebsd/sys DTC=$WORKDIR/build/freebsd-aarch64-build/$WORKDIR/freebsd/arm64.aarch64/tmp/obj-tools/usr.bin/dtc/dtc
-
Makefile
:
DTSO= fpga-cheri-bgas.dtso
.include <bsd.dtb.mk>
-
fpga-cheri-bgas.dtso
:
/dts-v1/;
/plugin/;
#include <dt-bindings/interrupt-controller/arm-gic.h>
/ {
compatible = "altr,socfpga-stratix10";
}
&{/soc} {
fmem_h2f_sys_sel@f9030000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cheri,fmem";
reg = <0xf9030000 0x1000>;
status = "okay";
region0 {
name = "selector";
reg = <0x0 0x1000>;
};
};
fmem_sys1@f9010000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cheri,fmem";
reg = <0xf9010000 0x3000>;
status = "okay";
region0 {
name = "sys1_debug_unit";
reg = <0x0 0x1000>;
};
region1 {
name = "sys1_interrupts";
reg = <0x1000 0x1000>;
};
region2 {
name = "sys1_misc";
reg = <0x2000 0x1000>;
};
};
/*
region3 {
name = "sys1_uart";
reg = <0x3000 0x1000>;
};
*/
uart1@f9013000 {
#address-cells = <1>;
#size-cells = <1>;
current-speed = <115200>;
compatible = "ns16550a";
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xf9013000 0x1000>;
clock-frequency = <50000000>;
reg-shift = <2>;
};
fmem_sys1_h2f_addr_ctrl@f9014000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cheri,fmem";
reg = <0xf9014000 0x1000>;
status = "okay";
region4 {
name = "sys1_h2f_addr_ctrl";
reg = <0x0000 0x1000>;
};
};
fmem_sys0@f9000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cheri,fmem";
reg = <0xf9000000 0x3000>;
status = "okay";
region0 {
name = "sys0_debug_unit";
reg = <0x0 0x1000>;
};
region1 {
name = "sys0_interrupts";
reg = <0x1000 0x1000>;
};
region2 {
name = "sys0_misc";
reg = <0x2000 0x1000>;
};
};
/*
region3 {
name = "sys0_uart";
reg = <0x3000 0x1000>;
};
*/
uart0@f9003000 {
#address-cells = <1>;
#size-cells = <1>;
current-speed = <115200>;
compatible = "ns16550a";
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xf9003000 0x1000>;
clock-frequency = <50000000>;
reg-shift = <2>;
};
fmem_sys0_h2f_addr_ctrl@f9004000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cheri,fmem";
reg = <0xf9004000 0x1000>;
status = "okay";
region4 {
name = "sys0_h2f_addr_ctrl";
reg = <0x0000 0x1000>;
};
};
fmem_h2f_dflt@80000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cheri,fmem";
reg = <0x80000000 0x60000000>;
status = "okay";
region0 {
name = "h2f_dflt_1G";
reg = <0x0 0x40000000>;
};
region1 {
name = "h2f_dflt_512M";
reg = <0x40000000 0x20000000>;
};
};
};
You can generate the dtbo
fron the dtso
by running build.sh
.
Extra files can be added to the final FreeBSD rootfs by placing them in <path to your cheri build source root, a.k.a. /home/gameboo/devstuff/cheri>/extra-files/\*
prior to running the command which builds the rootfs.
In our FreeBSD rootfs, we will want (in addition to all the files already included by the FreeBSD build):
-
the RISCV environment we prepared in Preparing the RISCV environment, i.e.
-
Device Tree Binary for the RISCV soft-core system
-
RISCV BBL
-
RISCV CheriBSD kernel with embedded rootfs
-
-
the files necessary to allow the ARM HPS to communicate with the RISCV FPGA soft-core, i.e.
-
a device tree overlay
/boot/fpga-cheri-bgas.dtbo
built in Device tree overlay exposing the soft-core system to the ARM HPS -
a loader configuration
/boot/loader.conf.local
containingfdt_overlays="/boot/fpga-cheri-bgas.dtbo"
-
-
possibly your ssh keys to help ssh-ing into the ARM HPS system (this can be automatically added when building the FreeBSD disk image)
-
optionally, in
/etc/rc.conf
add
ifconfig_<interface name, a.k.a. dwc0>="inet <ip for the ARM HPS system, e.g. 192.168.10.10/24>"
defaultrouter="<ip of a host machine to act as a router, e.g. 192.168.10.1>"
-
optionally, in
/etc/resolv.conf
add
nameserver 8.8.8.8
nameserver 208.67.222.222
nameserver 208.67.220.220
-
a clone of https://github.com/CTSRD-CHERI/RISCV_gdbstub.git to enable gdb sessions to the RISCV FPGA soft-core
-
a clone of https://github.com/CTSRD-CHERI/fmem.git to interact with the various fmem devices from the command line
-
git / vim / gcc / whatever tools…
Once the <path to your cheri build source root, a.k.a. /home/gameboo/devstuff/cheri>/extra-files/>
folder is prepared as described in Preparing relevant files for the FreeBSD rootfs, you can run the following command to build a FreeBSD kernel and a disk image:
./cheribuild.py --source-root=<path to your cheri build source root, a.k.a. /home/gameboo/devstuff/cheri> --freebsd/repository=https://github.com/CTSRD-CHERI/freebsd-morello --freebsd/git-revision=stratix10 --freebsd/toolchain=system-llvm freebsd-aarch64 disk-image-freebsd-aarch64
Note: we explicitly use the https://github.com/CTSRD-CHERI/freebsd-morello FreeBSD fork on the stratix10 branch as it contains the fmem driver necessary to expose the AXI memory-mapped device described in the device tree overlay
Once the command is done, a <path to your cheri build source root, a.k.a. /home/gameboo/devstuff/cheri>/output/freebsd-aarch64.img
disk image should be available. This image can be flashed onto an SD card by running (most likely as root
to allow access to the SD card device):
dd if=<path to your cheri build source root, a.k.a. /home/gameboo/devstuff/cheri>/output/freebsd-aarch64.img> of=<path to your SD card device, a.k.a. /dev/sdX> bs=4M
Note: you can mount the FAT partition from the SD card and copy files to it on a linux system easily. The rootfs partition uses UFS which cannot be easily written from a linux system. You will want a FreeBSD system to change files on it.
You can build u-boot by running this script.
Running the script in ./
generates (amongst others) the following files:
-
a u-boot image
./u-boot-socfpga/u-boot-dtb.img
-
a first stage memory image
./u-boot-socfpga/spl/u-boot-spl-dtb.ihex
To enable the later steps, the FAT partition on the SD card should contain:
-
the
*.core.rbf
FPGA image to use for the FPGA configuration -
a u-boot binary image
u-boot-dtb.img
built in Build an ARM u-boot bootloader -
the
*.dtb
device tree binary used by the ARM HPS system (see [Dervice tree for the ARM HPS])
The first stage memory image u-boot-spl-dtb.ihex
built in Build an ARM u-boot bootloader should be embedded in the startix 10 FPGA configuration.
This assumes a built DE10Pro-cheri-bgas sof file. Add explanations…
BOOTLOADER=<path to u-boot-spl-dtb.ihex>
SOF=<path to your stratix 10 *.sof file>
OUTNAME=socfpga
quartus_pfg -c $SOF -o hps=ON -o hps_path=$BOOTLOADER $OUTNAME.rbf
From the host machine driving the DE10pro board:
RBF=<path to your stratix 10 *.hps.rbf file>
quartus_pgm -m jtag -o P\;$RBF@2 && picocom -b 115200 /dev/ttyUSB0
From the u-boot prompt on the ARM HPS system:
fatload mmc 0:1 0x2000000 <FAT partition path to your *.efi FreeBSD loader file>
fatload mmc 0:1 0x8000000 <FAT partition path to your *.dtb device tree file>
bootefi 0x2000000 0x8000000
From the FreeBSD loader prompt:
load <disk0s1>:</path/to/kernel>
set currdev=<disk0s2:>
include <ROOTFS path to loader script, e.g. /boot/lua/loader.lua>
boot
Once FreeBSD is booted on the ARM HPS system:
-
Run RISCV gdb stub from an ARM HPS system FreeBSD prompt. RISCV gdb stub can be cloned from https://github.com/CTSRD-CHERI/RISCV_gdbstub.git and built simply using
make
. -
Once a RISCV gdb stub session is running on the ARM HPS system, connect a riscv gdb session. This should be done from a machine which has access to:
-
a RISCV bbl bootloader
-
a RISCV FreeBSD kernel
-
a device tree for the RISCV FPGA soft-core system (see https://github.com/CTSRD-CHERI/DE10Pro-softcore-devicetree.git) Typically, you would run on the same host machine driving the DE10Pro board
gdb-multiarch <path to RISCV bbl>
(running gdb-multiarch wih a riscv binary as argument will ensure a riscv-gdb session) and connect to the RISCV gdb stub running (on port 81) on the ARM HPS system withtarget remote <DE10Pro board ip or hostname>:81
-
From the gdb session to the RISCV FPGA soft-core:
-
load the RISCV system’s device tree (the one generated from https://github.com/CTSRD-CHERI/DE10Pro-softcore-devicetree.git is wrapped in an elf container which will load at address
0x80000000
):load <path to the elf container for the RISCV system’s device tree>
-
load the RISCV FreeBSD kernel:
load <path to the RISCV FreeBSD kernel>
-
load the bbl bootloader:
load
-
set the
a0
anda1
argument registers to bbl with the hart id and device tree address respectively:-
set $a0 = 0
-
set $a1 = <device tree load address, e.g. 0x80000000>
-
-
send the RISCV core running:
continue