CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
fail-simulator-on-error.h
1#include "compartment.h"
2#include <cheri.hh>
3#include <debug.hh>
4#include <priv/riscv.h>
5#include <simulator.h>
6
7using DebugErrorHandler = ConditionalDebug<
8#ifdef NDEBUG
9 false
10#else
11 true
12#endif
13 ,
14 "Error handler">;
15
16/**
17 * A error handler that reports unexpected traps and calls the scheduler to
18 * request that the simulator exit with exit code 1 (FAILURE).
19 *
20 * This is useful because the default behaviour in the absence of an error
21 * handler is to unwind the trusted stack and exit the thread when the top of
22 * the stack is reached. If all threads exit then the scheduler will exit the
23 * simulation with SUCCESS, which might mask errors.
24 *
25 * We attempt to detect the trap that occurs when a thread returns from its
26 * entry point function and do not halt the simulation as this is considered
27 * normal.
28 *
29 * Unwinds caused by errors in called compartments are also detected and are not
30 * treated as errors -- instead we resume execution at the call point with a
31 * return value of -1 as though this handler is not present.
32 *
33 * On non-simulation platforms this error handler reverts to the default force
34 * unwind behaviour.
35 *
36 * If NDEBUG is not defined then errors and thread exits will be logged.
37 *
38 * To use this simply include this file in your compartment's c / cc file.
39 */
40extern "C" ErrorRecoveryBehaviour
41compartment_error_handler(ErrorState *frame, size_t mcause, size_t mtval)
42{
43 if (mcause == priv::MCAUSE_CHERI)
44 {
45 // An unexpected error -- log it and end the simulation with error.
46 // Note: handle CZR differently as `get_register_value` will return a
47 // nullptr which we cannot dereference.
48
49 auto [exceptionCode, registerNumber] =
51
52 DebugErrorHandler::log(
53 "{} error at {} (return address: {}), with capability register "
54 "{}: {}",
55 exceptionCode,
56 frame->pcc,
58 registerNumber,
59 registerNumber == CHERI::RegisterNumber::CZR
60 ? nullptr
61 : *frame->get_register_value(registerNumber));
62 }
63 else
64 {
65 // other error (e.g. __builtin_trap causes ReservedInstruciton)
66 // log and end simulation with error.
67 DebugErrorHandler::log("Unhandled error {} at {}", mcause, frame->pcc);
68 }
69
70#ifdef SIMULATION
71 /*
72 * simulation exit may fail (say, we're not on a simulator or there isn't
73 * enough stack space to invoke the function. In that case, just fall back
74 * to forcibly unwinding.
75 */
76 (void)scheduler_simulation_exit(1);
77#endif
78
79 return ErrorRecoveryBehaviour::ForceUnwind;
80}
C++ helpers for operating on capabilities.
@ CZR
The zero register, which always contains the NULL capability.
Definition cheri.hh:1445
@ CRA
$c1 / $cra used by the ABI as the return address.
Definition cheri.hh:1450
std::pair< CauseCode, RegisterNumber > extract_cheri_mtval(uint32_t mtval)
Decompose the value reported in the mtval CSR on CHERI exception into a pair of CauseCode and Registe...
Definition cheri.hh:1579
C++ APIs for assertions, invariants, and writing formatted debug messages to a UART.
State for error handlers to use.
Definition compartment.h:21
void *& get_register_value()
Templated method to get a reference to value of given CHERI::RegisterNumber.
Definition compartment.h:49
void * pcc
The faulting program counter.
Definition compartment.h:32