1
use crate::trapframe::TrapFrame;
2

            
3
#[cfg(xtensa)]
4
#[unsafe(no_mangle)]
5
#[unsafe(link_section = ".rwtext")]
6
unsafe extern "C" fn __user_exception(
7
    cause: xtensa_lx_rt::exception::ExceptionCause,
8
    context: &TrapFrame,
9
) {
10
    panic!(
11
        "\n\nException occurred on {:?} '{:?}'\n{:?}",
12
        crate::system::Cpu::current(),
13
        cause,
14
        context
15
    );
16
}
17

            
18
#[cfg(all(xtensa, stack_guard_monitoring))]
19
#[inline(always)]
20
pub(crate) fn breakpoint_interrupt(context: &TrapFrame) {
21
    let mut dbgcause: u32;
22
    unsafe {
23
        core::arch::asm!(
24
            "rsr.debugcause {0}",
25
            out(reg) dbgcause, options(nostack)
26
        );
27
    }
28

            
29
    #[cfg(stack_guard_monitoring)]
30
    if dbgcause & 4 != 0 && dbgcause & 0b1111_0000_0000 == 0 {
31
        panic!(
32
            "\n\nDetected a write to the stack guard value on {:?}\n{:?}",
33
            crate::system::Cpu::current(),
34
            context
35
        );
36
    }
37

            
38
    panic!(
39
        "\n\nBreakpoint on {:?}\n{:?}\nDebug cause: {}",
40
        crate::system::Cpu::current(),
41
        context,
42
        dbgcause
43
    );
44
}
45

            
46
#[cfg(riscv)]
47
#[unsafe(no_mangle)]
48
unsafe extern "C" fn ExceptionHandler(context: &TrapFrame) -> ! {
49
    let mepc = riscv::register::mepc::read();
50
    let code = riscv::register::mcause::read().bits() & property!("soc.cpu_mcause_mask");
51
    let mtval = riscv::register::mtval::read();
52

            
53
    unsafe extern "C" {
54
        static mut __stack_chk_guard: u32;
55
    }
56

            
57
    let core = crate::system::Cpu::current();
58

            
59
    if code == 14 {
60
        panic!(
61
            "[{:?}] Stack overflow detected at 0x{:x}, possibly called by 0x{:x}",
62
            core, mepc, context.ra
63
        );
64
    }
65

            
66
    #[cfg(stack_guard_monitoring)]
67
    if code == 3 {
68
        let guard_addr = core::ptr::addr_of_mut!(__stack_chk_guard) as *mut _ as usize;
69

            
70
        if mtval == guard_addr {
71
            panic!(
72
                "[{:?}] Detected a write to the main stack's guard value at 0x{:x}, possibly called by 0x{:x}",
73
                core, mepc, context.ra
74
            )
75
        } else {
76
            if unsafe { crate::debugger::watchpoint_hit(1) } {
77
                panic!(
78
                    "[{:?}] Detected a write to the trap/rwtext segment at 0x{:x}, possibly called by 0x{:x}",
79
                    core, mepc, context.ra
80
                );
81
            } else if unsafe { crate::debugger::watchpoint_hit(0) } {
82
                panic!(
83
                    "[{:?}] Detected a write to a stack guard value at 0x{:x}, possibly called by 0x{:x}",
84
                    core, mepc, context.ra
85
                );
86
            } else {
87
                panic!(
88
                    "[{:?}] Breakpoint exception at 0x{:08x}, mtval=0x{:08x}\n{:?}",
89
                    core, mepc, mtval, context
90
                );
91
            }
92
        }
93
    }
94

            
95
    let code_str = match code {
96
        0 => "Instruction address misaligned",
97
        1 => "Instruction access fault",
98
        2 => "Illegal instruction",
99
        3 => "Breakpoint",
100
        4 => "Load address misaligned",
101
        5 => "Load access fault",
102
        6 => "Store/AMO address misaligned",
103
        7 => "Store/AMO access fault",
104
        8 => "Environment call from U-mode",
105
        9 => "Environment call from S-mode",
106
        10 => "Reserved",
107
        11 => "Environment call from M-mode",
108
        12 => "Instruction page fault",
109
        13 => "Load page fault",
110
        14 => "Reserved",
111
        15 => "Store/AMO page fault",
112
        #[cfg(esp32p4)]
113
        0x1f => "Illegal PIE instruction",
114
        _ => "UNKNOWN",
115
    };
116

            
117
    panic!(
118
        "[{:?}] Exception '{} ({:x})' mepc=0x{:08x}, mtval=0x{:08x}\n{:?}",
119
        core, code_str, code, mepc, mtval, context
120
    );
121
}