1use crate::early_println;
6
7extern crate cfg_if;
8extern crate gimli;
9
10#[linkage = "weak"]
15#[unsafe(no_mangle)]
17pub fn __ostd_panic_handler(info: &core::panic::PanicInfo) -> ! {
18 let _irq_guard = crate::irq::disable_local();
19
20 crate::cpu_local_cell! {
21 static IN_PANIC: bool = false;
22 }
23
24 if IN_PANIC.load() {
25 early_println!("The panic handler panicked {:#?}", info);
26 abort();
27 }
28
29 IN_PANIC.store(true);
30
31 early_println!("Non-resettable panic! {:#?}", info);
32
33 print_stack_trace();
34 abort();
35}
36
37pub fn abort() -> ! {
41 crate::power::poweroff(crate::power::ExitCode::Failure);
45}
46
47#[cfg(not(target_arch = "loongarch64"))]
48pub use unwinding::panic::{begin_panic, catch_unwind};
49
50#[cfg(not(target_arch = "loongarch64"))]
54pub fn print_stack_trace() {
55 use core::ffi::c_void;
56
57 use gimli::Register;
58 use unwinding::abi::{
59 _Unwind_Backtrace, _Unwind_FindEnclosingFunction, _Unwind_GetGR, _Unwind_GetIP,
60 UnwindContext, UnwindReasonCode,
61 };
62
63 use crate::{early_print, sync::SpinLock};
64
65 static BACKTRACE_PRINT_LOCK: SpinLock<()> = SpinLock::new(());
68 let _lock = BACKTRACE_PRINT_LOCK.lock();
69
70 early_println!("Printing stack trace:");
71
72 struct CallbackData {
73 counter: usize,
74 }
75 extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
76 let data = unsafe { &mut *(arg as *mut CallbackData) };
77 data.counter += 1;
78 let pc = _Unwind_GetIP(unwind_ctx);
79 if pc > 0 {
80 let fde_initial_address = _Unwind_FindEnclosingFunction(pc as *mut c_void) as usize;
81 early_println!(
82 "{:4}: fn {:#18x} - pc {:#18x} / registers:",
83 data.counter,
84 fde_initial_address,
85 pc,
86 );
87 }
88 for i in 0..8u16 {
91 let reg_i = _Unwind_GetGR(unwind_ctx, i as i32);
92 cfg_if::cfg_if! {
93 if #[cfg(target_arch = "x86_64")] {
94 let reg_name = gimli::X86_64::register_name(Register(i)).unwrap_or("unknown");
95 } else if #[cfg(target_arch = "riscv64")] {
96 let reg_name = gimli::RiscV::register_name(Register(i)).unwrap_or("unknown");
97 } else if #[cfg(target_arch = "aarch64")] {
98 let reg_name = gimli::AArch64::register_name(Register(i)).unwrap_or("unknown");
99 } else {
100 let reg_name = "unknown";
101 }
102 }
103 if i.is_multiple_of(4) {
104 early_print!("\n ");
105 }
106 early_print!(" {} {:#18x};", reg_name, reg_i);
107 }
108 early_print!("\n\n");
109 UnwindReasonCode::NO_REASON
110 }
111
112 let mut data = CallbackData { counter: 0 };
113 _Unwind_Backtrace(callback, &mut data as *mut _ as _);
114}
115
116#[cfg(target_arch = "loongarch64")]
118pub fn catch_unwind<R, F: FnOnce() -> R>(
119 f: F,
120) -> Result<R, alloc::boxed::Box<dyn core::any::Any + Send>> {
121 Ok(f())
123}
124
125#[cfg(target_arch = "loongarch64")]
127pub fn begin_panic<R>(_: alloc::boxed::Box<R>) {
128 }
130
131#[cfg(target_arch = "loongarch64")]
133pub fn print_stack_trace() {
134 early_println!("Printing stack trace:");
136}