Skip to content

Commit 228e834

Browse files
committed
ports/cheriot-rtos: Initial compartmentalisation and README.
Signed-off-by: Duncan Lowther <[email protected]>
1 parent 0f8bb9b commit 228e834

File tree

10 files changed

+404
-157
lines changed

10 files changed

+404
-157
lines changed

ports/cheriot-rtos/Makefile

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
include ../../py/mkenv.mk
22

3-
CROSS = 0
4-
53
# qstr definitions (must come before including py.mk)
64
QSTR_DEFS = qstrdefsport.h
75

@@ -13,6 +11,7 @@ include $(TOP)/py/py.mk
1311

1412
CLLVM_DIR ?= ~/cheriot-llvm/
1513
CRTOS_DIR ?= ../../../cheriot-rtos
14+
UF2CONV ?= ~/.cargo/bin/uf2conv
1615

1716
CROSS_COMPILE = $(CLLVM_DIR)bin/
1817
AS = $(CROSS_COMPILE)clang
@@ -28,7 +27,7 @@ INC += -I$(BUILD)
2827

2928
INC += $(SYS_INC)
3029
CFLAGS_CHERIOT_A7 = -target riscv32-unknown-unknown -mcpu=cheriot -mabi=cheriot -mxcheri-rvc -mrelax -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-builtin -fno-exceptions -fno-asynchronous-unwind-tables -fno-c++-static-destructors -fno-rtti
31-
CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CHERIOT_A7) $(COPT) -DNO_ALLOCA_H -DCHERIOT_IBEX -DIBEX -DSUNBURST -DSUNBURST_SHADOW_BASE=0x30000000 -DSUNBURST_SHADOW_SIZE=0x4000 -DCPU_TIMER_HZ=33000000 -DTICK_RATE_HZ=100 -DCHERIOT_NO_AMBIENT_MALLOC -DDEVICE_EXISTS_shadow -DDEVICE_EXISTS_clint -DDEVICE_EXISTS_uart -DDEVICE_EXISTS_gpio -DDEVICE_EXISTS_gpio -DDEVICE_EXISTS_plic -DREVOKABLE_MEMORY_START=0x00100080 -cheri-compartment=mp_main
30+
CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CHERIOT_A7) $(COPT) -DNO_ALLOCA_H -DCHERIOT_IBEX -DIBEX -DSUNBURST -DSUNBURST_SHADOW_BASE=0x30000000 -DSUNBURST_SHADOW_SIZE=0x4000 -DCPU_TIMER_HZ=33000000 -DTICK_RATE_HZ=100 -DCHERIOT_NO_AMBIENT_MALLOC -DDEVICE_EXISTS_shadow -DDEVICE_EXISTS_clint -DDEVICE_EXISTS_uart -DDEVICE_EXISTS_gpio -DDEVICE_EXISTS_gpio -DDEVICE_EXISTS_plic -DREVOKABLE_MEMORY_START=0x00100080
3231
LDFLAGS += --script=cheriot-a7-100t.ld --relax
3332

3433
CSUPEROPT = -Os # save some code space
@@ -39,42 +38,62 @@ ifeq ($(DEBUG), 1)
3938
CFLAGS += -O0
4039
else
4140
CFLAGS += -Os -DNDEBUG
42-
CFLAGS += -fdata-sections -ffunction-sections
4341
endif
4442

4543
# Flags for optional C++ source code
4644
CXXFLAGS += $(filter-out -std=c99,$(CFLAGS)) -std=c++20
4745

4846
LIBS =
4947

50-
SRC_C = \
51-
main.c \
52-
shared/libc/printf.c \
48+
SRC_C = mp_entry.c \
5349
shared/readline/readline.c \
5450
shared/runtime/pyexec.c \
55-
shared/runtime/stdout_helpers.c \
5651
$(BUILD)/_frozen_mpy.c \
5752

58-
SRC_CXX = uart_core.cpp
53+
SRC_CXX =
5954

6055
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c
6156

