Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions examples/automotive/cheri/send.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,35 @@ void reset_error_seen_and_shown()
* violation message or not, and display it if so. This will only be
* drawn once, and then `errorMessageShown` will be set true.
*/
void lcd_display_cheri_message()
void update_cheri_error_handling()
{
if (!errorSeen || errorMessageShown)
if (!errorSeen)
{
return;
}

/*
* We expect that we might correct the compartment's fault many times,
* especially since the error is being triggered every frame. As a
* built-in protection, the CHERIoT RTOS switcher places a default
* limit of 512 times a compartment invocation may fault, to help
* stop compartments getting stuck during recovery.
*
* Since this is a legitimate use case, and we don't want our demo
* to stop working after 512 errors, reset the counter each time.
*
* We have to restore it here and not in the error handler as otherwise
* the switcher will decrement its count and then underflow, which it
* will see as a double fault and then unwind.
*
* See:
* https://github.com/CHERIoT-Platform/cheriot-rtos/issues/299
* https://github.com/CHERIoT-Platform/cheriot-rtos/blob/9f3731c0e3805ad56a642987be9bc859e2ee1b4e/sdk/include/switcher.h#L40-L41
*/
switcher_handler_invocation_count_reset();
errorSeen = false;

if (errorMessageShown)
{
return;
}
Expand Down Expand Up @@ -537,7 +563,7 @@ void __cheri_compartment("automotive_send") entry()
.wait = wait,
.waitTime = 120 * CyclesPerMillisecond,
.time = rdcycle64,
.loop = lcd_display_cheri_message,
.loop = update_cheri_error_handling,
.start = reset_error_seen_and_shown,
.joystick_read = read_joystick,
.digital_pedal_read = read_pedal_digital,
Expand Down
31 changes: 31 additions & 0 deletions examples/snake/snake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ static constexpr Color BackgroundColor = Color::Black,
static constexpr Size TileSize = {10, 10}, TileSpacing = {2, 2},
BorderSize = {4, 3};

// Global flag used by the CHERI compartment error handler to detect when a
// capability violation has occurred, so that we can modify the switcher context
// appropriately.
static bool errorSeen = false;

typedef struct Position
{
int32_t x;
Expand Down Expand Up @@ -511,6 +516,26 @@ class SnakeGame
return true;
}

/* If any fault was seen in the compartment, handle the error.*/
void handle_compartment_faults()
{
/*
* Just in case somebody wants to play 512+ games of Snake without
* resetting, lets be safe and reset the switcher handler invocation
* count due to our PCC re-installation.
*
* We have to restore it here and not in the error handler as otherwise
* the switcher will decrement its count and then underflow, which it
* will see as a double fault and then unwind.
*
* See:
* https://github.com/CHERIoT-Platform/cheriot-rtos/issues/299
* https://github.com/CHERIoT-Platform/cheriot-rtos/blob/9f3731c0e3805ad56a642987be9bc859e2ee1b4e/sdk/include/switcher.h#L40-L41
* */
switcher_handler_invocation_count_reset();
errorSeen = false;
}

/**
* @brief Runs the main game loop, updating the snake's movement and drawing
* new information to the display, and regulates update/frame timing.
Expand Down Expand Up @@ -551,6 +576,11 @@ class SnakeGame
currentTime = rdcycle64();

gameStillActive = update_game_state(gpio, lcd);

if (errorSeen)
{
handle_compartment_faults();
}
}
};

Expand Down Expand Up @@ -627,6 +657,7 @@ compartment_error_handler(ErrorState *frame, size_t mcause, size_t mtval)
if (exceptionCode == CauseCode::BoundsViolation ||
exceptionCode == CauseCode::TagViolation)
{
errorSeen = true;
// If an explicit out of bounds access occurs, or bounds are made
// invalid by some negative array access, we **assume** that this was
// caused by the SnakeGame::check_if_colliding function and that the
Expand Down
Loading