1use crate::early_println;
6
7extern crate gimli;
8
9#[linkage = "weak"]
14#[unsafe(no_mangle)]
16pub fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
17 let _irq_guard = crate::irq::disable_local();
18
19 crate::cpu_local_cell! {
20 static IN_PANIC: bool = false;
21 }
22
23 if IN_PANIC.load() {
24 early_println!("The panic handler panicked {:#?}", info);
25 abort();
26 }
27
28 IN_PANIC.store(true);
29
30 early_println!("Non-resettable panic! {:#?}", info);
31
32 print_stack_trace();
33 abort();
34}
35
36pub fn abort() -> ! {
40 crate::power::poweroff(crate::power::ExitCode::Failure);
44}
45
46#[derive(Debug)]
51pub(crate) struct PanicGuard {
52 _private: (),
53}
54
55impl Drop for PanicGuard {
56 fn drop(&mut self) {
57 early_println!("Panicked in `PanicGuard`, aborting the system");
58 abort();
59 }
60}
61
62impl PanicGuard {
63 pub(crate) fn new() -> Self {
65 PanicGuard { _private: () }
66 }
67
68 pub(crate) fn forget(self) {
73 core::mem::forget(self);
74 }
75}
76
77#[cfg(not(target_arch = "loongarch64"))]
78pub use unwinding::panic::{begin_panic, catch_unwind};
79
80#[cfg(not(target_arch = "loongarch64"))]
84pub fn print_stack_trace() {
85 use core::ffi::c_void;
86
87 use gimli::Register;
88 use unwinding::abi::{
89 _Unwind_Backtrace, _Unwind_FindEnclosingFunction, _Unwind_GetGR, _Unwind_GetIP,
90 UnwindContext, UnwindReasonCode,
91 };
92
93 use crate::{early_print, sync::SpinLock};
94
95 static BACKTRACE_PRINT_LOCK: SpinLock<()> = SpinLock::new(());
98 let _lock = BACKTRACE_PRINT_LOCK.lock();
99
100 early_println!("Printing stack trace:");
101
102 struct CallbackData {
103 counter: usize,
104 }
105 extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
106 let data = unsafe { &mut *(arg as *mut CallbackData) };
107 data.counter += 1;
108 let pc = _Unwind_GetIP(unwind_ctx);
109 if pc > 0 {
110 let fde_initial_address = _Unwind_FindEnclosingFunction(pc as *mut c_void) as usize;
111 early_println!(
112 "{:4}: fn {:#18x} - pc {:#18x} / registers:",
113 data.counter,
114 fde_initial_address,
115 pc,
116 );
117 }
118 for i in 0..8u16 {
121 let reg_name = cfg_select! {
122 target_arch = "x86_64" => gimli::X86_64::register_name(Register(i)),
123 target_arch = "riscv64" => gimli::RiscV::register_name(Register(i)),
124 target_arch = "aarch64" => gimli::AArch64::register_name(Register(i)),
125 _ => None,
126 };
127 let reg_val = _Unwind_GetGR(unwind_ctx, i as i32);
128 if i.is_multiple_of(4) {
129 early_print!("\n ");
130 }
131 early_print!(" {} {:#18x};", reg_name.unwrap_or("unknown"), reg_val);
132 }
133 early_print!("\n\n");
134 UnwindReasonCode::NO_REASON
135 }
136
137 let mut data = CallbackData { counter: 0 };
138 _Unwind_Backtrace(callback, &mut data as *mut _ as _);
139}
140
141#[cfg(target_arch = "loongarch64")]
143pub fn catch_unwind<R, F: FnOnce() -> R>(
144 f: F,
145) -> Result<R, alloc::boxed::Box<dyn core::any::Any + Send>> {
146 Ok(f())
148}
149
150#[cfg(target_arch = "loongarch64")]
152pub fn begin_panic<R>(_: alloc::boxed::Box<R>) {
153 }
155
156#[cfg(target_arch = "loongarch64")]
158pub fn print_stack_trace() {
159 early_println!("Printing stack trace:");
161}