From 950b9ac4d68286585e4369efcf904704d8de9c53 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 24 Nov 2022 16:54:49 +0000 Subject: [PATCH] firmware: More explicit panic message if stack guard is tripped This should give even only mildly technical users a chance to figure out what's going on, which empirically is not the case for a plain Exception(LoadFault) without further context. --- artiq/firmware/ksupport/lib.rs | 15 ++++++++++++++- artiq/firmware/libboard_misoc/riscv32/pmp.rs | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index d9786ae3c..7bb1e675a 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -471,6 +471,8 @@ unsafe fn attribute_writeback(typeinfo: *const ()) { } } +static mut STACK_GUARD_BASE: usize = 0x0; + #[no_mangle] pub unsafe fn main() { eh_artiq::reset_exception_buffer(KERNELCPU_PAYLOAD_ADDRESS); @@ -502,6 +504,7 @@ pub unsafe fn main() { ptr::write_bytes(__bss_start as *mut u8, 0, (_end - __bss_start) as usize); board_misoc::pmp::init_stack_guard(_sstack_guard as usize); + STACK_GUARD_BASE = _sstack_guard as usize; board_misoc::cache::flush_cpu_dcache(); board_misoc::cache::flush_cpu_icache(); @@ -531,10 +534,20 @@ pub unsafe fn main() { #[no_mangle] #[unwind(allowed)] -pub extern fn exception(_regs: *const u32) { +pub unsafe extern fn exception(_regs: *const u32) { let pc = mepc::read(); let cause = mcause::read().cause(); let mtval = mtval::read(); + if let mcause::Trap::Exception(mcause::Exception::LoadFault) + | mcause::Trap::Exception(mcause::Exception::StoreFault) = cause + { + if mtval >= STACK_GUARD_BASE + && mtval < (STACK_GUARD_BASE + board_misoc::pmp::STACK_GUARD_SIZE) + { + panic!("{:?} at PC {:#08x} in stack guard page ({:#08x}); stack overflow in user kernel code?", + cause, u32::try_from(pc).unwrap(), mtval); + } + } panic!("{:?} at PC {:#08x}, trap value {:#08x}", cause, u32::try_from(pc).unwrap(), mtval); } diff --git a/artiq/firmware/libboard_misoc/riscv32/pmp.rs b/artiq/firmware/libboard_misoc/riscv32/pmp.rs index 9ac80b9e3..976f257b1 100644 --- a/artiq/firmware/libboard_misoc/riscv32/pmp.rs +++ b/artiq/firmware/libboard_misoc/riscv32/pmp.rs @@ -9,6 +9,8 @@ const PMP_W : usize = 0b00000010; const PMP_R : usize = 0b00000001; const PMP_OFF : usize = 0b00000000; +pub const STACK_GUARD_SIZE: usize = 0x1000; + #[inline(always)] pub unsafe fn init_stack_guard(guard_base: usize) { pmpaddr2::write((guard_base >> 2) | ((0x1000 - 1) >> 3));