/riscv-probe

Simple machine mode program to probe RISC-V control and status registers

Primary LanguageCOtherNOASSERTION

riscv-probe

Simple machine mode program to probe RISC-V control and status registers.

riscv-probe currently builds for Spike, QEMU and the SiFive E21 core. riscv-probe is a testing tool designed be used to compare CSRs (Control and Status Registers) between mutliple RISC-V simulators and RISC-V hardware implementations.

riscv-probe contains libfemto which is a lightweight bare-metal C library conforming to a reduced set ot the POSIX.1-2017 / IEEE 1003.1-2017 standard. libfemto can be used as a starting point for bare metal RISC-V programs that require interrupt handling, basic string routines and printf.

Dependencies

A recent version of riscv-tools with a multilib build of RISC-V GCC.

Build

The build system uses CROSS_COMPILE as the toolchain prefix and expects the toolchain to be present in the PATH environment variable. The default value for CROSS_COMPILE is riscv64-unknown-elf- however this can be overridden e.g. make CROSS_COMPILE=riscv64-unknown-linux-gnu-. The build system expects a multilib toolchain as it uses the same toolchain to build for riscv32 and riscv64. Make sure to use --enable-multilib when configuring riscv-gnu-toolchain. The examples are all built with -nostartfiles -nostdlib -nostdinc so either the RISC-V GCC Newlib toolchain or RISC-V GCC Glibc Linux toolchain can be used.

To build the examples after environent setup, type:

make

Invocation

To invoke the probe example in spike and RISC-V QEMU:

  • $ spike --isa=RV32IMAFDC build/bin/rv32imac/spike/probe
  • $ spike --isa=RV64IMAFDC build/bin/rv64imac/spike/probe
  • $ qemu-system-riscv32 -nographic -machine spike -kernel build/bin/rv32imac/spike/probe -bios none
  • $ qemu-system-riscv64 -nographic -machine spike -kernel build/bin/rv64imac/spike/probe -bios none
  • $ qemu-system-riscv32 -nographic -machine virt -kernel build/bin/rv32imac/virt/probe -bios none
  • $ qemu-system-riscv64 -nographic -machine virt -kernel build/bin/rv64imac/virt/probe -bios none
  • $ qemu-system-riscv32 -nographic -machine sifive_e -kernel build/bin/rv32imac/qemu-sifive_e/probe -bios none
  • $ qemu-system-riscv64 -nographic -machine sifive_e -kernel build/bin/rv64imac/qemu-sifive_e/probe -bios none
  • $ qemu-system-riscv32 -nographic -machine sifive_u -kernel build/bin/rv32imac/qemu-sifive_u/probe -bios none
  • $ qemu-system-riscv64 -nographic -machine sifive_u -kernel build/bin/rv64imac/qemu-sifive_u/probe -bios none

libfemto

libfemto is a lightweight bare-metal C library for embedded RISC-V development. libfemto provides:

  • Reduced set of the POSIX.1-2017 / IEEE 1003.1-2017 standard
  • Simple lightweight hardware configuration mechanism
  • RISC-V machine mode functions and macros
  • Console and power device drivers

libfemto implements a reduced set of the POSIX.1-2017 / IEEE 1003.1-2017 standard, with the addition of glibc's getauxval API to access hardware configuration in an auxiliary vector (__auxv) that contains tuples describing the target environment. The auxiliary vector is intended as a lightweight mechanism to pass dynamic configuration information on embedded targets, serving as an alternative to compile time constants used during hardware initialization. The auxiliary vector API has been repurposed to allow retrieval of hardware configuration parameters such as clock frequencies and device base addresses for use as a compact alternative to (DTB) Device Tree Binary, which is not available on small embedded targets.

libfemto contains the following device drivers:

  • HTIF (Host Target Interface)
  • NS16550A UART Console
  • SiFive UART Console
  • SiFive Test Device
  • Semihosting Syscalls

Environments

