Tidy simulation_exit Wrap the cross-call, which can fail, in a noreturn void wrapper that can't. Tweak callers appropriately. Have the scheduler internally use the platform layer everywhere.
diff --git a/sdk/core/scheduler/main.cc b/sdk/core/scheduler/main.cc index d4d36a8..132103b 100644 --- a/sdk/core/scheduler/main.cc +++ b/sdk/core/scheduler/main.cc
@@ -31,9 +31,10 @@ /** * Exit simulation, reporting the error code given as the argument. */ -void simulation_exit(uint32_t code) +int scheduler_simulation_exit(uint32_t code) { platform_simulation_exit(code); + return -EPROTO; } #endif @@ -228,8 +229,10 @@ static_cast<uint32_t>(capcause), badcap); +#ifdef SIMULATION // If we're in simulation, exit here - simulation_exit(1); + platform_simulation_exit(1); +#endif for (;;) { @@ -300,9 +303,11 @@ // Make the current thread non-runnable. if (Thread::exit()) { +#ifdef SIMULATION // If we have no threads left (not counting the idle // thread), exit. - simulation_exit(0); + platform_simulation_exit(0); +#endif } // We cannot continue exiting this thread, make sure we will // pick a new one.
diff --git a/sdk/include/fail-simulator-on-error.h b/sdk/include/fail-simulator-on-error.h index cad8bd7..1c656aa 100644 --- a/sdk/include/fail-simulator-on-error.h +++ b/sdk/include/fail-simulator-on-error.h
@@ -67,11 +67,14 @@ DebugErrorHandler::log("Unhandled error {} at {}", mcause, frame->pcc); } - simulation_exit(1); +#ifdef SIMULATION /* - * simulation_exit may fail (say, we're not on a simulator or there isn't + * simulation exit may fail (say, we're not on a simulator or there isn't * enough stack space to invoke the function. In that case, just fall back * to forcibly unwinding. */ + (void)scheduler_simulation_exit(1); +#endif + return ErrorRecoveryBehaviour::ForceUnwind; }
diff --git a/sdk/include/simulator.h b/sdk/include/simulator.h index 9de4a77..2d4733b 100644 --- a/sdk/include/simulator.h +++ b/sdk/include/simulator.h
@@ -3,14 +3,34 @@ #pragma once #include <compartment.h> +#include <errno.h> #include <stdint.h> #ifdef SIMULATION /** * Exit simulation, reporting the error code given as the argument. */ -[[cheri::interrupt_state(disabled)]] void __cheri_compartment("sched") - simulation_exit(uint32_t code = 0); -#else -static inline void simulation_exit(uint32_t code){}; +[[cheri::interrupt_state(disabled)]] int __cheri_compartment("sched") + scheduler_simulation_exit(uint32_t code __if_cxx(= 0)); #endif + +/** + * Exit the simulation, if we can, or fall back to an infinite loop. + */ +static inline void __attribute__((noreturn)) +simulation_exit(uint32_t code __if_cxx(= 0)) +{ +#ifdef SIMULATION + /* + * This fails only if either we are out of (trusted) stack space for the + * cross-call or the platform is misconfigured. If either of those happen, + * fall back to infinite looping. + */ + (void)scheduler_simulation_exit(code); +#endif + + while (true) + { + yield(); + } +};
diff --git a/tests/test-runner.cc b/tests/test-runner.cc index c9f3acb..37d2958 100644 --- a/tests/test-runner.cc +++ b/tests/test-runner.cc
@@ -66,10 +66,7 @@ if (mcause == 0x2) { debug_log("Test failure in test runner"); -#ifdef SIMULATION simulation_exit(1); -#endif - return ErrorRecoveryBehaviour::ForceUnwind; } debug_log("mcause: {}, pcc: {}", mcause, frame->pcc); auto [reg, cause] = CHERI::extract_cheri_mtval(mtval); @@ -162,13 +159,5 @@ TEST(crashDetected == false, "One or more tests failed"); - // Exit the simulator if we are running in simulation. -#ifdef SIMULATION simulation_exit(); -#endif - // Infinite loop if we're not in simulation. - while (true) - { - yield(); - } }