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

Should not be here. Use of SP_EL0 in EL1 is not supported.

Error message

Should not be here. Use of SP_EL0 in EL1 is not supported.

What it means

current_el0_synchronous is the vector-table entry for synchronous exceptions taken at the current exception level when using SP_EL0, which this kernel does not support (it runs at EL1 with its own stack). The handler unconditionally panics. It exists only so that every vector slot is defined; reaching it means user-mode (EL0) execution or SP_EL0 use happened although the kernel never intends to support it.

Source

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

// 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.")
}

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

//------------------------------------------------------------------------------
// Current, ELx
//------------------------------------------------------------------------------

#[no_mangle]
extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {

View on GitHub (pinned to 644474cc09)

Solutions

  1. Do not run code at EL0 or switch to SP_EL0; audit boot and context-switch code for `msr spsel, #0` and remove it.
  2. If user-mode support is intended, replace this stub with a real EL0 synchronous handler (syscall dispatch, abort handling) as a prerequisite.
  3. Check the ESR in a temporary debug handler to find what invoked the vector if the origin is unclear.

Example fix

// before
unsafe { core::arch::asm!("msr SPSel, #0"); } // switches to SP_EL0 -> unsupported
// after
// keep SPSel = 1: kernel always uses SP_ELx at EL1
unsafe { core::arch::asm!("msr SPSel, #1"); }
Defensive patterns

Strategy: validation

Validate before calling

// Assert the kernel never switches to SP_EL0:
fn ensure_kernel_sp() {
    let spsel: u64;
    unsafe { core::arch::asm!("mrs {}, SPSel", out(reg) spsel) };
    assert!(spsel == 1, "SPSel must be 1 at EL1");
}

Prevention

When it happens

Trigger: Taking a synchronous exception (e.g. SVC, instruction abort, data abort) at the current EL while SP_EL0 is the active stack pointer — i.e. code running in EL0 state or an explicit SP switch to SP_EL0 in EL1.

Common situations: Attempting to implement user-space processes before the kernel supports EL0, accidentally setting SPSel to 0 in early boot or context-switch code, or porting code that issues `svc` calls expecting syscall support that this tutorial kernel does not provide.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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