From 4568f5892d0e4ee202f37fcb2c3edf78eef296df Mon Sep 17 00:00:00 2001 From: "Cliff L. Biffle" Date: Tue, 26 Nov 2024 11:19:15 -0800 Subject: [PATCH] Enable a panic-free Jefe for the first time The supervisor task in Hubris is not permitted to panic, since it's responsible for handling panics. Jefe has historically contained a bunch of (static) panics, many of which aren't actually possible at runtime. I've been gradually grinding away at these in my other PRs. As of #1937, it's now possible to build a _minimal_ Jefe (like we use on the G0) that contains no panics. So I've enabled that on donglet, and turned on the userlib/no-panic feature that will statically ensure it remains true. Turning on dump support in Jefe causes a bunch of panics to reappear, because humpty is panic-heavy. That's a task for another day. In addition to eliminating all panic sites, this also eliminates the last indirect function calls from the generated binaries -- meaning, the static stack size estimate is very likely exact. So I have taken the opportunity to shrink the stack by a bit, reclaiming 256 bytes of RAM on this RAM-starved part. --- app/donglet/app-g031.toml | 3 ++- task/jefe/Cargo.toml | 1 + task/jefe/src/main.rs | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/donglet/app-g031.toml b/app/donglet/app-g031.toml index 94f077e58..3cfacc6b5 100644 --- a/app/donglet/app-g031.toml +++ b/app/donglet/app-g031.toml @@ -15,8 +15,9 @@ name = "task-jefe" priority = 0 max-sizes = {flash = 4096, ram = 512} start = true -stacksize = 368 +stacksize = 192 notifications = ["fault", "timer"] +features = ["no-panic", "nano"] [tasks.sys] name = "drv-stm32xx-sys" diff --git a/task/jefe/Cargo.toml b/task/jefe/Cargo.toml index 820b47b59..bae3c207f 100644 --- a/task/jefe/Cargo.toml +++ b/task/jefe/Cargo.toml @@ -31,6 +31,7 @@ build-util = { path = "../../build/util" } [features] dump = [] nano = [ "ringbuf/disabled" ] +no-panic = [ "userlib/no-panic" ] # This section is here to discourage RLS/rust-analyzer from doing test builds, # since test builds don't work for cross compilation. diff --git a/task/jefe/src/main.rs b/task/jefe/src/main.rs index 2d48acd1d..331cdd05f 100644 --- a/task/jefe/src/main.rs +++ b/task/jefe/src/main.rs @@ -310,9 +310,19 @@ impl idol_runtime::NotificationHandler for ServerImpl<'_> { let mut next_task = 1; while let Some(fault_index) = kipc::find_faulted_task(next_task) { let fault_index = usize::from(fault_index); - next_task = fault_index + 1; - - let status = &mut self.task_states[fault_index]; + // This addition cannot overflow in practice, because the number + // of tasks in the system is very much smaller than 2**32. So we + // use wrapping add, because currently the compiler doesn't + // understand this property. + next_task = fault_index.wrapping_add(1); + + // Safety: `fault_index` is from the kernel, and the kernel will + // not give us an out-of-range task index. + // + // TODO: it might be nice to fold this into a utility function + // in kipc or something + let status = + unsafe { self.task_states.get_unchecked_mut(fault_index) }; // If we're aware that this task is in a fault state, don't // bother making a syscall to enquire.