This project contains a simple build system that allows building applications targeting multiple embedded environments. A distinguishing characteristic of the build system is that program objects do not need to be recompiled to target a different environment, rather they are relinked with a different hardware configuration and setup function. The config object causes the correct drivers to be linked via compile time dependencies expressed by symbol references. The following environments are currently supported:

  • default - environment where IO defaults to ebreak
  • spike- the RISC-V ISA Simulator Golden Model
  • virt - the RISC-V VirtIO Virtual Machine
  • qemu-sifive_e - QEMU Functional Model of the SiFive E Series
  • qemu-sifive_u - QEMU Functional Model of the SiFive U Series
  • coreip-e2-arty - SiFive E2 CoreIP Arty A7 FPGA evaluation image

To create a new environment simply add a directory to env with two files:

  • default.lds - linker script describing the target's memory layout
  • config.c - environment specific configuration

The following is an example configuration from env/<boardname>/config.c showing the auxiliary vector used by getauxval via the setup function called by _start before entering main.

auxval_t __auxv[] = {
    { UART0_CLOCK_FREQ,         32000000   },
    { UART0_BAUD_RATE,          115200     },
    { SIFIVE_UART0_CTRL_ADDR,   0x20000000 },
    { SIFIVE_TEST_CTRL_ADDR,    0x4000     },
    { 0, 0 }
};

void setup()
{
    /*
     * clock setup code should be placed here and should modify the
     * uart clock speed before calling register_console, which calls
     * uart_init and reads the uart clock speed from the config array.
     */
    register_console(&console_sifive_uart);
    register_poweroff(&poweroff_sifive_test);
}

Examples

The build system automatically includes any directory added to examples which contains a rules.mk file.

hello

The following is the rules.mk file from the hello example:

$ cat examples/hello/rules.mk 
hello_objs = hello.o

and hello.c

$ cat examples/hello/hello.c 
#include <stdio.h>

int main(int argc, char **argv)
{
	printf("hello\n");
}

symbols

libfemto linker scripts define the following special symbols:

Symbol Value
_text_start start of .text section
_text_end end of .text section
_rodata_start start of .rodata section
_rodata_end end of .rodata section
_data_start start of .data section
_data_end end of .data section
_bss_start start of .bss section
_bss_end end of .bss section
_memory_start start of RAM
_memory_end end of RAM

The symbols example program shows how to access these special symbols. They can be used for example to locate data section in a flat image in ROM to copy into memory and to zero the bss section.

user

Simple example program that sets up PMP (Physical Memory Protection) to allow all memory accesses and then switches to U mode. The code to set up PMP to allow all memory access is pmp_allow_all() in machine.h. The code is derived from bbl.

Note: PMP is enabled by default on systems that implement it, so it is mandatory to include code to configure PMPs to allow memory access when switching from M mode to S mode or U mode, otherwise memory accesses will trap.

enclave

Simple enclave example using RISC-V PMP (Physical Memory Protection)

Physical memory protection is enabled for the program text (RX) program data (RW), UART, and the hart is switch to U mode, however, there is only one program and the default trap vector points into the executable text, so traps are handled in M mode, in the same executable text segment.

A future example will load a second process and provide ecall APIs to the process running in the protected enclave.

probe

riscv-probe is a utility that probes the Control and Status Register address space of a RISC-V emulator, FPGA or board:

qemu-system-riscv32

$ qemu-system-riscv32 -nographic -machine spike_v1.10 -kernel build/bin/rv32/spike/probe
isa: rv32imafdcsu
csr: fflags          illegal_instruction cause=0x00000002 mtval=0x00000000
csr: frm             illegal_instruction cause=0x00000002 mtval=0x00000000
csr: fcsr            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: mcycle          0xdbfa9cbd
csr: minstret        0xdc03f6a4
csr: mcycleh         0x0007c452
csr: minstreth       0x0007c452
csr: cycle           0xdc1d7e08
csr: time            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instret         0xdc393bf6
csr: cycleh          0x0007c452
csr: timeh           illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instreth        0x0007c452
csr: mvendorid       0x00000000
csr: marchid         0x00000000
csr: mimpid          0x00000000
csr: mhartid         0x00000000
csr: mstatus         0x00000000
csr: misa            0x4014112d
csr: medeleg         0x00000000
csr: mideleg         0x00000000
csr: mie             0x00000000
csr: mtvec           0x80000004
csr: mcounteren      0x00000000
csr: mscratch        0x00000000
csr: mepc            0x800002a4
csr: mcause          0x00000002
csr: mtval           0x00000000
csr: mip             0x00000000
csr: sstatus         0x00000000
csr: sedeleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sideleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sie             0x00000000
csr: stvec           0x00000000
csr: scounteren      0x00000000
csr: sscratch        0x00000000
csr: sepc            0x00000000
csr: scause          0x00000000
csr: stval           0x00000000
csr: sip             0x00000000
csr: satp            0x00000000
csr: pmpcfg0         0x00000000
csr: pmpcfg1         0x00000000
csr: pmpcfg2         0x00000000
csr: pmpcfg3         0x00000000
csr: pmpaddr0        0x00000000
csr: pmpaddr1        0x00000000
csr: pmpaddr2        0x00000000
csr: pmpaddr3        0x00000000
csr: pmpaddr4        0x00000000
csr: pmpaddr5        0x00000000
csr: pmpaddr6        0x00000000
csr: pmpaddr7        0x00000000
csr: pmpaddr8        0x00000000
csr: pmpaddr9        0x00000000
csr: pmpaddr10       0x00000000
csr: pmpaddr11       0x00000000
csr: pmpaddr12       0x00000000
csr: pmpaddr13       0x00000000
csr: pmpaddr14       0x00000000
csr: pmpaddr15       0x00000000

