From 8c6fc0c15415b32080a848bbde640e104098cf13 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Thu, 10 Jul 2025 22:18:39 +0200 Subject: Initial drop Add some riscv code Signed-off-by: Carlos Maiolino --- riscv/riscv-probe/examples/abort/main.c | 6 +++ riscv/riscv-probe/examples/abort/rules.mk | 1 + riscv/riscv-probe/examples/alloca/main.c | 17 ++++++ riscv/riscv-probe/examples/alloca/rules.mk | 1 + riscv/riscv-probe/examples/argv0/main.c | 6 +++ riscv/riscv-probe/examples/argv0/rules.mk | 1 + riscv/riscv-probe/examples/enclave/enclave.c | 79 ++++++++++++++++++++++++++++ riscv/riscv-probe/examples/enclave/rules.mk | 1 + riscv/riscv-probe/examples/hang/hang.c | 23 ++++++++ riscv/riscv-probe/examples/hang/rules.mk | 1 + riscv/riscv-probe/examples/hello/hello.c | 6 +++ riscv/riscv-probe/examples/hello/rules.mk | 1 + riscv/riscv-probe/examples/malloc/main.c | 21 ++++++++ riscv/riscv-probe/examples/malloc/rules.mk | 1 + riscv/riscv-probe/examples/memory/main.c | 17 ++++++ riscv/riscv-probe/examples/memory/rules.mk | 1 + riscv/riscv-probe/examples/probe/probe.c | 71 +++++++++++++++++++++++++ riscv/riscv-probe/examples/probe/rules.mk | 1 + riscv/riscv-probe/examples/symbols/rules.mk | 1 + riscv/riscv-probe/examples/symbols/symbols.c | 28 ++++++++++ riscv/riscv-probe/examples/user/rules.mk | 1 + riscv/riscv-probe/examples/user/user.c | 27 ++++++++++ 22 files changed, 312 insertions(+) create mode 100644 riscv/riscv-probe/examples/abort/main.c create mode 100644 riscv/riscv-probe/examples/abort/rules.mk create mode 100644 riscv/riscv-probe/examples/alloca/main.c create mode 100644 riscv/riscv-probe/examples/alloca/rules.mk create mode 100644 riscv/riscv-probe/examples/argv0/main.c create mode 100644 riscv/riscv-probe/examples/argv0/rules.mk create mode 100644 riscv/riscv-probe/examples/enclave/enclave.c create mode 100644 riscv/riscv-probe/examples/enclave/rules.mk create mode 100644 riscv/riscv-probe/examples/hang/hang.c create mode 100644 riscv/riscv-probe/examples/hang/rules.mk create mode 100644 riscv/riscv-probe/examples/hello/hello.c create mode 100644 riscv/riscv-probe/examples/hello/rules.mk create mode 100644 riscv/riscv-probe/examples/malloc/main.c create mode 100644 riscv/riscv-probe/examples/malloc/rules.mk create mode 100644 riscv/riscv-probe/examples/memory/main.c create mode 100644 riscv/riscv-probe/examples/memory/rules.mk create mode 100644 riscv/riscv-probe/examples/probe/probe.c create mode 100644 riscv/riscv-probe/examples/probe/rules.mk create mode 100644 riscv/riscv-probe/examples/symbols/rules.mk create mode 100644 riscv/riscv-probe/examples/symbols/symbols.c create mode 100644 riscv/riscv-probe/examples/user/rules.mk create mode 100644 riscv/riscv-probe/examples/user/user.c (limited to 'riscv/riscv-probe/examples') diff --git a/riscv/riscv-probe/examples/abort/main.c b/riscv/riscv-probe/examples/abort/main.c new file mode 100644 index 0000000..cf5bcc0 --- /dev/null +++ b/riscv/riscv-probe/examples/abort/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) +{ + abort(); +} diff --git a/riscv/riscv-probe/examples/abort/rules.mk b/riscv/riscv-probe/examples/abort/rules.mk new file mode 100644 index 0000000..d569b90 --- /dev/null +++ b/riscv/riscv-probe/examples/abort/rules.mk @@ -0,0 +1 @@ +abort_objs = main.o diff --git a/riscv/riscv-probe/examples/alloca/main.c b/riscv/riscv-probe/examples/alloca/main.c new file mode 100644 index 0000000..af9696a --- /dev/null +++ b/riscv/riscv-probe/examples/alloca/main.c @@ -0,0 +1,17 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + const size_t nelems = 4; + const size_t elemsize = 128; + char *alloc[nelems]; + + for (size_t i = 0; i < nelems; i++) { + if (alloc[i] = alloca(elemsize)) { + memset(alloc[i], 0, elemsize); + } + printf("alloca[%d]=0x%x\n", i, alloc[i]); + } +} diff --git a/riscv/riscv-probe/examples/alloca/rules.mk b/riscv/riscv-probe/examples/alloca/rules.mk new file mode 100644 index 0000000..198ef24 --- /dev/null +++ b/riscv/riscv-probe/examples/alloca/rules.mk @@ -0,0 +1 @@ +alloca_objs = main.o diff --git a/riscv/riscv-probe/examples/argv0/main.c b/riscv/riscv-probe/examples/argv0/main.c new file mode 100644 index 0000000..7699fe2 --- /dev/null +++ b/riscv/riscv-probe/examples/argv0/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) +{ + printf("%s\n", argv[0]); +} diff --git a/riscv/riscv-probe/examples/argv0/rules.mk b/riscv/riscv-probe/examples/argv0/rules.mk new file mode 100644 index 0000000..0ceeeaa --- /dev/null +++ b/riscv/riscv-probe/examples/argv0/rules.mk @@ -0,0 +1 @@ +argv0_objs = main.o diff --git a/riscv/riscv-probe/examples/enclave/enclave.c b/riscv/riscv-probe/examples/enclave/enclave.c new file mode 100644 index 0000000..93015cc --- /dev/null +++ b/riscv/riscv-probe/examples/enclave/enclave.c @@ -0,0 +1,79 @@ +#include "femto.h" + +/* + * Simple enclave example using RISC-V PMP (Physical Memory Protection) + * + * NOTE: 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 more complete example needs to load a + * second process and provide ecall APIs to the protected enclave. + * This is not yet a true secure enclave until two disjunctive worlds + * are have been implemented with measured boot and signed code. + */ + +extern char _text_start; +extern char _rodata_end; +extern char _data_start; +extern char _bss_end; + +static uintptr_t uart_keys[] = { + SIFIVE_UART0_CTRL_ADDR, + NS16550A_UART0_CTRL_ADDR, + RISCV_HTIF_BASE_ADDR, + 0 +}; + +#ifdef __riscv +#include "arch/riscv/encoding.h" +#include "arch/riscv/machine.h" +#include "arch/riscv/csr.h" +#endif + +int main() +{ + uintptr_t uart = 0; + uintptr_t *uart_k = uart_keys; + const uintptr_t uartlen = 32; + + /* locate UART address using known configuration keys */ + while (*uart_k && !(uart = getauxval(*uart_k++))); + + /* locate ROM/Flash (text+rodata) and RAM (data+bss) */ + uintptr_t rx_s = (uintptr_t)&_text_start; + uintptr_t rx_l = roundpow2((uintptr_t)(&_rodata_end - &_text_start)); + uintptr_t rw_s = (uintptr_t)&_data_start; + uintptr_t rw_l = roundpow2((uintptr_t)(&_bss_end - &_data_start)); + + /* print our findings */ + printf("text: 0x%x - 0x%x\n", rx_s, rx_s + rx_l - 1); + printf("data: 0x%x - 0x%x\n", rw_s, rw_s + rw_l - 1); + if (uart) { + printf("uart: 0x%x - 0x%x\n", uart, uart + uartlen - 1); + } + +#ifdef __riscv + pmp_info_t info = pmp_probe(); + if (info.count == 0) { + puts("pmp-not-supported"); + return 0; + } else { + printf("pmp.count: %d\n", info.count); + printf("pmp.width: %d\n", info.width); + printf("pmp.granularity: %d\n", info.granularity); + } + /* set up physical memory protection */ + pmp_entry_set(0, PMP_R | PMP_X, rx_s, rx_l); + pmp_entry_set(1, PMP_R | PMP_W, rw_s, rw_l); + if (uart) { + pmp_entry_set(2, PMP_R | PMP_W, uart, uartlen); + } + + /* switch to user mode enclave */ + mode_set_and_continue(PRV_U); + puts("riscv-enclave"); +#else + puts("architecture-not-supported"); +#endif +} diff --git a/riscv/riscv-probe/examples/enclave/rules.mk b/riscv/riscv-probe/examples/enclave/rules.mk new file mode 100644 index 0000000..046cbae --- /dev/null +++ b/riscv/riscv-probe/examples/enclave/rules.mk @@ -0,0 +1 @@ +enclave_objs = enclave.o diff --git a/riscv/riscv-probe/examples/hang/hang.c b/riscv/riscv-probe/examples/hang/hang.c new file mode 100644 index 0000000..066ca9e --- /dev/null +++ b/riscv/riscv-probe/examples/hang/hang.c @@ -0,0 +1,23 @@ +#include + +int main(int argc, char **argv) +{ + volatile int a; + int b, c, d, e, f, g, h, i, j, k, l, m; + printf("hang\n"); + for (;;) { + a = b; + b = c; + c = d; + d = e; + e = f; + f = g; + g = h; + h = i; + i = j; + j = k; + k = l; + l = m; + m = a; + } +} diff --git a/riscv/riscv-probe/examples/hang/rules.mk b/riscv/riscv-probe/examples/hang/rules.mk new file mode 100644 index 0000000..8a04005 --- /dev/null +++ b/riscv/riscv-probe/examples/hang/rules.mk @@ -0,0 +1 @@ +hang_objs = hang.o diff --git a/riscv/riscv-probe/examples/hello/hello.c b/riscv/riscv-probe/examples/hello/hello.c new file mode 100644 index 0000000..d65ed6a --- /dev/null +++ b/riscv/riscv-probe/examples/hello/hello.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) +{ + printf("hello\n"); +} diff --git a/riscv/riscv-probe/examples/hello/rules.mk b/riscv/riscv-probe/examples/hello/rules.mk new file mode 100644 index 0000000..4d43f63 --- /dev/null +++ b/riscv/riscv-probe/examples/hello/rules.mk @@ -0,0 +1 @@ +hello_objs = hello.o diff --git a/riscv/riscv-probe/examples/malloc/main.c b/riscv/riscv-probe/examples/malloc/main.c new file mode 100644 index 0000000..cde2038 --- /dev/null +++ b/riscv/riscv-probe/examples/malloc/main.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + const size_t nelems = 8; + const size_t elemsize = 128; + char *alloc[nelems]; + + for (size_t i = 0; i < nelems; i++) { + if (alloc[i] = malloc(elemsize)) { + memset(alloc[i], 0, elemsize); + } + printf("malloc[%d]=0x%x\n", i, alloc[i]); + } + + for (size_t i = 0; i < nelems; i++) { + free(alloc[i]); + } +} \ No newline at end of file diff --git a/riscv/riscv-probe/examples/malloc/rules.mk b/riscv/riscv-probe/examples/malloc/rules.mk new file mode 100644 index 0000000..82b0bc6 --- /dev/null +++ b/riscv/riscv-probe/examples/malloc/rules.mk @@ -0,0 +1 @@ +malloc_objs = main.o diff --git a/riscv/riscv-probe/examples/memory/main.c b/riscv/riscv-probe/examples/memory/main.c new file mode 100644 index 0000000..01c5d0b --- /dev/null +++ b/riscv/riscv-probe/examples/memory/main.c @@ -0,0 +1,17 @@ +#include "femto.h" +#ifdef __riscv +#include "arch/riscv/encoding.h" +#include "arch/riscv/machine.h" +#endif + +extern char _memory_start; + +int main(int argc, char **argv) +{ +#ifdef __riscv + memory_info_t info = memory_probe(); + printf("memory_start=0x%lx - 0x%lx\n", info.start, info.end); +#else + puts("architecture-not-supported"); +#endif +} diff --git a/riscv/riscv-probe/examples/memory/rules.mk b/riscv/riscv-probe/examples/memory/rules.mk new file mode 100644 index 0000000..1d0ad8c --- /dev/null +++ b/riscv/riscv-probe/examples/memory/rules.mk @@ -0,0 +1 @@ +memory_objs = main.o diff --git a/riscv/riscv-probe/examples/probe/probe.c b/riscv/riscv-probe/examples/probe/probe.c new file mode 100644 index 0000000..4cc4384 --- /dev/null +++ b/riscv/riscv-probe/examples/probe/probe.c @@ -0,0 +1,71 @@ +#include "femto.h" + +#ifdef __riscv +#include "arch/riscv/csr.h" +#include "arch/riscv/trap.h" +#include "arch/riscv/encoding.h" +#include "arch/riscv/machine.h" + +#define MCAUSE_UNSET 0xabbaabba + +static volatile uintptr_t save_mcause; + +static void trap_save_cause(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) +{ + save_mcause = mcause; + write_csr(mepc, mepc + 4); +} + +static const char* isa_string(char *buf, size_t bufsz) +{ + static const char *ext = "iemafdqlcbjtpvnsu"; + + const char *p = ext; + char *q = buf + snprintf(buf, bufsz, "rv%d", xlen()); + do { + if (has_ext(*p)) { + *q++ = *p; + } + } while (*++p); + *q = '\0'; + + return buf; +} + +static void probe_all_csrs() +{ + int *csrenum = csr_enum_array(); + const char **csrnames = csr_name_array(); + const char* ws = " "; + set_trap_fn(trap_save_cause); + while (*csrenum != csr_none) { + save_mcause = MCAUSE_UNSET; + long value = read_csr_enum(*csrenum); + const char* csrname = csrnames[*csrenum]; + if (save_mcause != MCAUSE_UNSET) { + int async = save_mcause < 0; + int cause = save_mcause & (((uintptr_t)-1) >> async); + printf("csr: %s%s %s cause=%ld mtval=0x%lx\n", + csrname, ws + strlen(csrname), cause < 16 + ? (async ? riscv_intr_names : riscv_excp_names)[cause] + : "(unknown)", save_mcause, read_csr_enum(csr_mtval)); + } else { + printf("csr: %s%s 0x%lx\n", + csrname, ws + strlen(csrname), value); + } + csrenum++; + } +} +#endif + +int main(int argc, char **argv) +{ +#ifdef __riscv + char buf[32]; + printf("isa: %s\n", isa_string(buf, sizeof(buf))); + probe_all_csrs(); + printf("\n"); +#else + puts("architecture-not-supported"); +#endif +} diff --git a/riscv/riscv-probe/examples/probe/rules.mk b/riscv/riscv-probe/examples/probe/rules.mk new file mode 100644 index 0000000..928f066 --- /dev/null +++ b/riscv/riscv-probe/examples/probe/rules.mk @@ -0,0 +1 @@ +probe_objs = probe.o diff --git a/riscv/riscv-probe/examples/symbols/rules.mk b/riscv/riscv-probe/examples/symbols/rules.mk new file mode 100644 index 0000000..ba4e934 --- /dev/null +++ b/riscv/riscv-probe/examples/symbols/rules.mk @@ -0,0 +1 @@ +symbols_objs = symbols.o diff --git a/riscv/riscv-probe/examples/symbols/symbols.c b/riscv/riscv-probe/examples/symbols/symbols.c new file mode 100644 index 0000000..d05807f --- /dev/null +++ b/riscv/riscv-probe/examples/symbols/symbols.c @@ -0,0 +1,28 @@ +#include + +/* program to print linker script provided symbols */ + +extern char _text_start; +extern char _text_end; +extern char _rodata_start; +extern char _rodata_end; +extern char _data_start; +extern char _data_end; +extern char _bss_start; +extern char _bss_end; +extern char _memory_start; +extern char _memory_end; + +int main(int argc, char **argv) +{ + printf("_text_start=0x%x\n", &_text_start); + printf("_text_end=0x%x\n", &_text_end); + printf("_rodata_start=0x%x\n", &_rodata_start); + printf("_rodata_end=0x%x\n", &_rodata_end); + printf("_data_start=0x%x\n", &_data_start); + printf("_data_end=0x%x\n", &_data_end); + printf("_bss_start=0x%x\n", &_bss_start); + printf("_bss_end=0x%x\n", &_bss_end); + printf("_memory_start=0x%x\n", &_memory_start); + printf("_memory_end=0x%x\n", &_memory_end); +} diff --git a/riscv/riscv-probe/examples/user/rules.mk b/riscv/riscv-probe/examples/user/rules.mk new file mode 100644 index 0000000..63c6868 --- /dev/null +++ b/riscv/riscv-probe/examples/user/rules.mk @@ -0,0 +1 @@ +user_objs = user.o diff --git a/riscv/riscv-probe/examples/user/user.c b/riscv/riscv-probe/examples/user/user.c new file mode 100644 index 0000000..e37397f --- /dev/null +++ b/riscv/riscv-probe/examples/user/user.c @@ -0,0 +1,27 @@ +#include "femto.h" + +#ifdef __riscv +#include "arch/riscv/encoding.h" +#include "arch/riscv/machine.h" +#endif + +int main(int argc, char **argv) +{ + /* + * Set up PMP (Physical Memory Protection) + * + * PMP is optional; bit if implemented enforcement is mandatory + * and user-mode is prevented access to all memory by default. + * We should change this code to restrict user mode to its .text + * .rodata, .data, .bss and devices. + */ +#ifdef __riscv + if (pmp_entry_count() > 0) { + pmp_allow_all(); + } + mode_set_and_continue(PRV_U); + puts("riscv-user-mode"); +#else + puts("architecture-not-supported"); +#endif +} -- cgit v1.2.3