57+
SRC_HAL_C = shared/runtime/stdout_helpers.c
58+
SRC_HAL_CXX = uart_core.cpp
59+
60+
SRC_MAIN_C = main.c
61+
SRC_MAIN_CXX =
62+
6263
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
6364
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
6465
OBJ += $(PY_CORE_O)
6566

67+
OBJ_HAL += $(addprefix $(BUILD)/, $(SRC_HAL_C:.c=.o))
68+
OBJ_HAL += $(addprefix $(BUILD)/, $(SRC_HAL_CXX:.cpp=.o))
69+
70+
OBJ_MAIN += $(addprefix $(BUILD)/, $(SRC_MAIN_C:.c=.o))
71+
OBJ_MAIN += $(addprefix $(BUILD)/, $(SRC_MAINL_CXX:.cpp=.o))
72+
73+
$(OBJ): CFLAGS += -DMP_VM_COMP -cheri-compartment=mp_vm
74+
$(OBJ_HAL): CFLAGS += -cheri-compartment=mp_hal
75+
$(OBJ_MAIN): CFLAGS += -cheri-compartment=main
76+
6677
all: $(BUILD)/micropython.uf2
6778

79+
all_objects : $(OBJ) $(OBJ_HAL) $(OBJ_MAIN)
80+
.PHONY: all all_objects
81+
6882
$(BUILD)/_frozen_mpy.c: $(TOP)/tests/frozen/frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
6983
$(ECHO) "MISC freezing bytecode"
7084
$(Q)$(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@
7185

7286
$(BUILD)/xmake.lua: xmake.lua.top xmake.lua.bottom
7387
cat xmake.lua.top > $@
88+
echo "compartment(\"mp_vm\")" >> $@
7489
for OFILE in $(patsubst $(BUILD)/%,%,$(OBJ)) ; do echo " add_files(\"$$OFILE\", {rule = \"utils.merge.object\"})" >> $@ ; done
90+
echo "compartment(\"mp_hal\")" >> $@
91+
for OFILE in $(patsubst $(BUILD)/%,%,$(OBJ_HAL)) ; do echo " add_files(\"$$OFILE\", {rule = \"utils.merge.object\"})" >> $@ ; done
92+
echo "compartment(\"main\")" >> $@
93+
for OFILE in $(patsubst $(BUILD)/%,%,$(OBJ_MAIN)) ; do echo " add_files(\"$$OFILE\", {rule = \"utils.merge.object\"})" >> $@ ; done
7594
cat xmake.lua.bottom >> $@
7695

77-
$(BUILD)/build/cheriot/cheriot/release/micropython: $(OBJ) $(BUILD)/xmake.lua
96+
$(BUILD)/build/cheriot/cheriot/release/micropython: all_objects $(BUILD)/xmake.lua
7897
cd $(BUILD) && xmake config --sdk=$(CLLVM_DIR) --board=sonata && xmake
7998

8099
#$(BUILD)/cpu0_iram.vhx: $(BUILD)/build/cheriot/cheriot/release/micropython
@@ -85,6 +104,6 @@ $(BUILD)/micropython.bin: $(BUILD)/build/cheriot/cheriot/release/micropython
85104
$(CLLVM_DIR)/bin/llvm-objcopy -O binary $< $@
86105

87106
$(BUILD)/micropython.uf2: $(BUILD)/micropython.bin
88-
~/.cargo/bin/uf2conv $< --base 0x00101000 --output $@
107+
$(UF2CONV) $< --base 0x00101000 --output $@
89108

90109
include $(TOP)/py/mkrules.mk

ports/cheriot-rtos/README.md

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,31 @@
1-
# The minimal port
1+
# The cheriot-rtos port
22

3-
This port is intended to be a minimal MicroPython port that actually runs.
4-
It can run under Linux (or similar) and on any STM32F4xx MCU (eg the pyboard).
3+
This is a port for CHERIoT systems, currently configured for the lowRISC Sonata board.
54

6-
## Building and running Linux version
5+
## Building MicroPython for CHERIoT
76

8-
By default the port will be built for the host machine:
7+
The following dependencies are required to build this port:
98

10-
$ make
9+
- [LLVM for CHERIoT](https://github.com/CHERIoT-Platform/llvm-project)
10+
- [CHERIoT RTOS](https://github.com/microsoft/cheriot-rtos)
11+
- Python 3
12+
- `make`
13+
- `uf2conv` (Can be installed through `cargo`)
1114

12-
To run the executable and get a basic working REPL do:
15+
To build, run the following (replacing `/path/to/xxx` with the relevant path on your system):
1316

14-
$ make run
17+
$ make CLLVM_DIR=/path/to/cheriot-llvm CRTOS_DIR=/path/to/cheriot-rtos UF2CONV=/path/to/uf2conv
1518

16-
## Building for an STM32 MCU
19+
- `CLLVM_DIR` should point to the parent directory of the `bin/` directory holding the CHERIoT llvm binaries.
20+
- `CRTOS_DIR` should point to the root of the CHERIoT RTOS git repository.
21+
- `UF2CONV` should point to the `uf2conv` executable.
1722

18-
The Makefile has the ability to build for a Cortex-M CPU, and by default
19-
includes some start-up code for an STM32F4xx MCU and also enables a UART
20-
for communication. To build:
23+
## Deploying MicroPython on the Sonata board
2124

22-
$ make CROSS=1
25+
Follow the instructions under 'Main persistent flow' at (Sonata v0.2)[https://github.com/lowRISC/sonata-system/releases/tag/v0.2], then drag the `build/micropython.uf2` file into the `SONATA` drive.
2326

24-
If you previously built the Linux version, you will need to first run
25-
`make clean` to get rid of incompatible object files.
27+
The MicroPython interpreter can then be accessed over the UART interface:
28+
$ sudo minicom -c on -D /dev/ttyUSB2
2629

27-
Building will produce the build/firmware.dfu file which can be programmed
28-
to an MCU using:
30+
In order to demonstrate the different MicroPython VM compartment entry points, a REPL is not automatically launched. Instead, press `r` to launch a REPL, `s` to execute the test string, `f` to load the test frozen module, or `q` to exit.
2931

30-
$ make CROSS=1 deploy
31-
32-
This version of the build will work out-of-the-box on a pyboard (and
33-
anything similar), and will give you a MicroPython REPL on UART1 at 9600
34-
baud. Pin PA13 will also be driven high, and this turns on the red LED on
35-
the pyboard.
36-
37-
## Building without the built-in MicroPython compiler
38-
39-
This minimal port can be built with the built-in MicroPython compiler
40-
disabled. This will reduce the firmware by about 20k on a Thumb2 machine,
41-
and by about 40k on 32-bit x86. Without the compiler the REPL will be
42-
disabled, but pre-compiled scripts can still be executed.
43-
44-
To test out this feature, change the `MICROPY_ENABLE_COMPILER` config
45-
option to "0" in the mpconfigport.h file in this directory. Then
46-
recompile and run the firmware and it will execute the frozentest.py
47-
file.

ports/cheriot-rtos/main.c

Lines changed: 24 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,35 @@
33
#include <string.h>
44
#include <compartment.h>
55

6-
#include "py/builtin.h"
7-
#include "py/compile.h"
8-
#include "py/runtime.h"
9-
#include "py/repl.h"
10-
#include "py/gc.h"
11-
#include "py/mperrno.h"
12-
#include "shared/runtime/pyexec.h"
13-
14-
#if MICROPY_ENABLE_COMPILER
15-
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
16-
nlr_buf_t nlr;
17-
if (nlr_push(&nlr) == 0) {
18-
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
19-
qstr source_name = lex->source_name;
20-
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
21-
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true);
22-
mp_call_function_0(module_fun);
23-
nlr_pop();
24-
} else {
25-
// uncaught exception
26-
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
27-
}
28-
}
29-
#endif
30-
31-
static char *stack_top;
32-
#if MICROPY_ENABLE_GC
33-
static char heap[16384]; //[MICROPY_HEAP_SIZE];
34-
#endif
6+
#include "mp_entry.h"
7+
#include "mphalport.h"
358

369
#include <stdio.h>
3710

38-
void __cheri_compartment("mp_main") mp_main(void) {
39-
MP_STATE_THREAD_HACK_INIT
11+
void __cheri_compartment("main") entry(void) {
4012
*MMIO_CAPABILITY(uint32_t, gpio) = 0xaa;
4113
printf("Test\n");
42-
int stack_dummy;
43-
stack_top = (char *)&stack_dummy;
44-
#if MICROPY_ENABLE_GC
45-
gc_init(heap, heap + sizeof(heap));
46-
printf("GC initialised\n");
47-
#endif
48-
mp_init();
49-
printf("Micropython initialised\n");
50-
#if MICROPY_ENABLE_COMPILER
51-
#if MICROPY_REPL_EVENT_DRIVEN
52-
pyexec_event_repl_init();
53-
for (;;) {
54-
int c = mp_hal_stdin_rx_chr();
55-
if (pyexec_event_repl_process_char(c)) {
56-
break;
57-
}
14+
mp_vminit();
15+
while(1) switch(mp_hal_stdin_rx_chr()) {
16+
#if MICROPY_ENABLE_COMPILER
17+
case 'r':
18+
if(!mp_friendly_repl()) continue;
19+
printf("REPL exited with a failure\n");
20+
return;
21+
#endif
22+
case 's':
23+
if(!mp_exec_str_single("print('foo', 7*8*9, [ 'bar', 'baz' ])")) continue;
24+
printf("String execution exited with a failure\n");
25+
case 'f':
26+
if(!mp_exec_frozen_module("frozentest.py")) continue;
27+
printf("Frozen module exited with a failure\n");
28+
return;
29+
break;
30+
case 'q':
31+
mp_vmexit();
32+
printf("VM Exited");
33+
return;
5834
}
59-
#else
60-
pyexec_friendly_repl();
61-
#endif
62-
// do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
63-
// do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT);
64-
#else
65-
#error "We don't want to be using frozen modules"
66-
pyexec_frozen_module("frozentest.py", false);
67-
#endif
68-
mp_deinit();
6935
}
7036

7137
enum ErrorRecoveryBehaviour compartment_error_handler(struct ErrorState *frame, size_t mcause, size_t mtval) {
@@ -107,46 +73,7 @@ enum ErrorRecoveryBehaviour compartment_error_handler(struct ErrorState *frame,
10773
if(__builtin_cheri_tag_get(stack)) for(int i = 0; i < 32; i++) {
10874
printf("\t\t+%02x : %p [base %lx, len %lx, perms %lx, tag %d]\n", sizeof(void*)*i, stack[i], __builtin_cheri_base_get(stack[i]), __builtin_cheri_length_get(stack[i]), __builtin_cheri_perms_get(stack[i]), __builtin_cheri_tag_get(stack[i]));
10975
}
110-
while(1);//mp_raise_OSError(mcause);
111-
}
112-
113-
114-
#if MICROPY_ENABLE_GC
115-
void gc_collect(void) {
116-
// WARNING: This gc_collect implementation doesn't try to get root
117-
// pointers from CPU registers, and thus may function incorrectly.
118-
void *dummy;
119-
gc_collect_start();
120-
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
121-
gc_collect_end();
122-
gc_dump_info(&mp_plat_print);
123-
}
124-
#endif
125-
126-
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
127-
mp_raise_OSError(MP_ENOENT);
76+
while(1);
12877
}
12978

130-
mp_import_stat_t mp_import_stat(const char *path) {
131-
return MP_IMPORT_STAT_NO_EXIST;
132-
}
133-
134-
void nlr_jump_fail(void *val) {
135-
while (1) {
136-
;
137-
}
138-
}
139-
140-
void NORETURN __fatal_error(const char *msg) {
141-
while (1) {
142-
;
143-
}
144-
}
145-
146-
#ifndef NDEBUG
147-
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
148-
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
149-
__fatal_error("Assertion failed");
150-
}
151-
#endif
15279

0 commit comments

Comments
 (0)