qemu-system-riscv64

$ qemu-system-riscv64 -nographic -machine spike_v1.10 -kernel build/bin/rv64/spike/probe
isa: rv64imafdcsu
csr: fflags          illegal_instruction cause=0x00000002 mtval=0x00000000
csr: frm             illegal_instruction cause=0x00000002 mtval=0x00000000
csr: fcsr            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: mcycle          0x0007c452dfeeddd3
csr: minstret        0x0007c452dff8a765
csr: mcycleh         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: minstreth       illegal_instruction cause=0x00000002 mtval=0x00000000
csr: cycle           0x0007c452e01f105f
csr: time            illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instret         0x0007c452e03d0a50
csr: cycleh          illegal_instruction cause=0x00000002 mtval=0x00000000
csr: timeh           illegal_instruction cause=0x00000002 mtval=0x00000000
csr: instreth        illegal_instruction cause=0x00000002 mtval=0x00000000
csr: mvendorid       0x0000000000000000
csr: marchid         0x0000000000000000
csr: mimpid          0x0000000000000000
csr: mhartid         0x0000000000000000
csr: mstatus         0x0000000000000000
csr: misa            0x800000000014112d
csr: medeleg         0x0000000000000000
csr: mideleg         0x0000000000000000
csr: mie             0x0000000000000000
csr: mtvec           0x0000000080000004
csr: mcounteren      0x0000000000000000
csr: mscratch        0x0000000000000000
csr: mepc            0x00000000800002f4
csr: mcause          0x0000000000000002
csr: mtval           0x0000000000000000
csr: mip             0x0000000000000000
csr: sstatus         0x0000000000000000
csr: sedeleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sideleg         illegal_instruction cause=0x00000002 mtval=0x00000000
csr: sie             0x0000000000000000
csr: stvec           0x0000000000000000
csr: scounteren      0x0000000000000000
csr: sscratch        0x0000000000000000
csr: sepc            0x0000000000000000
csr: scause          0x0000000000000000
csr: stval           0x0000000000000000
csr: sip             0x0000000000000000
csr: satp            0x0000000000000000
csr: pmpcfg0         0x0000000000000000
csr: pmpcfg1         0x0000000000000000
csr: pmpcfg2         0x0000000000000000
csr: pmpcfg3         0x0000000000000000
csr: pmpaddr0        0x0000000000000000
csr: pmpaddr1        0x0000000000000000
csr: pmpaddr2        0x0000000000000000
csr: pmpaddr3        0x0000000000000000
csr: pmpaddr4        0x0000000000000000
csr: pmpaddr5        0x0000000000000000
csr: pmpaddr6        0x0000000000000000
csr: pmpaddr7        0x0000000000000000
csr: pmpaddr8        0x0000000000000000
csr: pmpaddr9        0x0000000000000000
csr: pmpaddr10       0x0000000000000000
csr: pmpaddr11       0x0000000000000000
csr: pmpaddr12       0x0000000000000000
csr: pmpaddr13       0x0000000000000000
csr: pmpaddr14       0x0000000000000000
csr: pmpaddr15       0x0000000000000000