rust-embedded/rust-raspberrypi-OS-tutorials · critical

CPU Exception! {}

Error message

CPU Exception!

{}

What it means

The kernel's default exception vector handler panics whenever the CPU takes an exception (synchronous, IRQ, SError, from any EL) that is routed to the catch-all handler in the aarch64 exception vector table. It prints the full ExceptionContext (ESR, FAR, PC, SP) so the developer can see exactly which exception occurred and where. This library throws it because an unexpected CPU exception indicates the kernel executed an invalid or unhandled condition and cannot safely continue.

Source

Thrown at 20_timer_callbacks/kernel/src/_arch/aarch64/exception.rs:63

    lr: u64,

    /// Exception link register. The program counter at the time the exception happened.
    elr_el1: u64,

    /// Saved program status.
    spsr_el1: SpsrEL1,

    /// Exception syndrome register.
    esr_el1: EsrEL1,
}

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

/// Prints verbose information about the exception and then panics.
fn default_exception_handler(exc: &ExceptionContext) {
    panic!(
        "CPU Exception!\n\n\
        {}",
        exc
    );
}

//------------------------------------------------------------------------------
// Current, EL0
//------------------------------------------------------------------------------

#[no_mangle]
extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
    panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}

#[no_mangle]
extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
    panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")

View on GitHub (pinned to 644474cc09)

Solutions

  1. Read the printed ExceptionContext: decode the ESR (Exception Syndrome Register) to identify the exact exception class and the FAR for the faulting address.
  2. Locate the PC recorded in the context and inspect the kernel code/instruction at that address for the invalid access or instruction.
  3. Fix the offending kernel code (bad pointer, unaligned access, unsupported instruction) or register a proper handler for that exception class in the vector table.
  4. If it happens in lower-EL (EL0) entry paths, ensure user-mode transitions and SP_EL0 usage are actually supported before triggering them.
  5. Rebuild with debug symbols and run under QEMU -d int,cpu_reset to trace exception entry if the context alone is insufficient.

Example fix

// before
let val = unsafe { *(0x0 as *const u64) }; // unmapped address -> synchronous abort -> CPU Exception!
// after
if let Some(ptr) = VALID_MMIO_RANGE.contains_ptr(addr) {
    let val = unsafe { ptr.read_volatile() };
}
Defensive patterns

Strategy: validation

Validate before calling

// Before dereferencing an address in kernel code, assert it is within a mapped range:
fn addr_is_mapped(addr: usize) -> bool {
    addr >= KERNEL_MEM_START && addr < KERNEL_MEM_END
}

Type guard

fn is_valid_mmio(addr: usize) -> bool {
    const MMIO_START: usize = 0x3F00_0000;
    const MMIO_END: usize = 0x4000_0000;
    (MMIO_START..MMIO_END).contains(&addr)
}

Prevention

When it happens

Trigger: Any CPU exception routed to default_exception_handler via current_elx_synchronous, current_elx_serror, lower_aarch64_synchronous/irq/serror, or lower_aarch32_* vector entries: e.g. a data abort from a bad pointer dereference, an unaligned access, an undefined instruction, or an IRQ/SError arriving while a more specific handler is not wired into the vector table for that routing.

Common situations: Dereferencing null or unmapped addresses in kernel code, executing invalid instructions on a target that lacks a feature, misconfigured vector table entries (wrong target EL or stack), enabling interrupts before handlers exist, or porting the kernel to hardware whose exception routing differs from the BSP assumptions.

Related errors


AI-assisted analysis of rust-embedded/rust-raspberrypi-OS-tutorials@644474cc09 (2026-09-06). Data as JSON: /api/errors/3962405476265864. Report an issue: GitHub.