rust-embedded/rust-raspberrypi-OS-tutorials · error
Invalid KERNEL_STATE
Error message
Invalid KERNEL_STATE
What it means
The kernel state machine stores its state in an AtomicU8 with sentinel values (INIT, SINGLE_CORE_MAIN, MULTI_CORE_MAIN). state() loads the atomic and panics if the raw value matches none of the known sentinels, indicating corrupted or uninitialized KERNEL_STATE memory. is_init() calls state(), so any state query on corrupted state panics.
Source
Thrown at 20_timer_callbacks/kernel/src/state.rs:68
impl StateManager {
const INIT: u8 = 0;
const SINGLE_CORE_MAIN: u8 = 1;
const MULTI_CORE_MAIN: u8 = 2;
/// Create a new instance.
pub const fn new() -> Self {
Self(AtomicU8::new(Self::INIT))
}
/// Return the current state.
fn state(&self) -> State {
let state = self.0.load(Ordering::Acquire);
match state {
Self::INIT => State::Init,
Self::SINGLE_CORE_MAIN => State::SingleCoreMain,
Self::MULTI_CORE_MAIN => State::MultiCoreMain,
_ => panic!("Invalid KERNEL_STATE"),
}
}
/// Return if the kernel is init state.
pub fn is_init(&self) -> bool {
self.state() == State::Init
}
/// Transition from Init to SingleCoreMain.
pub fn transition_to_single_core_main(&self) {
if self
.0
.compare_exchange(
Self::INIT,
Self::SINGLE_CORE_MAIN,
Ordering::Acquire,
Ordering::Relaxed,
)View on GitHub (pinned to 644474cc09)
Solutions
- Ensure KERNEL_STATE is initialized (to INIT) at/before its first use — check static initialization in state.rs.
- Find any code writing raw values into the atomic and validate it uses the defined constants only.
- Initialize the atomic with Self::INIT as its default value so it can never hold a sentinel-unknown value.
- Check linker script / memory layout for overlap with other statics that could corrupt this cell.
- Gate early-boot callers so is_init() isn't invoked before state setup.
Example fix
// before static KERNEL_STATE: AtomicU8 = AtomicU8::new(0xff); // after static KERNEL_STATE: AtomicU8 = AtomicU8::new(KernelState::INIT as u8);
Defensive patterns
Strategy: validation
Validate before calling
fn state_is_known(raw: u8) -> bool {
matches!(raw, s if s == INIT || s == SINGLE_CORE_MAIN || s == MULTI_CORE_MAIN)
} Type guard
fn valid_kernel_state(raw: u8) -> Option<State> {
match raw {
x if x == INIT => Some(State::Init),
x if x == SINGLE_CORE_MAIN => Some(State::SingleCoreMain),
x if x == MULTI_CORE_MAIN => Some(State::MultiCoreMain),
_ => None,
}
} Try / catch
// Panic aborts in no_std; validate raw value before querying:
let raw = KERNEL_STATE.load(Ordering::Acquire);
if valid_kernel_state(raw).is_none() {
log::error!("corrupted KERNEL_STATE: {}", raw);
halt();
} Prevention
- Initialize the state atomic with a valid sentinel (INIT) as its default.
- Only write the state through the defined transition methods.
- Verify linker/memory layout doesn't overlap the static.
- Never transmute or hand-write raw values into the state cell.
When it happens
Trigger: Reading kernel state before the static KERNEL_STATE was initialized with a valid value (memory not zeroed/initialized to INIT); memory corruption overwriting the atomic; a bad transmute/write to the static from elsewhere; calling is_init()/state() on a wrongly constructed StateProvider.
Common situations: Early-boot code querying state before state initialization in .bss/.data setup; linker/script changes that clobber the static; concurrent unynchronized writes to the state cell; hand-edited sentinel constants.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- transition_to_single_core_main() called while state != Init
- Attempt to enable IRQ {} for device {}, but driver does not
- Error initializing driver: {}: {}
- Error during driver post-init callback: {}: {}
- Error during driver interrupt handler registration: {}: {}
AI-assisted analysis of rust-embedded/rust-raspberrypi-OS-tutorials@644474cc09 (2026-09-06).
Data as JSON: /api/errors/06e09030f1214d4c.
Report an issue: GitHub.